C# 作为根的属性的NHibernate IQueryable集合

C# 作为根的属性的NHibernate IQueryable集合,c#,nhibernate,fluent-nhibernate,domain-driven-design,C#,Nhibernate,Fluent Nhibernate,Domain Driven Design,我有一个根对象,它的属性是集合 例如: I have a Shelf object that has Books. // Now public class Shelf { public ICollection<Book> Books {get; set;} } // Want public class Shelf { public IQueryable<Book> Books {get;set;} } 我想让NHibernate专门执行该查询,而

我有一个根对象,它的属性是集合

例如:

I have a Shelf object that has Books.

// Now
public class Shelf 
{
    public ICollection<Book> Books {get; set;}
}

// Want 
public class Shelf 
{
   public IQueryable<Book> Books {get;set;}
}
我想让NHibernate专门执行该查询,而不是让get all加载整个集合,然后在内存中解析它(这是当前使用ICollection时发生的情况)

这背后的原因是,我的收集可能是巨大的,数以万计的记录,一个get-all查询可能会破坏我的数据库

我希望隐式地这样做,这样当NHibernate在我的类上看到IQueryable时,它就知道该做什么了

我已经看过了NHibernate的LINQ提供商,目前我正在决定采用大型集合,并将它们拆分到自己的存储库中,这样我就可以显式地调用筛选和分页

LINQ To SQL提供了类似于我所说的内容。

也许您应该试一试。它允许您使用IQueryable并执行以下操作:

Session.Linq<Book>().Where(b => b.Name == "The Great Gatsby");
Session.Linq().Where(b=>b.Name==“伟大的盖茨比”);

我倾向于这样想:

var shelf = ShelfRepo.Get(id);
var books = (from book shelf.FindBooks()
             where book.Title == "The Great Gatsby"
             select book);
聚合根是一致性的边界,因此,如果shelf需要在其包含的书籍上实施某种一致性策略,那么它应该是聚合根。 在这种情况下,它应该拥有一套/一套书籍

如果您不需要以任何方式执行从书架到书本的一致性,那么我会考虑删除SET/PROCESS属性并将这些查询移到存储库中。

另外,由于分页和筛选很可能与您的域逻辑无关,所以它最有可能用于表示。 然后我会考虑为它做一些特殊的视图,而不是在我的存储库中添加演示文稿。

e、 g

这种查询可以返回投影和/或优化为纯SQL等。 它们很可能特定于GUI中的特定视图或报告。
这样,您的域将只关注域概念。

我一直在尝试为类似的问题找到解决方案

您可以使用
ISession.FilterCollection
从实体中筛选集合。这将创建一个额外的IQuery,您可以在其中计数、分页、添加条件等

因此,例如(我在FilterCollection中的查询可能有点错误,但您应该了解):

恶心!您正在通过域模型释放持久性需求!也许您可以通过让存储库发出IQueryable(在运行时实际上是LINQ to NHibernate)使情况变得更糟一点:

public IQueryable<Book> FindBooks() {
  return Resolver.Get<IRepository<Book>>().CreateQuery().Where(b => b.Shelf == this);
}
public IQueryable FindBooks(){
返回Resolver.Get().CreateQuery().Where(b=>b.Shelf==this);
}
还是很无聊

创建您自己的自定义收藏类型(以及可能的IQueryable实现),该类型包装实际书籍的私有字段,并将NHibernate映射到该字段。但是,使用ISession.CreateFilter可能会很困难。您必须考虑“发现”当前会话,将LINQ表达式转换成可以在CealFieldFor等中使用的东西,此外,您的业务逻辑仍然依赖于NHiBiNAT.<
在这一点上没有什么真正令人满意的。在NHibernate能够为您完成LINQ而非藏书集之前,您最好像已经建议的那样正常地查询您的图书存储库,即使它看起来不那么性感或最优

“我已经看过NHibernates Linq provider,目前我正在做出决定,将大量收藏拆分到它们自己的存储库中,这样我就可以明确地调用筛选和分页。”@Khalid-我不知道为什么这对你没有帮助。这正是你问我的问题的原因。”如何让NHibernate映射到可查询的属性?“我已经知道了NHibernate Linq。这是我从未问过的一个问题的答案,这就是为什么我投了反对票。谢谢你如此透彻的解释。我考虑过你说的话,我同意你提出的所有观点。不知道NHibernate 3是否会支持这一开箱即用。
ISession session = GetSession();
var shelf = session.Get<Shelf>(id);
var books = session.FilterCollection(shelf.Books, "where Name = :title").SetString("title", "The Great Gatsby").List<Book>();
public IQueryable<Book> FindBooks() {
  return Resolver.Get<ISession>().Linq<Book>().Where(b => b.Shelf == this);
}
var shelf = ShelfRepo.Get(id);
var books = (from book shelf.FindBooks()
             where book.Title == "The Great Gatsby"
             select book);
public IQueryable<Book> FindBooks() {
  return Resolver.Get<IRepository<Book>>().CreateQuery().Where(b => b.Shelf == this);
}