Nhibernate-查询与Linq的一对多关系

Nhibernate-查询与Linq的一对多关系,nhibernate,fluent-nhibernate,linq-to-nhibernate,Nhibernate,Fluent Nhibernate,Linq To Nhibernate,我想查询实体上的一对多关系。为了帮助进一步解释我的问题,假设我的应用程序具有以下实体: public class User { public virtual int UserID { get; set; } public virtual Membership CurrentMembership { get { return Membership.Single(m => m.IsValid); } } public virtual ILis

我想查询实体上的一对多关系。为了帮助进一步解释我的问题,假设我的应用程序具有以下实体:

public class User {
    public virtual int UserID { get; set; }

    public virtual Membership CurrentMembership {
        get { return Membership.Single(m => m.IsValid); }
    }

    public virtual IList<Membership> Membership { get; private set; }

    public User() {
        Membership = new List<Membership>();
    }
}

public class Membership {
    public virtual int MembershipID { get; set; }
    public virtual User User { get; set; }
    public virtual DateTime StartDate { get; set; }
    public virtual DateTime? EndDate { get; set; }
    public virtual int DaysLeft { get; set; }
    public virtual bool IsValid { get; set; }

    public Membership() {
    }
}
公共类用户{
公共虚拟int用户标识{get;set;}
公共虚拟会员资格{
获取{return Membership.Single(m=>m.IsValid);}
}
公共虚拟IList成员身份{get;private set;}
公共用户(){
成员资格=新列表();
}
}
公共班级成员资格{
公共虚拟int成员身份ID{get;set;}
公共虚拟用户用户{get;set;}
公共虚拟日期时间起始日期{get;set;}
公共虚拟日期时间?EndDate{get;set;}
公共虚拟整数DaysLeft{get;set;}
公共虚拟bool有效{get;set;}
公众会员资格(){
}
}
对于以下流畅的映射(映射有点不相关,我在这里只是为了指导):

公共类用户映射:类映射{
公共用户映射(){
表(“用户”);
Id(x=>x.UserID);
HasMany(x=>x.Membership)
.KeyColumn(“用户ID”)
.Inverse()
.Cascade.All();
}
}
公共类成员关系映射:类映射{
公共成员资格映射(){
表(“成员资格”);
Id(x=>x.MembershipID);
参考文献(x=>x.User);
Map(x=>x.StartDate);
映射(x=>x.DaysLeft)
.Formula(“当EndDate不为NULL且dbo.DayDiff(GETUTCDATE(),EndDate)>0时,则dbo.DayDiff(GETUTCDATE(),EndDate)为0 END”);
//DayDiff是一个udf,它获取两个日期之间的天数
映射(x=>x.IsValid)
.Formula(“dbo.GetValidMembershipID(UserID)=MembershipID然后为1或0结束时的情况”);
//GetValidMembershipID是一个udf,用于计算此用户的有效成员身份id
}
}
正如您所看到的,一个用户可以拥有许多成员资格。CurrentMembership(针对用户的属性)返回IsValid属性为true的针对用户的成员资格(这仅适用于针对该用户的单个成员资格)

现在,我想能够抓住所有用户谁的当前会员资格不到20天剩余

我的第一次尝试是说:

session.Linq<User>().Where(u => u.CurrentMembership.DaysLeft < 20).ToList();
session.Linq().Where(u=>u.CurrentMembership.DaysLeft<20.ToList();
但这带来了一个错误:

“无法解析:用户的属性:CurrentMembership”

这是意料之中的,因为我没有对此属性使用公式映射(就像我对DaysLeft和IsValid属性针对成员身份所做的那样)。除了映射字符串、整数和布尔,我看不出如何使用公式映射。接下来我试着说:

session.Linq<User>().Where(u => u.Membership.Single(m => m.IsValid).DaysLeft < 20).ToList();
session.Linq().Where(u=>u.Membership.Single(m=>m.IsValid).DaysLeft<20.ToList();
但这带来了一个错误:

“对象引用未设置为对象的实例。”

我知道我可以直接查询这个会员资格,但我在很多地方都用过这个例子。有谁能推荐一种映射CurrentMembership属性的替代方法,它允许我用Linq查询它。请注意,我需要最佳性能,因此转换为列表并在内存中工作是不够的


我很感激你的帮助。感谢您将NHibernateContrib中的旧LINQ提供程序用于NHibernate2.1。 此提供程序不再受支持,也没有任何活动

NHibernate 3.0语法中内置的LINQ提供程序是
session.Query()
,而不是
session.LINQ()

现在NHibernate3.0是最终版本,所以,如果您在过去遇到过问题,它们可能已经解决了。我将这两种方法都用于繁重的查询,新方法满足很多场景。
也许最好的办法是获取最新的中继源并使用它

我强烈建议你用NHibenrate 3.0替换你的东西。它“几乎”100%向后兼容NHibernate 2.1,您只需将所有
session.Linq()
更改为
session.Query()

如果仍然不起作用,您可以尝试
u.Membership.Any(…)
u.Membership.First(…)
而不是
u.Membership.Single(…)
where
条件下

如果这仍然不起作用,请尝试反转查询。查询
Membership
并选择
Membership.User


CurrentMembership
将无法工作,因为它未映射。

新的Linq提供程序是垃圾。有很多问题,最大的问题是我不能在跳过/执行之前调用Fetch。在解决这些问题之前,我无法升级。您尝试过QueryOver API吗?这是NH3.0的默认API。与LINQ非常相似,但具有CriteriaAPI的大部分特性(它是围绕它的包装器)。不幸的是,老林克毫无疑问是一条死胡同。任何限制都不会被修正。QueryOver看起来很有希望,但我喜欢Linq的灵活性。如果将来我希望将我的应用程序升级到实体框架,那么这应该是trivual。现在我决定继续使用旧的提供者,但我正在编写一系列单元测试,因此如果我真的计划升级到NHibernate 3或实体框架,应该不会有什么痛苦。
session.Linq<User>().Where(u => u.Membership.Single(m => m.IsValid).DaysLeft < 20).ToList();