我正在尝试建立如下关系。每个主项都有一个或多个明细项:
public class Detail {
public virtual Guid DetailId { get; set; }
public virtual string Name { get; set; }
}
public class Master {
public virtual Guid MasterId { get; set; }
public virtual string Name { get; set; }
public virtual IList<Detail> Details { get; set; }
}
和映射:
public class MasterMap : ClassMap<Master>
{
public MasterMap()
{
Id(x => x.MasterId);
Map(x => x.Name);
HasMany(x => x.Details).Not.KeyNullable.Cascade.All();
}
}
public class DetailMap : ClassMap<Detail>
{
public DetailMap()
{
Id(x => x.Id);
Map(x => x.Name);
}
}
Master 数据库表是:
masterId uniqueidentifier NOT NULL
name nvarchar(max) NULL
和明细是:
DetailId uniqueidentifier NOT NULL
name nvarchar(max) NULL
MasterId uniqueidentifier NULL
foreign key (masterId) references [Master]
我真的不关心从细节回到主人的链接 - 换句话说,自己的细节对象对我的域层不感兴趣。他们将始终通过他们的主对象访问。
使用这样的代码:
Master mast = new Master
{
MasterId = new Guid(),
Name = "test",
Details = new List<Detail>
{
new Detail { .DetailId = new Guid(), .Name = "Test1" },
new Detail { .DetailId = new Guid(), .Name = "Test1" }
}
};
using (transaction == Session.BeginTransaction)
{
Session.Save(mast);
transaction.Commit();
}
这很有效,除了this post中概述的疯狂限制:NHibernate执行INSERT并将Detail.MasterId先置为NULL,然后执行UPDATE将其设置为真正的MasterId。
实际上,我不希望明细条目具有NULL MasterIds,因此如果我将MasterId字段设置为NOT NULL,则INSERT to Detail将失败,因为我说NHibernate试图输入MasterId = NULL。
我想我的问题归结为:
如何让上面的代码示例与现有的域模型一起使用(例如,不添加Detail.Master属性),并将数据库中的Detail.MasterId字段设置为NOT NULL?
有没有办法让Nhibernate在最初的INSERT中放入正确的MasterId,而不是之后运行UPDATE?这个设计决定有什么理由吗? - 我很难理解为什么会这样做。
答案 0 :(得分:32)
NH3及以上版本允许在单向一对多映射的情况下更正保存实体,而不会烦恼save null
- save
- update
周期,如果同时设置{{} 1}} on&lt; key&gt;和not-null="true"
on&lt; one-to-many&gt;
FluentNHibernate代码片段:
inverse="false"
答案 1 :(得分:14)
你做不到。引用my answer关于您链接到的其他问题的链接:
非常重要注意:如果
<key>
关联的<one-to-many>
列声明为NOT NULL,则NHibernate在创建或更新关联时可能会导致约束违规。要防止出现此问题,必须使用标记为inverse="true"
的多值结束(集合或包)的双向关联。请参阅本章后面的双向关联讨论。
编辑:正如Hazzik正确指出的那样,NHibernate 3及以上版本已经发生了变化。可悲的是,文档还没有更新,所以这里是Hazzik:
[如果你]在
inverse="false"
上设置not-null
和<key>
,NH3及以上版本只会执行两次insert-insert-update插入。
答案 2 :(得分:4)
NHibernate这样做的原因是因为:
当它保存细节时,它只知道细节知道的东西。因此忽略在后台发生的任何主引用。
只有在保存主文件时,它才会看到关系,并使用主文件的ID更新集合的元素。
这是从面向对象的角度来看的逻辑。然而,从保存的角度来看,逻辑上略显不足。我想你总是可以提交错误报告,或者查看它是否已经提交过,并要求他们进行更改。但我认为他们有其特定的(设计/域名)原因。