使用nHibernate的CreateSQLQuery时如何保留列顺序?

Flo*_*eda 5 c# nhibernate fluent-nhibernate

上下文
我正在创建一个Web应用程序,其功能之一是允许通过UI进行数据库查询.为了持久,它使用nHibernate ORM.下面是处理传入SQL查询的存储库方法:

public IList ExecuteSqlQuery(string sqlQuery)
{
    var query = Session.CreateSQLQuery(sqlQuery);
    var queryResult = query.SetResultTransformer(Transformers.AliasToEntityMap).List();

    return queryResult;
}  
Run Code Online (Sandbox Code Playgroud)

问题
上面的方法将返回一个字典列表,每个字典都包含具有Key = ColumnNameValue = ColumnValue的DictionaryEntry对象.

除了列名与原始SQL查询中指定的顺序不同之外,这一切都很好.例如,以下SQL查询:

select FirstName, LastName, c.Name   
from SoftwareDeveloper sf  
join Certification c on  sf.SoftwareDeveloperId = c.SoftwareDeveloperId  
Run Code Online (Sandbox Code Playgroud)

,每行的返回类似于:

["FirstName"] = "John"
["Name"] = "70-515  MCTS, .NET Framework 4, Web Applications"
["LastName"] = "Doe"  
Run Code Online (Sandbox Code Playgroud)

请注意,不保留列的顺序.它应该是:

["FirstName"] = "John"  
["LastName"] = "Doe"  
["Name"] = "70-515  MCTS, .NET Framework 4, Web Applications"  
Run Code Online (Sandbox Code Playgroud)

更新 在上面的示例中,字典的键按名称排序,但这仅适用于此示例,故意保持简单.对于较大的查询,不对键(=列)进行排序.


在这个上下文中的问题(nHibernate/CreateSQLQuery),我如何保留原始查询中指定的列顺序?

UPDATE#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
}  
Run Code Online (Sandbox Code Playgroud)

在上面的代码中,别名是列名称.

来源:
nhibernate是否有可能将查询作为IDictionary而不是实体类返回?
https://github.com/nhibernate/nhibernate-core/blob/master/src/NHibernate/Transform/AliasToEntityMapResultTransformer.cs

Osk*_*ren 2

您不能将结果作为字典,因为它们没有定义任何键顺序。因此,您必须将 AliasToEntityMap 的使用替换为构建保留排序的数据结构的内容(实现 IResultTransformer)。如果您为 SortedDictionary 提供一个在内部从列名映射到列索引的比较器,它可能会起作用。

请注意,如果直接调用 List() 而不使用结果转换器,您应该获得一个对象数组列表,其中元素的顺序遵循 select 子句中指定的顺序。