【问题标题】:Do unidirectional associations lead to non-required foreign key fields through NHibernate单向关联是否会通过 NHibernate 导致非必需的外键字段
【发布时间】:2010-11-28 10:42:00
【问题描述】:

更新 在下面添加了映射

问题摘要 我有一个包含许多必需外键字段的数据库和一个具有许多单向关联的代码库。我想使用 NHibernate,但据我所知,我要么必须使数据库中的外键字段为 NULLable(不是一个现实的选择),要么将关联更改为双向(也不理想)。还有其他我错过的选择吗?

背景 我加入了一个项目,该项目使用 NHibernate 将表 1:1 映射到所谓的“技术”对象。数据检索后,对象被映射到实际的领域模型(AutoMapper 风格,实现方式不同)。我知道这是一个不必要的步骤,我想建议团队将其删除。但是,我遇到了一个问题。

领域模型包含许多单向关联:Case 对象有一个与该案例关联的 Persons 列表,但 Persons 不包含对 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) 组合。还有其他我错过的选择吗?蒂亚!

编辑 Case 的 (Fluent) 映射如下所示:

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 语句:

  1. 插入Case...
  2. 选择@@identity
  3. INSERT INTO Person /*(除 CaseId 之外的所有列)*/
  4. 选择@@identity
  5. 更新Person SET CaseId = ? WHERE Id = ?;@p0 = 2, @p1 = 1

【问题讨论】:

  • LOL ... 对于 关系,大多数人在提到单向关系时会忽略多值端!您如何映射 Case 上的 Persons 属性?

标签: c# nhibernate nhibernate-mapping


【解决方案1】:

我想你在这里可能不走运。 http://nhibernate.info/doc/nh/en/index.html#collections-onetomany 状态的文档:

如果关联的列被声明为 NOT NULL,NHibernate 在创建或更新关联时可能会导致违反约束。为防止出现此问题,您必须使用与标记为 inverse="true"

的多值端(集合或包)的双向关联

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-09-11
    • 1970-01-01
    • 2019-10-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-10-08
    • 2012-08-29
    相关资源
    最近更新 更多