我正在尝试使用部分父组合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();
}
答案 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实例,并在一个会话中进行更改。 (这不是必需的。否则,有一些代码结构可以这样做,但是除非您绝对确定必须用另一种方法,否则通常在单个会话中执行加载,修改和持久化(刷新)要容易得多。 !)还应该进行交易以确保可靠的操作。