如果我理解正确的话,你的数据库结构并没有强制执行引用完整性(FK_OwnerID 并不是真正的外键),但是通过你对映射的更改,你告诉 NHibernate 强制执行这一点。我认为这是行不通的。
基本上,我看到两个选项可以解决这个问题:
- 使用您的创建一个虚拟条目
000-DB 中的 Guid 充当
所有这些孤儿的父母。
- 更改表以允许该列中存在 NULL 并
使其成为真正的外键
约束(带有“级联集
无效的)。 (我会推荐这样做。)
Edit:如果选项 1 不可行,那么我建议选项 3:
您可以尝试 NHibernate 的拦截器功能。您需要实现 IInterceptor (或继承自 EmptyInterceptor)。 OnSave() 方法用于新对象,OnFlushDirty 用于更改对象。我们在这里所做的是创建一个具有所需 ID 的新“虚拟”对象并分配它。
using System;
using NHibernate;
namespace NameSpaceWithDAL
{
public class TestInterceptor : NHibernate.EmptyInterceptor
{
public override bool OnSave(object entity, object id, object[] state, string[] propertyNames, NHibernate.Type.IType[] types)
{
if (entity is ChildClass && (entity as ChildClass).Owner == null)
{
SetState(propertyNames, state, "Owner", new OwnerClass { ID = "000..." });
}
return true;
}
public override bool OnFlushDirty(object entity, object id, object[] currentState, object[] previousState, string[] propertyNames, NHibernate.Type.IType[] types)
{
if (entity is ChildClass && (entity as ChildClass).Owner == null)
{
SetState(propertyNames, state, "Owner", new OwnerClass { ID = "000..." });
}
return true;
}
private void SetState(string[] propertyNames, object[] state, string propertyname, object value)
{
var index = Array.IndexOf(propertyNames, propertyname);
if (index == -1) return;
state[index] = value;
}
}
}
为了使用它,需要为会话(在 OpenSession() 中)或整体配置中定义拦截器:
new Configuration().SetInterceptor(new TestInterceptor());
我用简单的属性测试了上面的代码,所以我不能说这是否真的适用于关系。
代码示例取自迈克·奥布莱恩 http://blog.mikeobrien.net/2010/01/automatically-setting-modified-and.html