LINQ Fluent NHIBERNATE .Contains() 在 QueryOver<> 中不起作用,但在 Query<> 中起作用

Posted

技术标签:

【中文标题】LINQ Fluent NHIBERNATE .Contains() 在 QueryOver<> 中不起作用,但在 Query<> 中起作用【英文标题】:LINQ Fluent NHIBERNATE .Contains() does not work in QueryOver<> but works in Query<> 【发布时间】:2013-03-29 13:43:01 【问题描述】:

使用 FNH,我正在尝试使用以下方法检索类别:

_session.QueryOver<Data.Model.Category>()
                                     .Where(c => tourCreateRequest.Categories.Contains(c.CategoryId))
                                     .List()
                                     .Select(_categoryMapper.CreateCategory)
                                     .ToList();

但我在 .Contains() 方法中遇到错误:

无法识别的方法调用: System.Collections.Generic.ICollection`1[[System.Int64,mscorlib, 版本=4.0.0.0,文化=中性, PublicKeyToken=b77a5c561934e089]]:布尔包含(Int64)

为什么我会收到这个错误,有什么问题?

我浏览了一些帖子,然后将我的查询更改为(如下),这适用于 Query。

_session.Query<Data.Model.Category>()
                                     .Where(c => tourCreateRequest.Categories.Contains(c.CategoryId))
                                     .ToList()
                                     .Select(_categoryMapper.CreateCategory)
                                     .ToList();

我认为 QueryOver 是最新最好的,应该用来代替 Query。

如上所示,我使用 QueryOver 的方式有什么问题?

【问题讨论】:

我认为您需要先阅读此内容***.com/questions/5328565/… 感谢您的链接。但是,如何使用 .Contains() 使用 QueryOver 执行相同的操作? 我更喜欢这个解决方案:***.com/questions/4739129/… @JacobBrewer,该解决方案不起作用,因为它只检查单个 childId。需要一个 IN 子句。 【参考方案1】:

我找到了答案。感谢发帖:NHibernate using QueryOver with WHERE IN

var categories = _session.QueryOver<Data.Model.Category>()
                                     .WhereRestrictionOn(c => c.CategoryId).IsIn(ArrayofCategoryIds)
                                     .List()
                                     .Select(_categoryMapper.CreateCategory)
                                     .ToList();

我不得不使用 WhereRestrictionOn()

【讨论】:

【参考方案2】:

这是一个切线相关的问题,这似乎是放置它的最佳位置。

_session.Query<SomeType>.Where(t => someEnumerable.Contains(t))

没有工作。

就我而言,someEnumerable 不是List&lt;SomeType&gt;,而是HashSet&lt;SomeType&gt;。显然,NH 真的希望它成为一个列表。所以,我这样做了,而且效果很好。

var someEnumerableList = someEnumerable.ToList();
_session.Query<SomeType>.Where(t => someEnumerableList.Contains(t)

另外,FWIW,我的印象是 Query&lt;T&gt; 是新的首选方式,QueryOver&lt;T&gt; 是不太首选的方式,因为 Query&lt;T&gt; 返回 IQueryable,这意味着它应该更容易一些测试,理论上换掉 ORM。

【讨论】:

您对ToList() 的调用将执行查询,即它会导致服务器往返返回所有SomeType 类型的记录。我认为首选的选项是从满足Where() 子句的服务器中获取子集。似乎至少对于简单的情况这是可行的:session.Query&lt;Foo&gt;().Where(f =&gt; setOfIds.Contains(f.SomeId)) 并且其中SomeId 的类型为Guid。我们使用 NHibernate 5.1.0 版本。 重要提示:NHibernate 并不是“真的希望它成为一个列表”。 HashSet 无法按预期工作的根本原因是 HashSet 依赖于 GetHashCode() 对其所有子对象保持不变的结果。至关重要的是,当您实现 NHibernate 时,您通常会在基本实体中覆盖 Equals()GetHashCode()... 结果是,当您保存实体并获得 ID 时,该实体的 GetHashCode() 值会发生变化,现在 HashSet 无法在其自身中找到它。 List 不依赖于GetHashCode(),所以它可以工作。【参考方案3】:

像这样:

    query = query.WhereRestrictionOn(x => x.DescricaoDoProduto.Homogenize()).IsInsensitiveLike
(filter.Description.Homogenize());

【讨论】:

以上是关于LINQ Fluent NHIBERNATE .Contains() 在 QueryOver<> 中不起作用,但在 Query<> 中起作用的主要内容,如果未能解决你的问题,请参考以下文章

从 QueryOver(或者 Fluent NHibernate)中获取魔法字符串?

使用 Fluent NHibernate 有条件地将两列映射到一个字段

NHibernate 2 + Fluent Nhibernate 中等信任

NHibernate + Fluent NHibernate 异常

用 Fluent Nhibernate 定义 NHibernate 过滤器的语法?

Fluent NHibernate and Mysql,SQLite