NHibernate延迟加载导致堆栈溢出

时间:2018-03-27 21:37:55

标签: nhibernate nhibernate-mapping

我有一个简单的域模型,实体租户和客户(前者是聚合)。我还有一个CustomerCode值对象。这些类看起来如下。

class Tenant() {
    private Guid _id;
    private Customer _customer;
    public Tenant(CustomerCode cc) {
        _customer = new Customer(this, cc);
    }
    public virtual Customer {
        get => _customer;
        protected set => _customer = value;
    }
    //etc
}

class Customer {
    private Guid _id;
    private Tenant _parent;
    private CustomerCode _code;
    internal Customer(Tenant parent, CustomerCode code) {
        _parent = parent;
        _code = code;
    }
    public virtual Tenant Parent {
        get => _parent;
        protected set => _parent = value;
    }
    public virtual CustomerCode Code {
        get => _code;
        protected set => _code = value;
    }
    //etc
}

class CustomerCode {
    private string _value;
    public CustomerCode(string value) {
        // some validations
        _value = value;
    }
    public virtual string Value {
        get => _value;
        protected set => _value = value;
    }
    // etc
}

租户和客户有一对一的关系,如HBM文件中所定义。

<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
                   namespace="..." assembly="...">
  <class name="Tenant" table="Tenants">
    <id name="Id" column="Id" type="Guid">
      <generator class="guid" />
    </id>
    <!-- etc -->
    <many-to-one name="Customer" unique="true" column="CustomerId" 
        class="Customer" not-null="true" cascade="save-update "/>
  </class>
</hibernate-mapping>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   namespace="..." assembly="...">
    <class name="Customer" table="Customers">
        <id name="Id" column="Id" type="Guid">
            <generator class="guid" />
        </id>
        <component name="Code">
            <property name="Value" column="Code" />
        </component>
        <!-- etc -->
        <one-to-one name="Tenant" class="Tenant" property-ref="Customer" />
    </class>
</hibernate-mapping>

最后,我有以下测试用例。这里,CreateSession返回一个ISession。

[TestMethod]
public void CreateTenantTest()
{
    var session = CreateSession();

    object tenantId;

    using (var tran = session.BeginTransaction()) {
        var customerCode = new CustomerCode("BW1801");
        var item = new Tenant(customerCode);

        tenantId = session.Save(item);
        tran.Commit();
    }
    session.Clear();

    var ts = session.Get<Tenant>(tenantId);

    Assert.AreEqual(tenantId, ts.Id);
    //some other asserts
    Assert.IsNotNull(ts.Customer); 
    Assert.AreEqual("BW1801", ts.Customer.Code.Value); // <--this won't work
}

测试用例中的最后一个断言导致Visual Studio 2017的测试系统因为stackoverflow异常而停止。完整的信息是:

The active test run was aborted. Reason: Process is terminated 
due to StackOverflowException

如果我评论最后一个断言,则测试功能正常。调试测试用例没有结果,因为VS只是冻结而且我必须杀死VStest进程。

鉴于这对Customer不起作用,我开始怀疑延迟加载有问题。所以我更改了两个HBM.XML文件的声明以禁用延迟加载:

    <hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" 
                   namespace="..." assembly="...">
  <class name="Tenant" table="Tenants" lazy="true">
    <!-- etc -->
  </class>
</hibernate-mapping>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   namespace="..." assembly="...">
    <class name="Customer" table="Customers" lazy="true">
        <!-- etc -->
    </class>
</hibernate-mapping>

它工作正常,StackOverflowException问题消失了,测试用例通过并正确设置了值。现在,我可以继续工作,但我不觉得轻松禁用延迟加载,因为它是一个可以在面临瓶颈或资源消耗时提供帮助的功能。此外,也许我搞砸了一些东西,而我只是把虫子扫到地毯下面。

任何人都可以解释为什么会出现这种情况吗?我是在忽略某些东西,或者在某个地方错过设置?

0 个答案:

没有答案