【问题标题】:NHibernate, saving IDictionary : TransientObjectExceptionNHibernate,保存 IDictionary:TransientObjectException
【发布时间】:2010-11-09 08:38:46
【问题描述】:

在我的班级案例中,我有一个 IDictionary,其中实体(类)作为键,角色(枚举)作为值。当尝试保存 Case 的新实例(非持久化)时,IDictionary 中填充了 Entity 的新实例,我收到以下错误:

NHibernate.TransientObjectException: 对象引用了一个未保存的瞬态实例 - 在刷新之前保存瞬态实例。类型:实体

这些是类(Roles 是一个枚举):

public class Case
{
    public Case { EntityCollection = new Dictionary<Entity, Roles>(); }
    public virtual int Id { get; set; }
    public virtual IDictionary<Entity, Roles> EntityCollection { get; set; }
}

public class Entity
{
    public virtual int Id { get; set; }
}

并且映射如下:

<class name="Case" table="[Case]">
    <id name="Id" column="Id" type="Int32" unsaved-value="any">
        <generator class="hilo"/>
    </id>
    <map name="EntityCollection" table="CaseEntityRoles" 
     cascade="save-update" lazy="false" inverse="false">
        <key column="CaseId" />
        <index-many-to-many class="Entity" 
         column="EntityId" />
        <element column="Roles" type="Roles" not-null="true" />
    </map>
</class>

<class name="Entity" table="[Entity]">
    <id name="Id" column="Id" type="Int32" unsaved-value="0">
        <generator class="hilo"/>
    </id>
</class>

测试代码示例:

[Test]
public void Can_add_new_case()
{
    var newCase = new Case();
    newCase.EntityCollection.Add(new Entity(), Roles.Role1);
    newCase.EntityCollection.Add(new Entity(), Roles.Role2);

    /* At which point I try to persist newCase and get an exception */
}

在测试代码中,newCase-instance 是持久化的,但新实体不是。我尝试了很多不同的东西,比如向 Entity 添加一个 version> 标记并弄乱未保存的值,但似乎没有任何帮助。正如您从映射中看到的那样,我确实有 cascade="save-update"。 有什么想法吗?

【问题讨论】:

    标签: c# nhibernate nhibernate-mapping instance transient


    【解决方案1】:

    如果将 inverse 设置为 true 会发生什么?

    我不知道这是否能解决你的问题......

    您可以做的是利用存储库模式,并创建一个“CaseRepository”类。 在该存储库中,您将有一个 Save 方法来保存给定的案例。 在该保存方法中,您可以遍历给定案例的所有实体,并为每个实体显式调用“SaveOrUpdate”。

    我也想知道您为什么要使用字典来解决这个问题?

    【讨论】:

    • 如果我将 inverse 设置为 true 我没有例外,但实体仍然没有得到保存。实际上,我确实使用了带有 Save 方法的通用 Repository 类,但是如果我正确映射了 NHibernate 能够为我做这件事,我不想为此编写额外的代码。如果我别无选择,这可能就是我必须做的。我使用字典是因为我只想为每个案例保存一次相同的实体(这就是我使用它们作为键的原因)。这个想法是,如果一个实体有很多角色,我可以只使用一个标志枚举。如果这成为问题,我可能不得不修改我的解决方案。
    【解决方案2】:

    我认为在尝试持久化 Case 之前,您需要先持久化 Case 引用的 Entity 对象。我有一个类似的问题,我以这种方式解决了。例如,使用 Rhino NHRepository:

    [Test]
    public void Can_add_new_case()
    {
        var newCase = new Case();
        var entity1 = new Entity();
        var entity2 = new Entity();
        newCase.EntityCollection.Add(entity1, Roles.Role1);
        newCase.EntityCollection.Add(entity2, Roles.Role2);
    
        Rhino.Commons.NHRepository<Entity> entityRepository = new NHRepository<Entity>();
        Rhino.Commons.NHRepository<Case> caseRepository = new NHRepository<Case>();
    
        using (UnitOfWork.Start())
        {
            entityRepository.SaveOrUpdate(entity1);
            entityRepository.SaveOrUpdate(entity2);
            caseRepository.SaveOrUpdate(newCase);
        }
    }
    

    【讨论】:

    • 是的,这也是我最终所做的。遗憾的是 NHibernate 没有自动处理它。如果有人知道任何其他解决方案(或者知道这个错误,如果它是一个错误,何时会被修复)请告诉我,但在那之前我想我必须接受这个作为必要的解决方案。
    猜你喜欢
    • 2011-01-13
    • 1970-01-01
    • 2011-12-08
    • 2010-10-06
    • 2012-09-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多