NHibernate的IQueryable集合作为根的属性 [英] NHibernate IQueryable collection as property of root

查看:148
本文介绍了NHibernate的IQueryable集合作为根的属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个拥有属性集合的根对象。



例如:

 我有一个Shelf对象, 。 

//现在
公共类书架
{
public ICollection< Book>书籍{get;设置;}
}

//需要
公共类书架
{
public IQueryable< Book>书籍{get; set;}
}

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

  var shelf = shelfRepository获得(1); 

var filtered =从book.Books
中book book.Name ==The Great Gatsby
select book;

我希望NHibernate专门执行查询,而不是全部加载整个集合,然后解析它在内存中(这是当我使用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)列表< Book>();

有一个问题,但是:

执行代码
的消费者需要访问
ISession.CreateFilter,或者需要

仓库中创建一个方法在一个属性中,
a查询,以及您的查询参数
(以及任何分页或其他
信息)。不是真正的地球上最性感的
的东西。

  • 这不是你想要的LINQ。


    不幸的是,我不认为有什么办法可以用NHibernate来获得你想要的东西。你可以假冒它,如果你想尝试,但他们似乎对我平坦:

    添加一个方法或属性,在封面下返回一个LINQ到这个架子的NHibernate IQueryable

      public IQueryable< Book> FindBooks(){
    return Resolver.Get< ISession>()。Linq< Book>()。其中​​(b => b.Shelf == this);



    $ b $ p
    $ b

    有人可能会这样消费:

      var shelf = ShelfRepo.Get(id); 
    var books =(from book shelf.FindBooks()
    where book.Title ==The Great Gatsby
    select book);

    唷!你正在通过你的域模型来满足你的持久性需求!也许你可以通过存储库发出IQueryable来让它变得更简单一些,它在运行时实际上是LINQ到NHibernate:

      public IQueryable的<图书> FindBooks(){
    return Resolver.Get< IRepository< Book>>()。CreateQuery()。

    $ / code>

    还是挺不错的



    创建自己的自定义集合类型(可能是IQueryable实现),封装实际书籍的专用字段,并将NHibernate映射到该字段。但是,使用ISession.CreateFilter可能会遇到困难。你必须考虑发现当前会话,将LINQ表达式转换成你可以在CreateFilter中使用的东西等。另外,你的业务逻辑仍然依赖于NHibernate。

    在这一点上没有什么可以满足的。直到NHibernate可以为你完成一个集合的LINQ,看起来你最好像查询过的那样正常查询你的书库,即使它看起来不够性感或者最优。


    I have a root object that has a property that is a collection.

    For example:

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

    What I want to accomplish is to return a collection that is IQueryable so that I can run paging and filtering off of the collection directly from the the parent.

    var shelf = shelfRepository.Get(1);
    
    var filtered = from book in shelf.Books
                   where book.Name == "The Great Gatsby"
                   select book;
    

    I want to have that query executed specifically by NHibernate and not a get all to load a whole collection and then parse it in memory (which is what currently happens when I use ICollection).

    The reasoning behind this is that my collection could be huge, tens of thousands of records, and a get all query could bash my database.

    I would like to do this implicitly so that when NHibernate sees an IQueryable on my class it knows what to do.

    I have looked at NHibernate's LINQ provider and currently I am making the decision to take large collections and split them into their own repository so that I can make explicit calls for filtering and paging.

    LINQ To SQL offers something similar to what I'm talking about.

    解决方案

    I've been trying to come up with a solution for a similar problem.

    You can filter collections off an entity using ISession.FilterCollection. This creates an additional IQuery where you can count, page, add criteria, etc.

    So, for example (my query in FilterCollection may be a little off, but you should get the idea):

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

    There are a problem with that, however:

    1. The consumer executing the code needs to access ISession.CreateFilter, or you need to create a method on your repository that takes in a property, a query, and your query arguments (as well as any paging or other information). Not really the sexiest thing on the planet.
    2. It's not the LINQ you wanted.

    Unfortunately, I don't think there's any way to get what you want out of the box with NHibernate. You could fake it, if you wanted to try, but they seem to fall flat to me:

    Add a method or property that under the covers returns a LINQ to NHibernate IQueryable for this shelf:

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

    where someone might consume that like this:

    var shelf = ShelfRepo.Get(id);
    var books = (from book shelf.FindBooks()
                 where book.Title == "The Great Gatsby"
                 select book);
    

    Yuck! You are bleeding your persistence needs through your domain model! Maybe you could make it a little less worse by having a repository emit IQueryable, which at runtime is actually LINQ to NHibernate:

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

    Still pretty blah.

    Create your own custom collection type (and potentially an IQueryable implementation) that wraps a private field of the actual books, and map NHibernate to that field. However, it may be a difficult undertaking getting that working with ISession.CreateFilter. You have to consider "discovering" the current session, converting the LINQ expression into something you can use in CreateFilter, etc. Plus, your business logic is still dependent on NHibernate.

    Nothing really satisfies at this point. Until NHibernate can do LINQ over a collection for you, it appears that you're better off just querying your Book repository normally as has already been suggested, even if it doesn't seem as sexy or optimal.

    这篇关于NHibernate的IQueryable集合作为根的属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

  • 查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆