NHibernate:尝试保存包含集合的实体时出现问题
我需要一些帮助。
我刚刚开始使用 NHibernate,并且正在使用 Fluent 进行映射。直到今天一切似乎都运转良好。 故事是这样的:
我的数据库中有两个表:Store 和 WorkDay 第一个表包含有关商店的信息,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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
NHibernate 不应首先插入
WorkDay
,因此您的代码中一定存在错误。确保执行以下所有操作:WorkDay
对象添加到WorkDays
集合中。WorkDay
对象的Store
属性设置为父对象。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:WorkDay
objects to theWorkDays
collection.Store
property on allWorkDay
objects to the parent object.session.Save()
for theStore
but not for theWorkDay
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, useCascade.AllDeleteOrphan()
.它可能会在 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.