我有一个实体人:
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"];
如果不添加不同的映射,是否可以这样做?
答案 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://www.codeproject.com/KB/architecture/NHibernateBestPractices.aspx
或者在 SetResultTransformer 上进行谷歌搜索,该搜索仅适用于此,将结果转换为其他对象或集合。包括IDictionnary。
答案 5 :(得分:0)
您可以通过执行客户端linq投影来执行此操作,请参阅Diego对this post的回答。