更新 添加了
下面的映射问题摘要 我有一个包含许多必需外键字段的数据库和一个具有许多单向关联的代码库。我想使用NHibernate,但据我所知,我要么必须使数据库中的外键字段为NULL(不是现实选项),要么将关联更改为双向(不理想)。我错过了其他任何选择吗?
背景 我加入了一个使用NHibernate将表1:1映射到所谓的“技术”对象的项目。在数据检索之后,对象被映射到实际的域模型(AutoMapper样式,以不同的方式实现)。我知道这是一个不必要的步骤,我想建议将其删除给团队。但是,我遇到了一个问题。
域模型包含许多单向关联:Case对象具有与案例关联的人员列表,但人员不持有对Case对象的引用。在底层数据库方案中,Person表具有引用案例Id的必需外键字段。数据模型:
[ERD]
PERSON
CASE Id* Ids are generated by the DB
Id* <--FK-- CaseId* * denotes required fields
(other) (other)
域模型如下所示:
public class Person : DomainEntity
{ // DomainEntity implements Id. Non-essential members left out }
public class Case : DomainEntity
{
public virtual IList<Person> Persons { get; set; }
}
在Case上调用session.Save()导致数据库错误(插入Person时需要CaseId),因为NHibernate首先插入Person条目,然后是Case条目,并通过更新Person中的CaseId列结束条目。如果数据库中的CaseId列被更改为非必需(允许NULL),则一切都按原样运行...但是,此更改不是一个选项(数据库模型由多个应用程序共享至少另一个年)。 我发现让NHibernate正确执行数据库操作的唯一方法是将关联更改为双向,即将Person更改为
public class Person : DomainEntity
{
public virtual Case Case { get; set; }
}
这将涉及对现有代码库的重大更改,因此如果存在,我会更喜欢替代方案。我已经玩过组件映射,但这是不合适的,因为我们模型中的大多数关联都不是实际的(UML)组合。还有其他我错过的选择吗? TIA!
修改 Case的(流利)映射如下所示:
public class CaseMapping : ClassMap<Case>
{
public CaseMapping()
{
Not.LazyLoad();
Id(c => c.Id).GeneratedBy.Identity();
Map(x => x.Code).Not.Nullable().Length(20);
Map(x => x.Name).Not.Nullable().Length(100);
HasMany<Person>(x => x.Persons)
.AsBag()
.KeyColumn("CaseId")
.ForeignKeyConstraintName("FK_Person_Case")
.Cascade.AllDeleteOrphan();
}
}
如果我将SessionSource.BuildSchema用于测试数据库,则会生成一个具有可为空的CaseId列的Person表。我没有找到一种方法来使用不可空的CaseId字段,没有双向关联。执行的(伪)SQL语句:
Case
... Person
/ *(除CaseId以外的所有列)* / Person
SET CaseId =?在哪里Id =?; @ p0 = 2,@ p1 = 1 答案 0 :(得分:1)
我想你可能在这里运气不好。 http://nhibernate.info/doc/nh/en/index.html#collections-onetomany州的文档:
如果关联的列被声明为NOT NULL,则NHibernate在创建或更新关联时可能会导致约束违规。要防止出现此问题,必须使用标记为inverse =“true”
的多值结束(集合或包)的双向关联