asp.net 使用NHibernate将SQL查询转换为Datatable并从Datatable获取列标题

t5fffqht  于 2023-02-26  发布在  .NET
关注(0)|答案(3)|浏览(146)

我尝试在C# .Net中使用NHibernate将Sql查询转换为数据表
下面是查询示例。查询可以很复杂,可以包含任意数量的列。SELECT EMAIL ,ID ,[NAME] FROM TestTable
我正在使用C#中的以下代码

using (ISession session = sessionFactory.OpenSession())
{
    // Create a new SQL query object
    SQLQuery query = session.CreateSQLQuery(sqlQuery);

    // Set the transformer to return the result as a list of dictionaries
    query.SetResultTransformer(Transformers.AliasToEntityMap);

    // Execute the query and convert the result to a DataTable
    DataTable dataTable = new DataTable();

    // Get the column names from the keys of the first dictionary in the result list
    IList<IDictionary<string, object>> result = query.List<IDictionary<string, object>>();
    if (result.Count > 0)
    {
        foreach (string columnName in result[0].Keys)
        {
            DataColumn column = new DataColumn(columnName);
            dataTable.Columns.Add(column);
        }
    }

    // Add rows to the DataTable based on the result list
    foreach (IDictionary<string, object> row in result)
    {
        var values = new object[row.Count];
        int index = 0;

        foreach (object item in row.Values)
        {
            values[index++] = item;
        }

        dataTable.Rows.Add(values);
    }
}

现在的问题是,我能够得到列只有当查询有一个结果。但如果查询返回0结果比我想不能得到列标题。
我想列标题在任何情况下,如果结果是返回或不从查询,使用NHibernate。我的NHibernate版本是3.3.1.4000

qzlgjiam

qzlgjiam1#

我不太明白你到底在找什么但如果您需要实体属性名称和数据库列名称,以下内容可能会有所帮助:

internal static Dictionary<string, string> GetPropertyColumnDictionary(this ISessionFactory sessionFactory, object instance)
{
    Type type = instance.GetType();
    var metaData = sessionFactory.GetClassMetadata(type.ToString());
    var persister = (AbstractEntityPersister)metaData;
    var dictionary = new Dictionary<string, string>();
    string entityIdentifier = metaData.IdentifierPropertyName;
    string databaseIdentifier = persister.KeyColumnNames[0];
    dictionary.Add(entityIdentifier, databaseIdentifier);

    var fieldInfo = typeof(AbstractEntityPersister)
        .GetField("subclassPropertyColumnNames", BindingFlags.NonPublic | BindingFlags.Instance);

    var pairs = (Dictionary<string, string[]>)fieldInfo.GetValue(persister);

    foreach(var pair in pairs)
    {
        if(pair.Value.Length > 0)
        {
            if(pair.Value[0] == databaseIdentifier)
                break;
            dictionary.Add(pair.Key, pair.Value[0]);
        }
    }
    return dictionary;
}

在上面的代码中,参数sessionFactorySessionFactory的示例,instance是实体的示例。

k97glaaz

k97glaaz2#

据我所知,它不应该绑定到一个实体,它应该是通用的,因为不知道背后的数据库。最好的选择,我看到的是诉诸ADO.Net

var command = session.Connection.CreateCommand();
command.CommandText = sql;
using (var reader = command.ExecuteReader())
{
    var table = new DataTable();
    table.Load(reader);
    return table;
}
cxfofazt

cxfofazt3#

问题还不清楚-- NHibernate是一个ORM,而不是数据库驱动程序。它用于将关系结果Map到对象。检索数据表或行的原始结果是ADO .NET的工作。NHibernate本身使用ADO .NET底层执行查询和读取结果。

使用SqlBulkCopy中的对象

如果实际问题是如何使用SqlBulkCopy中的数据,那么最好使用FastMember的ObjectReadeer将对象 Package 在IDataReader接口中,而不是将其转换为DataTable:

using(var bcp = new SqlBulkCopy(connection)) 
using(var reader = ObjectReader.Create(data)) 
{ 
  bcp.DestinationTableName = "SomeTable"; 
  bcp.WriteToServer(reader); 
}

如果对象仅用于大容量导入,则更好的选择是直接使用ADO .NET加载数据并将DatReader传递给SqlBulkCopy。这样,内存中不会缓存任何数据,所有数据都将直接从源发送到目标:

using var sourceCon=new SqlConnection(source_cns);
using var command = new SqlCommand(sqlQuery,sourceCon);
using var reader=command.ExecuteReader();

using var targetCon=new SqlConnection(target_cns);
using var bcp = new SqlBulkCopy(targetCon);
bcp.DestinationTableName = "SomeTable"; 
bcp.WriteToServer(reader);

将数据读入数据表

如果您真的想执行原始SQL并获得DataTable,只需编写如下代码:

using var con=new SqlConnection(connection_string);
using var command = new SqlCommand(sqlQuery,con);
using var reader=command.ExecuteReader();
var table=new DataTable();
table.Load(reader);
return table;

连接或连接字符串可能来自NHibernate。但这仍然是一个ADO .NET连接:

var command = session.Connection.CreateCommand();
command.CommandText = sqlQuery;
...

另一种选择是使用NHibernate加载对象,然后使用MoreLINQ的ToDataTable将对象列表转换为DataTable。不过这相当浪费,因为ADO .NET加载结果时,NH将其转换为对象,然后ToDataTable()将其转换为DataTable。这至少使用其他选项两倍的内存。

var table=someObjects.ToDataTable();

相关问题