是否有可能nhibernate将查询作为IDictionary而不是实体类返回?

时间:2010-09-03 17:48:56

标签: nhibernate fluent-nhibernate

我有一个实体人:

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"];

如果不添加不同的映射,是否可以这样做?

6 个答案:

答案 0 :(得分:12)

您需要定义自己的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
}

答案 1 :(得分:2)

session.CreateCriteria<Person>()
.SetResultTransformer(NHibernate.Transform.Transformers.AliasToEntityMap) 
.List<Hashtable>();

这样的事情?

答案 2 :(得分:2)

您不需要DictionaryResultTransformer 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<T>。当然,您可以稍微更改一下并返回一个集合;只需拨打UniqueResult<T>而不是{{1}}。

答案 3 :(得分:1)

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

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;
}

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

答案 4 :(得分:0)

看看这篇博文:

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 上进行谷歌搜索,该搜索仅适用于此,将结果转换为其他对象或集合。包括IDictionnary。

答案 5 :(得分:0)

您可以通过执行客户端linq投影来执行此操作,请参阅Diego对this post的回答。