NHibernate配置用于单向一对多关系

gre*_*mac 18 nhibernate one-to-many fluent-nhibernate

我正在尝试建立如下关系.每个项目都有一个或多个详细信息项:

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; }
}
Run Code Online (Sandbox Code Playgroud)

和映射:

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

数据库表:

masterId   uniqueidentifier NOT NULL
name       nvarchar(max) NULL
Run Code Online (Sandbox Code Playgroud)

细节是:

DetailId   uniqueidentifier NOT NULL
name       nvarchar(max) NULL
MasterId   uniqueidentifier NULL
foreign key (masterId) references [Master]
Run Code Online (Sandbox Code Playgroud)

我真的不在乎有一个从Detail回到Master的链接 - 换句话说,自己的Detail对象对我的域层并不感兴趣.它们将始终通过其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();
}
Run Code Online (Sandbox Code Playgroud)

这很好用,除了这篇文章中概述的疯狂限制: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?这个设计决定有什么理由吗? - 我很难理解为什么会这样做.

haz*_*zik 32

NH3及以上允许正确的存储实体单向,没有恼人的一个一对多映射的情况下save null- save- update周期,如果同时设置not-null="true"对<key>和inverse="false"对<一个一对多>

FluentNHibernate代码片段:

public class MasterMap : ClassMap<Master> 
{
    public MasterMap() 
    {
        Id(x => x.MasterId);
        Map(x => x.Name);
        HasMany(x => x.Details)
            .Not.Inverse()     //these options are very
            .Not.KeyNullable() //important and work only if set together 
            .Not.KeyUpdate()   //to prevent double update
            .Cascade.All();
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @Sam也设置`.Not.KeyUpdate()`并且双重更新将消失 (3认同)

Jam*_*ory 14

你不能.引用对你链接到的另一个问题的回答的链接:

非常重要注意:如果关联的<key><one-to-many>声明为NOT NULL,则NHibernate在创建或更新关联时可能会导致约束违规.要防止出现此问题,必须使用标记为的多值结束(集合或包)的双向关联inverse="true".请参阅本章后面的双向关联讨论.

编辑:正如Hazzik正确指出的那样,NHibernate 3及以上版本已经发生了变化.遗憾的是,文档还没有更新,所以这里是Hazzik:

[如果你]设置inverse="false"not-null打开<key>,NH3及以上将只执行insert-insert-update的两个插入插入.

  • 实际上如果在键NH3及以上设置inverse ="false"且not-null将只执行insert-insert-update的两个插入插入 (4认同)
  • 我不知道为什么,但如果我设置.Not.KeyNullable().Not.Inverse()插件按预期工作 - 设置外键,但后来nhibernate发出额外更新,这是不需要的:设置外键已经设置好了...这是设计成这种方式吗? (3认同)