将 .Any() 与 NHibernate 和继承结合使用
Using .Any() in combination with NHibernate and inheritance
我将 NHibernat 与继承结合使用。这意味着我有一个父对象和一个子对象,它们相互继承,但每个对象都有自己的映射文件,因此创建了单独的表。
我在执行以下操作时遇到了 .Any() 功能的问题:
var value = session.Query<ParentObject>().Any(t => t.Name.Equals(name));
我一直在调试 NHibernate 源代码,我发现当我对一个对象执行查询时,它还会循环遍历从它继承的所有其他 class。这意味着对于 .Any 函数调用,将填充布尔结果集。但奇怪的是,在 DefaultQueryProvider.cs(第 125 行)中发生了以下情况:return results[0];
第一个结果是我的 ChildObject 的 .Any 结果,因此完全忽略了我的 ParentObject 的结果。
我做了一个单元测试来证明这个行为:
[TestMethod]
public void TestInheritance()
{
var name = "test";
var sessionFactory = CreateSessionFactory(database2);
using (var session = sessionFactory.OpenSession())
using (var transaction = session.BeginTransaction())
{
var testObject = new ParentObject();
testObject.SetName(name);
session.SaveOrUpdate(testObject);
transaction.Commit();
var value = session.Query<ParentObject>().Any(t => t.Name.Equals(name));
Assert.IsTrue(value);
}
}
你不会想到这一点,但这个单元测试失败了。
如果我使用没有其他 class 继承自它的 class 测试相同的代码,则单元测试通过。
我可以使用以下方法解决此问题:
var value = session.Query<ParentObject>().FirstOrDefault(t => t.Name.Equals(name)) != null
但我只想使用 Any() 功能。
有人对此有解决方案吗?
还在 NHibernate Bug Tracker 中添加:https://nhibernate.jira.com/browse/NH-3939
这里的问题是您将 ParentObject
作为一个实体使用。
当你在执行
时勾选NHProfiler
session.Query<ParentObject>().ToList()
您将看到 NHibernate 从数据库中获取所有派生的 class,包括您的 ParentObject
。这将导致多个 Select 语句。
当您将 ParentObject
更改为抽象并从中派生 class 时,您可以防止这种行为。然后检查您的派生 class,您将得到您期望的结果。
我找到了答案。
您可以通过在映射 class 上执行以下操作来禁用继承行为(在我的例子中是 FluentNhibernate):
Polymorphism.Explicit();
我将 NHibernat 与继承结合使用。这意味着我有一个父对象和一个子对象,它们相互继承,但每个对象都有自己的映射文件,因此创建了单独的表。
我在执行以下操作时遇到了 .Any() 功能的问题:
var value = session.Query<ParentObject>().Any(t => t.Name.Equals(name));
我一直在调试 NHibernate 源代码,我发现当我对一个对象执行查询时,它还会循环遍历从它继承的所有其他 class。这意味着对于 .Any 函数调用,将填充布尔结果集。但奇怪的是,在 DefaultQueryProvider.cs(第 125 行)中发生了以下情况:return results[0];
第一个结果是我的 ChildObject 的 .Any 结果,因此完全忽略了我的 ParentObject 的结果。
我做了一个单元测试来证明这个行为:
[TestMethod]
public void TestInheritance()
{
var name = "test";
var sessionFactory = CreateSessionFactory(database2);
using (var session = sessionFactory.OpenSession())
using (var transaction = session.BeginTransaction())
{
var testObject = new ParentObject();
testObject.SetName(name);
session.SaveOrUpdate(testObject);
transaction.Commit();
var value = session.Query<ParentObject>().Any(t => t.Name.Equals(name));
Assert.IsTrue(value);
}
}
你不会想到这一点,但这个单元测试失败了。 如果我使用没有其他 class 继承自它的 class 测试相同的代码,则单元测试通过。
我可以使用以下方法解决此问题:
var value = session.Query<ParentObject>().FirstOrDefault(t => t.Name.Equals(name)) != null
但我只想使用 Any() 功能。
有人对此有解决方案吗?
还在 NHibernate Bug Tracker 中添加:https://nhibernate.jira.com/browse/NH-3939
这里的问题是您将 ParentObject
作为一个实体使用。
当你在执行
时勾选NHProfilersession.Query<ParentObject>().ToList()
您将看到 NHibernate 从数据库中获取所有派生的 class,包括您的 ParentObject
。这将导致多个 Select 语句。
当您将 ParentObject
更改为抽象并从中派生 class 时,您可以防止这种行为。然后检查您的派生 class,您将得到您期望的结果。
我找到了答案。 您可以通过在映射 class 上执行以下操作来禁用继承行为(在我的例子中是 FluentNhibernate):
Polymorphism.Explicit();