将.Any()与NHibernate和继承结合使用

时间:2017-01-27 15:03:27

标签: c# inheritance nhibernate fluent-nhibernate linq-to-nhibernate

我将NHibernat与继承结合使用。这意味着我有一个父对象和一个子对象,它们彼此继承,但每个对象都有自己的映射文件,因此创建了单独的表。

当我执行以下操作时,我遇到了.Any()功能的问题:

    var value = session.Query<ParentObject>().Any(t => t.Name.Equals(name));

我一直在调试NHibernate源代码,我发现当我在一个对象上执行Query时,它也会循环遍历从它继承的所有其他类。这意味着对于.Any函数调用,填充了布尔值的结果集。但奇怪的是,在DefaultQueryProvider.cs(第125行)中会发生以下情况:return results [0];

第一个结果是我的ChildObject的.Any结果,所以我的ParentObject的结果被完全忽略。

我做了一个UnitTest来证明这种行为:

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

你不会指望这个,但是这个单元测试失败了。 如果我使用一个没有从中继承其他类的类来测试相同的代码,则单元测试会通过。

我可以使用以下方法为此做出解决方法:

var value = session.Query<ParentObject>().FirstOrDefault(t => t.Name.Equals(name)) != null

但我只是想使用Any()功能。

有人可能有解决方案吗?

还在NHibernate Bug Tracker中添加:https://nhibernate.jira.com/browse/NH-3939

2 个答案:

答案 0 :(得分:0)

这里的问题是您使用ParentObject作为实体。

执行

时检查NHProfiler
session.Query<ParentObject>().ToList()

您将看到NHibernate从数据库获取所有派生类,包括您的ParentObject。这将导致多个Select语句。

当您将ParentObject更改为抽象并从中派生类时,可以防止此行为。然后检查你的派生类,你将得到你期望的结果。

答案 1 :(得分:0)

我找到了答案。 您可以通过在映射类上执行以下操作来禁用继承行为(在我的示例中为FluentNhibernate):

Polymorphism.Explicit();