流畅的NHibernate级联问题 - 尝试插入NULL ID

mar*_*nes 13 .net asp.net nhibernate fluent-nhibernate

我有以下模型和映射(下面的代码片段).

一场比赛必须从一开始就有多个与之相关的CompetitionAnswers(多选).

目前,使用下面显示的Fluent NHibernate映射,当我创建一个全新的Competition对象时,填充属性,然后创建3个全新的CompetitionAnswer对象并将它们添加到CompetitionAnswers属性(竞争中的属性),我希望调用Save在会话上将INS竞赛行和3个CompetitionAnswer行插入DB.

但是,当我尝试在会话上调用Save时,它会抱怨CompetitionId为null并且无法在该字段的CompetitionAnswers表中插入null - 这是对的,但是,我不应该这样做NHibernate首先创建竞赛,然后在CompetitionAnswers表中使用新生成的IDENTITY值(CompetitionId)?

比赛(模特)

public virtual int CompetitionId { get; private set; }
public virtual string Title { get; set; }
public virtual string Description { get; set; }
public virtual IList<CompetitionAnswer> CompetitionAnswers { get; set; }
Run Code Online (Sandbox Code Playgroud)

CompetitionAnswer(型号)

public virtual int CompetitionAnswerId { get; set; }
public virtual string Answer { get; set; }
public virtual Competition Competition { get; set; }
Run Code Online (Sandbox Code Playgroud)

CompetitionMap(流利的NHibernate制图)

public CompetitionMap()
{
    Id(x => x.CompetitionId)
        .GeneratedBy.Native();
    Map(x => x.Title);
    Map(x => x.Description);
    HasMany(x => x.CompetitionAnswers)
        .Cascade.AllDeleteOrphan()
        .KeyColumn("CompetitionId")
        .Inverse();
    Table("Competitions");
}
Run Code Online (Sandbox Code Playgroud)

CompetitionAnswerMap(流利的NHibernate制图)

public CompetitionAnswerMap()
{
    Id(x => x.CompetitionAnswerId)
        .GeneratedBy.Native();
    Map(x => x.Answer);
    References(x => x.Competition)
        .Column("CompetitionId");
    Table("CompetitionAnswers");
}
Run Code Online (Sandbox Code Playgroud)

以下是我用于测试此场景的一些示例代码,它会生成错误:

Competition c = new Competition();

c.Description = "Description";
c.Title = "Title";

CompetitionAnswer a1 = new CompetitionAnswer { Answer = "Answer 1" };
CompetitionAnswer a2 = new CompetitionAnswer { Answer = "Answer 2" };
CompetitionAnswer a3 = new CompetitionAnswer { Answer = "Answer 3" };

c.CompetitionAnswers.Add(a1);
c.CompetitionAnswers.Add(a2);
c.CompetitionAnswers.Add(a3);

session.Save(c);
Run Code Online (Sandbox Code Playgroud)

我尝试保存时得到的确切错误是:

无法将值NULL插入列'CompetitionId',表'CompetitionAnswers'; 列不允许空值.INSERT失败.该语句已终止.

任何人都可以详细说明为什么目前没有这个工作?

Kei*_*thS 22

我很确定,而不是100%,问题是竞争中的CompetitionAnswers映射中的Inverse()规范.Inverse()指定子记录负责定义它们与父级的关系.大多数情况下,一对多(父母)的"一"面是对象图的"顶部",并且"拥有"与其子女的关系.父母有孩子,关于是否保留或收养孩子的决定是父母的.然而,情况并非总是如此; 一所大学可能有学生,但是有能力决定他们将去哪里的学生.在这里,学生是图表的"顶部",学校只是识别学生出勤率的单一记录.学生可以随时转学; 这是他们的决定,并没有以任何有意义的方式改变学校,因此学生有责任将自己确定为属于学校.

你的案子是第一个:比赛有竞赛答案,孩子在逻辑上没有责任说"我属于比赛"; 竞争对手"拥有"其答案集.删除Inverse()指令应该使NH将竞争视为对象图的"顶部",因此NH将插入竞赛,然后是CompetitionAnswers,现在可以引用其父亲的ID.

另一个与问题无关的事情,但是如果您要映射到MS SQL Server数据库,并且ID列被定义为DB中的标识列,我GeneratedBy.Identity()将为ID列指定.Native()应该最终使用Identity,但它也会检查HiLo或Sequence方法是否可用.


dot*_*joe 5

References(x => x.Competition)
    .Column("CompetitionId")
    .Not.Nullable(); //add this
Run Code Online (Sandbox Code Playgroud)

并且除了父母在其集合中持有孩子之外,还要确保孩子指向父母.当父对象是反向时,这是必需的.

a1.Competition = c; 
Run Code Online (Sandbox Code Playgroud)

该列是否non null在数据库端但在NH端映射为可空?

  • 对我来说,我不得不使用`.Not.KeyNullable()`,但这个答案帮助+1 (2认同)