使用NHibernate使用复合键插入记录失败

时间:2018-09-18 07:31:44

标签: c# nhibernate

我正在尝试使用部分父组合ID引用某些子实体。 我有一个表定义,如下所示:

Programs
Events
ProgramEvents

类文件:

public class Program
{
    public virtual int Id { get; set; }
    public virtual string Name { get; set; }
    public virtual IList<ProgramEvent> StartEvents { get; set; }
    public virtual IList<ProgramEvent> EndEvents { get; set; }
}

public class ProgramEvent
{
    public virtual Event Event { get; set; }
    public virtual bool Repeatable { get; set; }
    public virtual int EventOrder { get; set; }
    public virtual int EventSection { get; set; }
    public virtual Program Program { get; set; }

    public override bool Equals(object obj)
    {
        return Equals(obj as ProgramEvent);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            int hash = GetType().GetHashCode();

            hash = (hash * 31) ^ EventSection.GetHashCode();
            hash = (hash * 31) ^ EventOrder.GetHashCode();
            hash = (hash * 31) ^ Event.Id.GetHashCode();
            hash = (hash * 31) ^ Program.Id.GetHashCode();

            return hash;
        }
    }

程序类的映射包含以下参考:

<list name="StartEvents" table="ProgramEvents" lazy="false" where="EVENT_SECTION = 1" cascade="all-delete-orphan" inverse="true">
  <key column="PROGRAM_ID" />
  <index column="EVENT_ORDER" />
  <one-to-many class="ProgramEvent"/>
</list>

映射程序事件类:

  <class name="ProgramEvent" table="ProgramEvents">

    <composite-id>
      <key-many-to-one class="Program"  lazy="false" name="Program" column="PROGRAM_ID" />
      <key-many-to-one class="Event"  lazy="false" name="Event" column="EVENT_ID" />
      <key-property name="EventOrder" column="EVENT_ORDER" />
      <key-property name="EventSection" column="EVENT_SECTION" />
    </composite-id>

    <property name="Repeatable" column="REPEATABLE"/>

  </class>

当我尝试使用对事件表的新引用保存程序时,出现此类错误:

  

SqlException:无法将值NULL插入列“ PROGRAM_ID”,   表“ ProgramEvents”;列不允许为空。   INSERT失败。该声明已终止。

我打开sql探查器并得到了这样的sql:

  

exec sp_executesql N'INSERT INTO ProgramEvents(REPEATABLE,   PROGRAM_ID,EVENT_ID,EVENT_ORDER,EVENT_SECTION)的值(@ p0,@ p1,   @ p2,@ p3,@ p4)',N'@ p0位,@ p1整数,@ p2整数,@ p3整数,@ p4   int',@ p0 = 1,@ p1 = NULL,@ p2 = NULL,@ p3 = 0,@ p4 = 0

NHibernate确实尝试插入空值。为什么会发生?

UPD 我尝试像这样更新程序:

    var program = ProgramDao.Current.GetById(1);

    var newEvent = EventDao.Current.GetById(4);
    var programEvent = new ProgramEvent { Event = newEvent, Repeatable = true };
    program.StartEvents.Add(programEvent);

    using (var session = SessionFactory.Current.OpenSession())
    {
        session.Evict(program);
        session.Update(program);
        session.Flush();
    }

2 个答案:

答案 0 :(得分:0)

尝试此代码:

public class ClassNameMap: ClassMap<ClassName>
{
    public ClassNameMap()
    {
        CompositeId().
            .KeyReference(x => x.A, "A")
            .KeyReference(x => x.B, "B");
    }
}

答案 1 :(得分:0)

必须将programEvent.Program设置为指向该程序。当您指定inverse = true时,所包含的类有责任维护对Program的引用。

此外,我会避免逐出和更新。在通用程序结构中应该没有必要。但是您的示例代码很奇怪...您应该加载Program实例,并在一个会话中进行更改。 (这不是必需的。否则,有一些代码结构可以这样做,但是除非您绝对确定必须用另一种方法,否则通常在单个会话中执行加载,修改和持久化(刷新)要容易得多。 !)还应该进行交易以确保可靠的操作。