使用nhibernate ResultTransformer

时间:2012-01-02 10:53:55

标签: nhibernate fluent-nhibernate

我在我的MVC项目中使用Nhibernate最后一个版本

我想对对象类型名称“Person”进行查询,但person有许多属性。在我的一个查询中,我最好不要拥有大部分这些属性。 这是人:

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

}

可以吗?它可以更加个性化吗?我是否正确使用它?

它似乎有一个很大的问题:它获取所有人的名字和姓氏,然后从中选择,姓氏为“nadal”,并且表现并不好

3 个答案:

答案 0 :(得分: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;
    }
}

答案 1 :(得分:0)

您使用Session.CreateCriteria<T>()但不Find。因此,查询在没有条件的情况下执行,然后进行转换和过滤。

你必须找到一种方法,以Nhibernate的ICriteria可以处理的方式将你的规范添加到{{1}}方法,或者使用Linq to Nhibernate(但要注意一些问题!)。

答案 2 :(得分:0)

我可能错了 - 但我认为你过度了。

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