NHibernate 3 LINQ:如何过滤 IQueryable 以仅选择 T 类及其子类的对象?

Posted

技术标签:

【中文标题】NHibernate 3 LINQ:如何过滤 IQueryable 以仅选择 T 类及其子类的对象?【英文标题】:NHibernate 3 LINQ : How to filter IQueryable to select only objects of class T and its subclasses? 【发布时间】:2011-01-02 15:42:34 【问题描述】:

我想升级我的应用程序以使用 NHiberante 3 而不是 NHibernate 2.1.2,但在使用新的 LINQ 提供程序时遇到了一些问题。这个问题是关于其中之一的。假设我有以下类层次结构:

public abstract class PageData

    public int ID  get; set; 
    public string Title  get; set; 


public class ArticlePageData : PageData

    public DateTime PublishedDate  get; set; 
    public string Body  get; set; 


public class ExtendedArticlePageData : ArticlePageData

    public string Preamble  get; set; 

我使用 Fluent NHibernate 将这些类映射到数据库:

public class PageDataMap : ClassMap<PageData>

    public PageDataMap()
             
        Table("PageData");
        Id(x => x.ID);
        Map(x => x.Title);
        DiscriminateSubClassesOnColumn("PageType");
    


public class ArticlePageDataMap : SubclassMap<ArticlePageData>

        public ArticlePageDataMap()
                             
            Join("ArticlePageData", p =>
            
                p.KeyColumn("ID");
                p.Map(x => x.PublishedDate);
                p.Map(x => x.Body);
            );
        


public class ExtendedArticlePageDataMap : SubclassMap<ExtendedArticlePageData>

        public ExtendedArticlePageDataMap ()
                    
            Join("ExtendedArticlePageData", p =>
            
                p.KeyColumn("ID");
                p.Map(x => x.Preamble);
            );
        

然后我想查询所有页面并进行一些过滤:

IQueryable<PageData> pages = session.Query<PageData>();

...

var articles = pages.OfType<ArticlePageData>().Where(x => x.PublishedDate >= (DateTime.Now - TimeSpan.FromDays(7))).ToList();

在这种情况下,NHibernate 3.0.0 失败并出现 NotSupported 异常,但在 NH 的开发版本中有错误修复 NH-2375 导致此代码工作。但是,不幸的是,OfType() 方法按确切类型过滤对象,并且只选择 ArticlePageData 类的对象。旧的 Linq to NH 提供程序在相同的情况下选择 ArticlePageData 和 ExtendedArticlePageData。 如何使用新的 Linq to NH 提供程序进行此类过滤(仅选择 T 类及其子类的对象)?

【问题讨论】:

您拥有哪个版本的 Linq 提供程序?我下载了 NH3.0 (NHibernate-3.0.0.GA-bin) 但似乎找不到比 2.1.2 版本更新的提供程序。谢谢。 自 3.0.0 版以来,linq 提供程序是 NHibernate 的一部分。除了 NHibernate 本身,您不需要下载其他任何东西。所有 linq 的东西都在 NHibernate.Linq 命名空间中。 【参考方案1】:

session.Query&lt;T&gt;().OfType&lt;SubT&gt;() 没有什么意义,它不会让你过滤子类的属性。请改用session.Query&lt;SubT&gt;()

【讨论】:

当然,但是如果没有对我的应用程序进行大量更改,我就无法使用 Query,这就是我问这个问题的原因。我想知道是否存在使用现有 IQueryable 进行 OfType() 过滤的某种方法。 您必须进行更改,因为这是不可能的。 @DiegoMijelshon 是否有描述此问题的错误? @alexdev 这不是错误 我的意思是功能。你知道这是否存在 Jira 问题吗?我愿意做出贡献。即使有针对这种情况的解决方法,在集合内部过滤时也会出现问题。即Blogs.Where(b =&gt; b.Pages.OfType&lt;ArticlePageData&gt;().Any(p =&gt; p.PublishedDate &gt;= DateTime.Now))【参考方案2】:

你可以使用

var article = pages.AsEnumerable().OfType().Where(x => x.PublishedDate >= (DateTime.Now - TimeSpan.FromDays(7))).ToList();

等待 NHibernate 3.0.1。 或者你可以使用

session.Query()

而不是

session.Query()

【讨论】:

第一个想法很糟糕:它将所有内容加载到内存中。 当然,我可以进行内存过滤,但在性能方面这是个坏主意。 OfType() 方法会在 NH 3.0.1 中正常工作吗?我找不到任何有关它的信息。

以上是关于NHibernate 3 LINQ:如何过滤 IQueryable 以仅选择 T 类及其子类的对象?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 LINQ 在 NHibernate 3 中实现关键字搜索?

使用 NHibernate 3.0 QueryOver 或 LINQ 提供程序的权衡

在 NHibernate 3.0 Linq 中急切加载多个兄弟姐妹和孙辈(堂兄弟?)的良好行为

Linq Projection 在 NHibernate 3.2 中被错误地缓存

NHibernate - 使用 LINQ 选择随机记录数

LINQ to NHibernate - 如何检测失败的翻译