NHibernate IQueryable属性

时间:2015-01-22 11:12:25

标签: nhibernate iqueryable

我有一些代码:

public class Hippo
{
    public virtual int Id { get; set; }
    public virtual string Name {get;set;}
}
public class Zoo
{
    public virtual int Id { get; set; }
    public virtual IQueryable<Hippo> Hippos { get; set; } 
}

我可以在NHibernate中创建Hippos(或者流利的nhibernate)吗? 或者我可以将会话传递给此对象吗?

我怎么做? (在NHibernage.Linq或NHibernate.CollectionQuery的帮助下?)

我的目标是这样的:

_session.Query<Zoo>().Where(e => e.Hippos.Where(h=>h.Name=="Bobby").Any())

1 个答案:

答案 0 :(得分:1)

当您通过session.Query<>定义查询时,它看起来像是访问了集合,但事实并非如此。它只是在生成的Expression中被引用,它被转换为sql。因此查询页面会将限制转发到数据库,因此只会提取少量记录。例如,以下查询将仅返回50只河马:

const int pagesize = 50;
_session.Query<Zoo>()
    .SelectMany(e => e.Hippos)
        .Where(h => h.Name=="Bobby")
    .Skip(pageindex * pagesize).Take(pagesize)
    .OrderBy(h => h.Id)
    .ToList<Hippo>();

在查询像someZoo.Hippos.Where(h=>h.Name=="Bobby").ToList()这样的集合时,请不要混淆。这将触发延迟加载并获取动物园的所有河马。所以在DomainModel上收集可能包含大量项目的集合是一个坏主意。有人会在代码中使用它,并且在使用小数据集进行开发时不会崩溃。如果可能,最好只使用反向引用somehippo.ContainingZoo并查询

const int pagesize = 50;
_session.Query<Hippo>()
    .Where(h => h.Name=="Bobby")
    .Skip(pageindex * pagesize).Take(pagesize)
    .OrderBy(h => h.Id)
    .ToList<Hippo>();

<强>更新

可查询属性的实验代码。不漂亮但可用

class ZooMap : ClassMap<Zoo>
{
    public ZooMap()
    {
        ...

        Map(x => x.Hippos)
            .CustomType<QueryableHipposUserType>()
            .Formula("1")
            .ReadOnly();
    }
}

class QueryableHipposUserType : ICompositeUserType
{
    public object Assemble(object cached, ISessionImplementor session, object owner)
    {
        return cached;
    }

    public object DeepCopy(object value)
    {
        return value;
    }

    public object Disassemble(object value, ISessionImplementor session)
    {
        return value;
    }

    public bool Equals(object x, object y)
    {
        return true;
    }

    public int GetHashCode(object x)
    {
        return 0;
    }

    public object GetPropertyValue(object component, int property)
    {
        return null;
    }

    public bool IsMutable
    {
        get { return false; ; }
    }

    public object NullSafeGet(IDataReader dr, string[] names, ISessionImplementor session, object owner)
    {
        var zooId = ((Zoo)owner).Id;
        return ((NHibernate.ISession)session).Query<Hippo>().Where(hippo => hippo.ContainingZoo.Id == zooId);
    }

    public void NullSafeSet(IDbCommand cmd, object value, int index, bool[] settable, ISessionImplementor session)
    {
    }

    public string[] PropertyNames
    {
        get { return new string[0]; }
    }

    public IType[] PropertyTypes
    {
        get { return new IType[]{ NHibernateUtil.Int32 }; }
    }

    public object Replace(object original, object target, ISessionImplementor session, object owner)
    {
        return original;
    }

    public Type ReturnedClass
    {
        get { return typeof(IQueryable<Hippo>); }
    }

    public void SetPropertyValue(object component, int property, object value)
    {
    }
}

var someZoo = session.Get<Zoo>(zooId);
var theHappyHippos = someZoo.Hippos.Where(h => h.Name=="Bobby").ToList();