NHibernate,保存 IDictionary : TransientObjectException

发布于 2024-07-26 07:39:33 字数 1845 浏览 2 评论 0原文

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

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

这些是类(角色是枚举):

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 实例被持久化,但新实体则不然。 我尝试了很多不同的方法,例如添加 <version> 标记到实体并弄乱未保存的值,但似乎没有任何帮助。 正如您从映射中看到的那样,我确实有cascade =“save-update”。 有任何想法吗?

In my class Case I have an IDictionary with Entity (a class) as key and Roles (an enum) as value. When trying to save a new instance (non-persisted) of Case, where the IDictionary is filled with new instances of Entity I get the following error:

NHibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing. Type: Entity

These are the classes (Roles is an enum):

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

and

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

And mapping is as follows:

<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>

and

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

Sample of the test code:

[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 */
}

In the testcode the newCase-instance is persisted, but the new entities are not. I've tried a lot of different things, like adding a <version> tag to Entity and messing around with unsaved-value, but nothing seems to help. And as you can see from the mapping I do have cascade="save-update".
Any ideas?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

旧人 2024-08-02 07:39:33

我认为在尝试持久化 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);
    }
}

I think you need to persist the Entity objects that are referenced by the Case first, before you try to persist the Case. I had a similar issue that I solved this way. For example, using the 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);
    }
}
三寸金莲 2024-08-02 07:39:33

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

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

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

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

What happens if you set inverse to true ?

I dont know whether this wil solve your problem ...

What you could do, is make use of the Repository pattern, and create a 'CaseRepository' class.
In that repository, you will have a Save method which would Save a given Case.
In that save method, you could loop over all the entities for the given Case and explicitly call 'SaveOrUpdate' for each Entity.

I also wonder why you are using a Dictionary for this issue ?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文