c# - NHibernate IQueryable 集合作为根的属性

标签 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;}
}

我想要完成的是返回一个 IQueryable 集合,这样我就可以直接从父集合运行分页和过滤。

var shelf = shelfRepository.Get(1);

var filtered = from book in shelf.Books
               where book.Name == "The Great Gatsby"
               select book;

我想让 NHibernate 专门执行该查询,而不是让 get all 加载整个集合,然后在内存中解析它(这是我使用 ICollection 时当前发生的情况)。

这背后的原因是我的集合可能很大,有数万条记录,而获取所有查询可能会破坏我的数据库。

我想隐式地执行此操作,以便当 NHibernate 在我的类中看到 IQueryable 时,它​​知道该做什么。

我查看了 NHibernate 的 LINQ 提供程序,目前我正在决定采用大型集合并将它们拆分到它们自己的存储库中,以便我可以明确调用过滤和分页。

LINQ To SQL 提供了与我所说的类似的东西。

最佳答案

我一直在尝试为类似的问题提出解决方案。

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

因此,例如(我在 FilterCollection 中的查询可能有点偏离,但您应该明白了):

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>();

但是有一个问题:

  1. 执行代码的消费者 需要访问 ISession.CreateFilter,或者你需要 在你的上创建一个方法 接收属性的存储库, 查询和您的查询参数 (以及任何传呼或其他 信息)。不是最性感的 地球上的东西。
  2. 这不是您想要的 LINQ。

不幸的是,我认为没有任何方法可以让 NHibernate 开箱即用。如果你想尝试,你可以伪造它,但它们似乎对我来说是平淡无奇的:

添加一个方法或属性,在幕后为这个架子返回一个 LINQ to NHibernate IQueryable:

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);

呸!您正在通过您的域模型流血您的持久性需求!也许你可以通过让存储库发出 IQueryable 来让它变得更糟,它在运行时实际上是 LINQ to NHibernate:

public IQueryable<Book> FindBooks() {
  return Resolver.Get<IRepository<Book>>().CreateQuery().Where(b => b.Shelf == this);
}

还是很乏味。

创建您自己的自定义集合类型(可能还有一个 IQueryable 实现)来包装实际书籍的私有(private)字段,并将 NHibernate 映射到该字段。然而,使用 ISession.CreateFilter 可能是一项艰巨的任务。您必须考虑“发现”当前 session ,将 LINQ 表达式转换为您可以在 CreateFilter 中使用的内容等。另外,您的业务逻辑仍然依赖于 NHibernate。

在这一点上没有什么能真正令人满意。在 NHibernate 可以为您对集合执行 LINQ 之前,看起来您最好只像已经建议的那样正常查询您的 Book 存储库,即使它看起来不那么性感或最佳。

关于c# - NHibernate IQueryable 集合作为根的属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2774095/

相关文章:

c# - 如何在 WPF 中将位图渲染到 Canvas 中?

c# - 单击时导致 IndexOutOfRangeException 的 Datagridview

c# - 如何按日期升序对 DataTable 进行排序?

c# - 人是聚合根吗?

.net - NHibernate 缓存/删除问题?

nhibernate - 使用 Fluent NHibernate 和 NHibernate 3 将枚举映射为 Int

c# - Fluent NHibernate映射: QuantLib.日期和Mysql的日期

c# - 通过 C# 使用 INF 文件安装 libusb 驱动程序

nhibernate - 如何使用 Fluent Nhibernate 映射没有唯一标识列的 VIEW

NHibernate 当前 session 上下文问题