NHibernate + LINQ - 与相关集合一起高效工作

时间:2013-12-01 21:25:31

标签: c# linq nhibernate fluent-nhibernate linq-to-nhibernate

我对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的“类型”过滤器,计数完成客户端) related

而这一个:

s.Query<PersonalDocument>().Count(x => x.Owner == personInstance && x.Type == "xx");

转换为一个不错的SQL:

enter image description here

有没有办法像第一个那样编写DRY LINQ查询,但是得到的SQL最优于第二个?

2 个答案:

答案 0 :(得分:2)

答案 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/