单向一对多关系的 NHibernate 配置
我正在尝试建立如下关系。每个Master 项目都有一个或多个Detail 项目:
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
Detail 为:
DetailId uniqueidentifier NOT NULL
name nvarchar(max) NULL
MasterId uniqueidentifier NULL
foreign key (masterId) references [Master]
我真的不关心从 Detail 回到 Master 的链接——换句话说,Detail 对象本身对我的域层来说并不感兴趣。它们总是通过其主对象进行访问。
使用这样的代码:
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();
}
这非常有效,除了 中概述的疯狂限制之外这篇文章:NHibernate 执行 INSERT 并将 Detail.MasterId 首先设置为 NULL,然后执行 UPDATE 将其设置为真实的 MasterId。
实际上,我不希望详细信息条目具有 NULL MasterId,因此如果我将 MasterId 字段设置为 NOT NULL,则 INSERT 到 Detail 将失败,因为正如我所说,NHibernate 正在尝试输入 MasterId = NULL。
我想我的问题归结为:
如何使上述代码示例与我现有的域模型一起使用(例如,不添加 Detail.Master 属性),并将数据库中的 Detail.MasterId 字段设置为 NOT NULL?
有没有办法让 Nhibernate 将正确的 MasterId 放入初始 INSERT 中,而不是随后运行 UPDATE?这个设计决定有什么理由吗? ——我很难理解为什么要这样做。
I'm trying to set up a relationship as follows. Each Master item has one or more Detail items:
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; }
}
And Mappings:
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);
}
}
The Master database table is:
masterId uniqueidentifier NOT NULL
name nvarchar(max) NULL
and Detail is:
DetailId uniqueidentifier NOT NULL
name nvarchar(max) NULL
MasterId uniqueidentifier NULL
foreign key (masterId) references [Master]
I don't really care to have a link from Detail back to Master -- in otherwords, Detail objects on their own are just not interesting to my domain layer. They will always be accessed via their Master object.
Using code like this:
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 works great, except for a crazy limitation outlined in this post: NHibernate does an INSERT and puts Detail.MasterId as NULL first, then does an UPDATE to set it to the real MasterId.
Really, I don't want Detail entries with NULL MasterIds, so if I set the MasterId field to NOT NULL, the INSERT to Detail will fail, because as I said NHibernate is trying to put in MasterId = NULL.
I guess my question boils down to this:
How can I get the above code sample to work with my existing domain model (eg, without adding a Detail.Master property), and the Detail.MasterId field in the database set to NOT NULL?
Is there a way to get Nhibernate to just put the correct MasterId in the initial INSERT, rather than running an UPDATE afterwards? Is there rationale somewhere for this design decision? -- I'm struggling to see why it would be done this way.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
NH3 及更高版本允许在单向一对多映射的情况下正确保存实体,而无需烦人的上设置了 上的
save null
-save
-update
循环,如果您在not-null="true"
以及inverse="false"
FluentNHibernate 代码片段:
NH3 and above allow to correct save entities in case of uni-directional one-to-many mapping without annoying
save null
-save
-update
cycle, if you set bothnot-null="true"
on <key> andinverse="false"
on <one-to-many>FluentNHibernate code snippet for that:
你不能。引用我的回答中的链接您链接到的另一个问题:
编辑: 正如 Hazzik 正确指出的那样,这在 NHibernate 3 及更高版本中已发生变化。遗憾的是,文档尚未更新,因此 Hazzik 如下:
You can't. To quote the link from my answer on the other question you linked to:
Edit: as Hazzik has rightly pointed out, this has changed in NHibernate 3 and above. The docs sadly haven't been updated, so here's Hazzik:
NHibernate 这样做的原因是:
当它保存详细信息时,它只知道该详细信息所知道的内容。因此,在后台发生的任何主引用都将被忽略。
仅当保存 master 时,它才会看到关系并使用 master 的 id 更新集合的元素。
从面向对象的角度来看,这是合乎逻辑的。然而,从节省的角度来看,这有点不合逻辑。我想您始终可以提交错误报告,或者查看是否已经提交并要求他们进行更改。但我认为他们有其特定的(设计/领域)原因。
The reason NHibernate does it this way is because:
When it saves the detail it only knows about the stuff the detail knows about. So any master references which happen in the background are ignored.
Only when the master is saved it sees the relation and updates the elements of the collection with the id of the master.
Which is from an object oriented point of view logical. However from a saving point-of-view is slightly less logical. I suppose you can always file a bug report, or look if it might have been filed already and ask them to change it. But I suppose they have their specific (design/domain) reasons.