上下文
我正在创建一个Web应用程序,它的一个功能是允许通过UI进行数据库查询。为了持久,它使用nHibernate ORM。下面是处理传入SQL查询的存储库方法:
public IList ExecuteSqlQuery(string sqlQuery)
{
var query = Session.CreateSQLQuery(sqlQuery);
var queryResult = query.SetResultTransformer(Transformers.AliasToEntityMap).List();
return queryResult;
}
问题
上述方法将返回一个词典列表,每个词典都包含 DictionaryEntry 对象,这些对象具有键 = ColumnName 和值 = < EM> ColumnValue 。
除了列名与原始SQL查询中指定的顺序不同之外,这一切都很好。例如,以下SQL查询:
select FirstName, LastName, c.Name
from SoftwareDeveloper sf
join Certification c on sf.SoftwareDeveloperId = c.SoftwareDeveloperId
,每行返回类似:
["FirstName"] = "John"
["Name"] = "70-515 MCTS, .NET Framework 4, Web Applications"
["LastName"] = "Doe"
请注意,不保留列的顺序。它应该是:
["FirstName"] = "John"
["LastName"] = "Doe"
["Name"] = "70-515 MCTS, .NET Framework 4, Web Applications"
更新 在上面的示例中,字典的键按名称排序,但这仅适用于此示例,故意保持简单。对于较大的查询,键(=列)不是有序的。
问题
在此上下文(nHibernate / CreateSQLQuery)中,如何保留原始查询中指定的列顺序?
更新#2
的解决方案
通过创建IResultTransformer的以下自定义实现来解决:
public class DictionaryResultTransformer : IResultTransformer
{
#region IResultTransformer Members
public IList TransformList(IList collection)
{
return collection;
}
public object TransformTuple(object[] tuple, string[] aliases)
{
var result = new Dictionary<string, object>();
for (int i = 0; i < aliases.Length; i++)
{
result[aliases[i]] = tuple[i];
}
return result;
}
#endregion
}
在上面的代码中,别名是列名。
来源:
Is it possible for nhibernate to return a query as an IDictionary instead of an entity class?
https://github.com/nhibernate/nhibernate-core/blob/master/src/NHibernate/Transform/AliasToEntityMapResultTransformer.cs
答案 0 :(得分:2)
您不能将结果作为词典,因为这些不会定义任何键排序。因此,您必须将AliasToEntityMap的使用替换为构建保留排序的数据结构(实现IResultTransformer)。如果你给它一个内部从列名映射到列索引的比较器,SortedDictionary可能会起作用。
请注意,如果直接调用List()而不使用结果转换器,则应获得一个对象数组列表,其中元素的顺序遵循select子句中指定的顺序。