2012-01-02 67 views
0

我使用NHibernate的最后一个版本在我的MVC项目使用NHibernate的使用ResultTransformer

我想做出一个对象类型名称“人”的查询,但人有许多特性。在我的一个问题中,我最好不要拥有大部分这些属性。 这里是人:

public partial class Person 
{ 
    virtual public User User { get; set; } 
    virtual public string FirstName { get; set; } 
    virtual public string LastName { get; set; } 
    virtual public int Gender { get; set; } 
    virtual public Contact Contact { get; set; } 
    virtual public BirthCertificate PersonBirthCertificate { get; set; } 
} 

在查询我只想名字和人的姓氏。

所以我决定用使用ResultTransformer和实现它是这样的:

public class PersonResultTransformer : IResultTransformer 
{ 
    private Type result; 
    private PropertyInfo[] properties; 

    #region IResultTransformer Members 

    public IList TransformList(IList collection) 
    { 
     return collection; 
    } 
    public PersonResultTransformer (Type result, params string[] names) 
    { 
     this.result = result; 
     List<PropertyInfo> props = new List<PropertyInfo>(); 
     foreach (string name in names) 
     { 
      props.Add(result.GetProperty(name)); 
     } 
     properties = props.ToArray(); 
    } 

    public object TransformTuple(object[] tuple, string[] aliases) 
    { 
     object instance = Activator.CreateInstance(result); 
     for (int i = 0; i < tuple.Length; i++) 
     { 
      var t = properties[i].Name; 

      var value = tuple[i].GetType().GetProperty(t).GetValue(tuple[i], null); 
      instance.GetType().GetProperty(t).SetValue(instance, value, null); 
     } 
     return instance; 
    } 

    #endregion 
} 

,并为获得要我要与LINQ查询:

var person = Repository<Person>.Find(p => p.LastName.Equals("Nadal") 
    , new PersonResultTransformer (typeof(Person), "FirstName", "LastName")); 

//////////////// 

public IQueryable<T> Find(Expression<Func<T, bool>> expression, IResultTransformer transformer) 
{ 
    return Session.CreateCriteria<T>().SetResultTransformer(transformer).List<T>() 
     .AsQueryable().Where(expression); 

} 

,可以吗?它可以更定制?我是否正确使用它?

看来,它有一个很大的问题:它得到所有人的姓氏和名字,然后从中选择,那些姓氏=“纳达尔”,而且性能也不好

回答

0

你使用Session.CreateCriteria<T>()但你不要add any criteria它。所以,查询在没有标准的情况下执行,然后进行转换和过滤。

您必须找到一种方法,以Nhibernate的ICriteria可以处理的方式将您的规范添加到Find方法,或者使用Linq到Nhibernate(尽管注意一些问题!)。

+0

没有使用创建标准,而只是使用查找扩展库仑我做到了吗? – Adrakadabra 2012-01-02 13:24:41

+0

我怎么能用linq来做到休眠? – Adrakadabra 2012-01-02 13:41:46

+0

Linq到Nhibernate是Nhibernate源自(我认为)3.2以来的一部分,因此它已经可以使用了。在StackOverflow上有很多关于它的帖子,你可以看看[这里](http://nhforge.org/blogs/nhibernate/archive/2009/12/16/using-the-new-linq-to-nh-提供商和迁移 - 从最老one.aspx)。 – 2012-01-03 08:41:48

0

我可能是错的 - 但我认为你是过度的这个。

您可以更轻松地使用延迟加载来不提取您不需要的属性。

+0

它只是一个样本,我想知道如果我的使用结果变换是好的或不,我知道我可以使用懒性质 – Adrakadabra 2012-01-02 13:18:39

3

首先你要委托给其理解表达

using NHibernate.Linq; 

public IQueryable<T> Find(Expression<Func<T, bool>> expression) 
{ 
    return Session.Query<T>().Where(expression); 
} 

那么你可以

var personDTOs = Repository<Person>.Find(p => p.LastName.Equals("Nadal")) 
    .Select(person => new { person.FirstName, person.LastName }); 

可以缩短使用ResultTransformer大量的查询,但你不能用Linq2NHibernate使用它。

public class PersonResultTransformer : IResultTransformer 
{ 
    private Type result; 
    private List<PropertyInfo> properties = new List<PropertyInfo>(); 

    public IList TransformList(IList collection) 
    { 
     return collection; 
    } 
    public PersonResultTransformer (Type result, params string[] names) 
    { 
     this.result = result; 
     foreach (string name in names) 
     { 
      properties.Add(result.GetProperty(name)); 
     } 
    } 

    public object TransformTuple(object[] tuple, string[] aliases) 
    { 
     object instance = Activator.CreateInstance(result); 
     for (int i = 0; i < tuple.Length; i++) 
     { 
      properties[i].SetValue(instance, tuple[i], null); 
     } 
     return instance; 
    } 
} 
+0

我知道这是一个解决方案,但我想使用结果转换器,认为我想学习如何使用它,但我很困惑,如果它可能告诉我如何使用linq来做到这一点,使用结果变换器 – Adrakadabra 2012-01-03 04:55:04

+0

有没有什么办法像:Session.Query ().Where(expression).. SetResultTransformer(变压器)? – Adrakadabra 2012-01-03 12:25:02

+2

只要按照建议投影到PersonDTO对象中,只会导致这两个属性返回。另一个选择可能是更改映射,以便Person对象由多个值类型组成,将这些值类型标记为延迟加载,然后包含提示以强制它们返回查询。如果您的目标是要了解如何以及如何使用ResultTransformers,这可能不是一个好例子。 – JeffreyABecker 2012-01-03 17:24:48