【问题标题】:Is it possible for nhibernate to return a query as an IDictionary instead of an entity class?nhibernate 是否可以将查询作为 IDictionary 而不是实体类返回?
【发布时间】:2018-02-16 06:15:43
【问题描述】:

我有一个实体人:

public class Person
{
   public virtual int Id {get; set; }
   public virtual string FirstName { get; set; }
   public virtual string MiddleName { get; set; }
   public virtual string LastName { get; set; }
}

使用映射:

public class PersonMap
{
   public PersonMap()
   {
       Table(TABLE_NAME); 
       Id( x => x.Id);
       Map(x => x.FirstName).Not.Nullable();
       Map(x => x.LastName).Not.Nullable();
       Map(x => x.MiddleName).Not.Nullable();
    }
}

在某些情况下,我希望 Nhibernate 返回字典而不是实体:

IDictionary<string,string> person = session.Get(id);//????
string firstName = person["FirstName"];

这是否可以在不添加不同映射的情况下实现?

【问题讨论】:

    标签: nhibernate fluent-nhibernate


    【解决方案1】:

    您需要定义自己的 ResultTransformer 实现,以使其按您需要的方式工作。下面是一个参考实现,您可以根据需要进行调整。完全缺乏错误检查等;所以谨慎使用;)

    using System;
    using System.Collections;
    using NHibernate;
    using NHibernate.Properties;
    using NHibernate.Transform;
    
    
    [Serializable]
    public class DictionaryResultTransformer : IResultTransformer
    {
    
            public DictionaryResultTransformer()
            {
    
            }
    
            #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
    }
    

    【讨论】:

    • 非常干净的解决方案。太棒了!
    • 如何从查询中使用它?可以显示使用情况吗?
    • @emirhosseini - 用法类似于: session.CreateSQLQuery("select p.Name, p.Price, p.ProductId from Product p").SetResultTransformer(new DictionaryResultTransformer()).List>();
    【解决方案2】:
    session.CreateCriteria<Person>()
    .SetResultTransformer(NHibernate.Transform.Transformers.AliasToEntityMap) 
    .List<Hashtable>();
    

    这样的?

    【讨论】:

    • 这与我想做的非常接近。问题在于每个哈希表中都有一个键值对,其中 person 对象是值。我正在尝试获取一个将每个属性作为键值对的哈希表。
    【解决方案3】:

    您不需要 DictionaryResultTransformer 那样 DanP posted. AliasToEntityMapTransformer 做同样的事情,尽管它们都不会单独工作。你会得到一个实体字典。

    我发现的唯一方法是单独投影每个属性。但是,您不想 手动执行此操作,因为每当您更改映射时它都会中断。解决方案是这样的:

    var criteria = DetachedCriteria.For<Person>();
    criteria.Add(Restrictions.Eq("Id", id));
    var projectionList = Projections.ProjectionList();
    var metadata = session.SessionFactory.GetClassMetadata(typeof(Person));
    foreach (var name in metadata.PropertyNames)
    {
        projectionList.Add(Projections.Property(name), name);
    }
    criteria
        .SetProjection(projectionList)
        .SetResultTransformer(Transformers.AliasToEntityMap);
    var result = criteria.GetExecutableCriteria(session)
        .UniqueResult<IDictionary>()
    

    在上面的示例中,我使用查询来模拟Get。当然,您可以稍微更改一下并返回一个集合;只需调用List&lt;T&gt; 而不是UniqueResult&lt;T&gt;

    【讨论】:

      【解决方案4】:

      不,但您可以通过将逻辑封装在存储库方法中轻松实现。

      public IDictionary<string, string> GetPersonDictionary(int id)
      {
          var person = session.Get<Person>(id);
          var dict = new Dictionary<string, string>();
          dict.Add("FirstName", person.FirstName);
          /// etc.
          return dict;
      }
      

      您也可以使用反射来填充字典。

      【讨论】:

        【解决方案5】:

        看看这篇博文:

        http://sdesmedt.wordpress.com/2006/09/04/nhibernate-part-4-mapping-techniques-for-aggregation-one-to-many-mapping/

        如果您想要一个具体的示例,请查看这个不错的教程的示例。查看不是实体且具有自定义映射逻辑的摘要:

        http://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx

        或在 SetResultTransformer 上进行谷歌搜索,该搜索仅适用于此,将结果转换为另一个对象或集合。包括字典。

        【讨论】:

        • 你能提供一个使用结果转换器来填充字典的例子吗?我认为不编写自定义 IResultTransformer 是不可能的。
        • 是的,您必须编写代码。编写干净的代码有时需要更多的努力。
        【解决方案6】:

        您可以通过执行客户端 linq 投影来做到这一点,请参阅 Diego 对 this post 的回答。

        【讨论】:

        • 这与我想要做的很接近;但是,我认为不可能使用投影来为列名及其值创建 KeyValuePair。
        • @Maudite:好吧..我明白你的意思了..让我用一个示例结果转换器 impl 发布一个新答案。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-12-29
        • 1970-01-01
        • 2011-01-28
        • 2011-03-09
        相关资源
        最近更新 更多