我对LINQ很新,但我已经知道IQueryable和IEnumerable之间的基本区别(即应用于第一个的条件可能由远程引擎执行,在我的情况下 - 转换为SQL)。 / p>
现在,我见过的所有NHibernate教程都使用IList<T>
作为相关集合。
我想知道是否有任何方法可以使用IQueryable
,因此过滤效率可能会很高。
不幸的是,如果我尝试使用IQueryable<T>
作为相关集合的属性类型,则会导致错误:
无法投射类型的对象 “NHibernate.Collection.Generic.PersistentGenericBag
1[....PersonalDocument]' to type 'System.Linq.IQueryable
因此,为了保持SQL端相关集合的过滤,我需要直接查询相关类型,提供“绑定”关系的额外条件。这是非常不方便的,我想避免这种情况(因为关系条件已经宣布......)
澄清一下:
我有两个模型,如下:
public partial class Person
{
public virtual int Id { get; set; }
// ....
public virtual IEnumerable<PersonalDocument> Documents { get; set; }
}
public class PersonalDocument
{
// ...
public virtual int Id { get; set; }
public virtual Person Owner { get; set; }
public virtual string Type { get; set; }
}
以及Person
的映射代码:
HasMany<DomainModel.PersonalDocument>(x => x.Documents)
.KeyColumn("Owner_Id")
.Inverse()
.Cascade.Delete()
.AsBag();
和查询代码
personInstance.Documents.Where(d => d.Type == "xx").Count()
正在被转换为非最佳SQL(没有应用于SQL的“类型”过滤器,计数完成客户端)
而这一个:
s.Query<PersonalDocument>().Count(x => x.Owner == personInstance && x.Type == "xx");
转换为一个不错的SQL:
有没有办法像第一个那样编写DRY LINQ查询,但是得到的SQL最优于第二个?
答案 0 :(得分:2)
NHibernate核心中没有这样的功能。
请参阅https://nhibernate.jira.com/browse/NH-2319和http://www.nuget.org/packages/NHibernate.CollectionQuery。
答案 1 :(得分:0)
使用IList / ISet / IDictionary!
您可以在Person类中为每种文档类型创建一个集合。在映射中,您可以执行以下操作:
HasMany(x => x.Documents)
.KeyColumn("Owner_Id")
.Inverse()
.Cascade.Delete()
.Where("Type=xx")
.AsBag();
我不喜欢这个解决方案。我也不喜欢你的Product类是如何偏爱的。如果我是你,我会尝试WHERE建议,一切正常后我会看看我的设计。
另请参阅NHibernate继承策略。实际上我认为这正是你想要的:
http://www.nhforge.org/doc/nh/en/#inheritance
http://ayende.com/blog/3941/nhibernate-mapping-inheritance
http://lostechies.com/jimmybogard/2008/08/27/strategies-and-discriminators-in-nhibernate/