我现在一直在使用Nhibernate和LINQ,我有一些问题。假设我有以下实体:
public class User
{
public virtual int UserID { get; set; }
public virtual bool IsActive { get; set; }
public virtual bool SomeField { get { return 0; } }
public virtual DateTime DateRegistered { get; set; }
public virtual IList<Membership> Membership { get; set; }
public virtual Membership ValidMembership { get { return Membership.FirstOrDefault(m => m.IsValid); } }
}
public class User2
{
public virtual int UserID { get; set; }
public virtual int MembershipID { get; set; }
}
public class Membership
{
public virtual int MembershipID { get; set; }
public virtual bool IsValid { get; set; }
}
现在,如果我运行以下查询:
var users = service.Linq<User>()
.Where(u => u.IsActive) // This would work
.Where(u => u.SomeField > 0) // This would fail (i know i can map these using formulas but this is here to illustrate)
.Where(u => u.Membership.Any(m => m.IsValid)) // This would work
.Where(u => u.ValidMembership != null) // This would fail
.Where(u => u.DateRegistered > DateTime.UtcNow.AddDays(-1)) // This would work
.Where(u => u.DateRegistered.AddDays(1) > DateTime.UtcNow) // This would fail
.Select(u => new User2 { UserID = u.UserID }) // This would work
.Select(u => u.UserID) // This would work
.Select(u => new { UserID = u.UserID }) // This would fail
.Select(u => new User2 { UserID = u.UserID, MembershipID = u.Membership.Any(m => m.IsValid) ? u.Membership.Any(m => m.IsValid).First().MembershipID : 0 }); // This would fail
我在每个旁边添加了一条评论,表明它们是否会起作用或失败。这些是我现在能想到的情景。我已经设法通过将数据转换为列表来解决这些问题,然后才能做任何过于花哨的事情。这显然会对性能产生影响。我想知道NHibernate的LINQ提供程序的未来版本是否会支持这些?也有人知道实体框架将如何处理这些场景。我认为实体框架会有所改进,但如果存在同样的问题我不想跳船。
感谢您的反馈。感谢
答案 0 :(得分:3)
NHibernate 3支持的构造比你正在使用的contrib提供程序更多(Beta1刚刚发布,最终版本预计在今年年底之前)
然而,正如其他人指出的那样,一些构造很难(或不可能)解析,而其他构造需要非常特定的代码才能将表达式树转换为SQL。
幸运的是,新的提供程序也是可扩展的,这意味着您可以为自己的方法添加自己的数据库逻辑,或者不支持开箱即用的方法。
答案 1 :(得分:1)
这段代码甚至不应该编译。 User.SomeField是一个布尔属性,但你试图从getter返回0? SomeField和ValidMemberships甚至不是虚拟的,因为它们是甚至不能由NHibernate管理的字段。
答案 2 :(得分:1)
这是对Diego Mijelshon的回答的补充
当前的Linq提供程序中实现了一些甚至所有未实现的问题。
其中(u =&gt; u.SomeField&gt; 0)//计算属性SomeField
其中(u =&gt; u.ValidMembership!= null)//计算属性ValidMembership
其中(u =&gt; u.DateRegistered.AddDays(1)&gt; DateTime.UtcNow)//日期比较运算符的这一方法没有实现DateTime.AddDays方法大于&gt;
选择(u =&gt; new {UserID = u.UserID}) //未实现创建匿名对象
选择(u =&gt;新用户2 {UserID = u.UserID,MembershipID = u.Membership.Any(m =&gt; m.IsValid)?u.Membership.Any(m =&gt; m.IsValid)。 First()。MembershipID:0}); //三元运算符未实现
答案 3 :(得分:0)
实体框架将在与NHibernate相同的情况下失败(至少对于您的示例)。请记住,Linq使用延迟加载进行Where() - 操作 - 以及Linq2SQL中的所有内容(包括实体框架)和Linq2NHibernate需要在deferred loading中转换为SQL。方法调用无法转换为SQL - SQL中没有方法的表示 - 这就是它失败的原因。
当您使用ToList()时 - 强制先前的Linq语句进行评估(到数据库调用),然后向前工作,您正在进行内存中的表示,允许您使用完整的Linq2Object表达式树(有可能花哨的方法调用等。)
至于你的预测 - 我不会将Linq2NHibernate用于那些 - 而是使用内置于'标准'NHibernate中的Projections。