NHibernate:尝试保存包含集合的实体时出现问题

发布于 2024-12-06 12:10:57 字数 1864 浏览 0 评论 0原文

我需要一些帮助。

我刚刚开始使用 NHibernate,并且正在使用 Fluent 进行映射。直到今天一切似乎都运转良好。 故事是这样的:

我的数据库中有两个表:StoreWorkDay 第一个表包含有关商店的信息,WorkDay 表包含有关商店营业时的星期几和开始/结束时间的信息。 Store 包含 WorkDay 表中引用的 Guid StoreID PK 列。 因此,我有一个 Store 的映射文件,其中与 WorkDay 表有 HasMany 关联,以及 Store< 的相应 POCO /强>。 现在,当我填写所有必要的数据并尝试将其保存到数据库时,我收到一个异常,告诉我插入表 WorkDay 失败,因为 StoreID 为空值并且表约束不允许该列为空(当然,这是预期的行为)。

我明白这个异常的原因,但不知道如何解决。 插入失败的原因是因为 StoreID 是在插入时生成的,但 [b]WorkDay[/b] 集合首先保存,在 strong>StoreID尚未生成!

那么,如何强制 NHibernate 生成此 ID 以将其传递给依赖表呢?或者还有其他解决方案吗?

谢谢你!

这是 StoreMap 的代码

public class StoreMap : ClassMap<Store> {
    public StoreMap() {
        Id(x => x.StoreID)
            .GeneratedBy.GuidComb();
        Map(x => x.City);
        Map(x => x.Description);
        Map(x => x.Email);
        Map(x => x.Fax);
        Map(x => x.ImageData).CustomType("BinaryBlob");
        Map(x => x.ImageMimeType);
        Map(x => x.Name);
        Map(x => x.Phone);
        Map(x => x.Street);
        Map(x => x.Zip);

        HasMany(x => x.WorkDays)
            .Inverse().KeyColumn("StoreID").ForeignKeyCascadeOnDelete()
            .Cascade.All();
    }
}

,这是 WorkDayMap 的代码

public class WorkDayMap : ClassMap<WorkDay>{
    public WorkDayMap() {
        Id(x => x.WorkDayID)
            .GeneratedBy.Identity();
        Map(x => x.TimeOpen);
        Map(x => x.TimeClose);
        References(x => x.Store).Column("StoreID");
        References(x => x.Day).Column("DayID");
    }
}

I need some help.

I'm just starting out with NHibernate and I'm using Fluent for mappings. Everything seemed to work fine until today.
Here is the story:

I have two tables in my db: Store and WorkDay
The first table contains info about the store, and the WorkDay table contains info about the days of week and start/end time when the store is open.
Store contains a Guid StoreID PK column that is referenced in the WorkDay table.
So I have a mapping file for Store where I have a HasMany association with the WorkDay table, and a corresponding POCO for Store.
Now, when I fill in all the necessary data and try to persist it to database, I get an exception telling me that the insert into table WorkDay failed because the StoreID had null value and the table constraint doesn't allow nulls for that column (which is, of course, expected behavior).

I understand the reason for this exception, but I don't know how to solve it.
The reason why the insert fails is because the StoreID gets generated upon insert, but the [b]WorkDay[/b] collection gets saved first, in the time when the StoreID hasn't yet been generated!

So, how do I force NHibernate to generate this ID to pass it to dependent tables? Or is there another solution for this?

Thank you!

Here's the code for StoreMap

public class StoreMap : ClassMap<Store> {
    public StoreMap() {
        Id(x => x.StoreID)
            .GeneratedBy.GuidComb();
        Map(x => x.City);
        Map(x => x.Description);
        Map(x => x.Email);
        Map(x => x.Fax);
        Map(x => x.ImageData).CustomType("BinaryBlob");
        Map(x => x.ImageMimeType);
        Map(x => x.Name);
        Map(x => x.Phone);
        Map(x => x.Street);
        Map(x => x.Zip);

        HasMany(x => x.WorkDays)
            .Inverse().KeyColumn("StoreID").ForeignKeyCascadeOnDelete()
            .Cascade.All();
    }
}

and this is for the WorkDayMap

public class WorkDayMap : ClassMap<WorkDay>{
    public WorkDayMap() {
        Id(x => x.WorkDayID)
            .GeneratedBy.Identity();
        Map(x => x.TimeOpen);
        Map(x => x.TimeClose);
        References(x => x.Store).Column("StoreID");
        References(x => x.Day).Column("DayID");
    }
}

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

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

发布评论

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

评论(2

尘世孤行 2024-12-13 12:10:57

NHibernate 不应首先插入 WorkDay,因此您的代码中一定存在错误。确保执行以下所有操作:

  1. 将所有 WorkDay 对象添加到 WorkDays 集合中。
  2. 将所有 WorkDay 对象的 Store 属性设置为父对象。
  3. Store 调用 session.Save(),但不为 WorkDay 对象调用。

编辑:您还应该注意 ForeignKeyCascadeOnDelete() 不会在运行时更改任何内容。这只是 hbm2ddl 工具的一个属性。如果您希望 NHibernate 删除已删除的条目,请使用 Cascade.AllDeleteOrphan() 。

NHibernate shouldn't insert the WorkDay first, so there must be an error in your code. Make sure you do all of the following:

  1. Add all WorkDay objects to the WorkDays collection.
  2. Set the Store property on all WorkDay objects to the parent object.
  3. Call session.Save() for the Store but not for the WorkDay objects.

edit: You should also note that ForeignKeyCascadeOnDelete() won't change anything at runtime. This is just an attribute for the hbm2ddl tool. If you want NHibernate to delete removed entries, use Cascade.AllDeleteOrphan().

北座城市 2024-12-13 12:10:57

它可能会在 Store 之前插入 Workday,因为第一个有一个 identity 生成器。这会强制 NH 执行 INSERT 语句来生成 ID。 guid.comb是在内存中生成的,NH不需要数据库。

NH 尝试在尽可能晚的时间点访问数据库,以避免不必要的更新并利用批次。当您调用 session.Save 时会插入工作日,当下次刷新会话时(例如提交时)会插入 Store。

您不应该使用身份生成器(除非您被迫使用它)。无论如何,这对性能都是不利的。


如果仍然不起作用,您可能需要删除外键上的非空约束。 NH每次都解决不了。有一些智能算法也能够处理递归引用。但有时会出现将外键设置为 null 并稍后更新的情况,即使有解决方案可以避免这种情况。

It probably inserts the Workday before the Store because the first has an identity generator. This forces NH to execute an INSERT statement to generate the ID. guid.comb is generated in memory, NH doesn't need the database.

NH tries to access the db at the latest possible point in time, to avoid unnecessary updates and to make use of batches. Workday is inserted when you call session.Save, Store is inserted when it flushes the session next time (eg. on commit).

You shouldn't use the identity generator (unless you are forced to use it). It is bad for performance anyway.


If it still doesn't work, you probably need to remove the not-null constraint on the foreign key. NH can't resolve it every time. There is some smart algorithm which is also able to cope with recursive references. But there are sometimes cases where it sets a foreign key to null and updates it later even if there would be a solution to avoid it.

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