单向关联是否通过NHibernate导致不需要的外键字段 [英] Do unidirectional associations lead to non-required foreign key fields through NHibernate

查看:101
本文介绍了单向关联是否通过NHibernate导致不需要的外键字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

更新 在下面添加了映射

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

Question summary I have a database with many required foreign key fields and a code base with many unidirectional associations. I want to use NHibernate, but as far as I can tell, I either have to make the foreign key fields in the database NULLable (not a realistic option) or change the associations to bidirectional (not ideal either). Any other options that I've missed?

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

Backgrounds I've joined a project that uses NHibernate to map tables 1:1 to so-called "technical" objects. After data retrieval, the objects are mapped to the actual domain model (AutoMapper style,implemented differently). I know that this is an unnecessary step and I want to propose removing it to the team. However, I'm running into an issue.

域模型包含许多单向关联:Case对象具有与Case关联的Person列表,但是Persons不持有对Case对象的引用.在基础数据库方案中,Person表具有一个必需的外键字段,该字段引用了案例ID.数据模型:

The domain model contains many unidirectional associations: the Case object has a list of Persons associated with the case, but the Persons do not hold a reference to the Case object. In the underlying database scheme, the Person table has a required foreign key field that references the case Id. The data model:

[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更改为

Calling session.Save() on a Case leads to a database error (CaseId required when inserting into Person), because NHibernate starts with inserting the Person entries, followed by the Case entry and finishes by updating the CaseId column in the Person entries. If the CaseId column in the database is altered to non-required (allow NULLs), everything works as it should... however, that change is not an option at the moment (the database model is shared by several apps for at least another year). The only way I have found to get NHibernate to execute the database actions correctly is by changing the association to bidirectional, i.e., by changing Person to

public class Person : DomainEntity
{ 
  public virtual Case Case { get; set; }
}

但是,这将涉及对现有代码库的重大更改,因此,我希望使用替代方法(如果存在).我已经尝试过组件映射,但是这很不合适,因为我们模型中的大多数关联都不是实际的(UML)组合.我还有其他选择吗? TIA!

This would involve significant changes to the existing codebase however, so I would prefer alternatives, if they exist. I've played around with component mappings, but that is a bad fit since most associations in our model are not actual (UML) compositions. Are there any other options that I've missed? TIA!

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

EDIT The (Fluent) mapping for Case looks like this:

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

If I use SessionSource.BuildSchema for a test database, this generates a Person table with a nullable CaseId column. I have not found a way for this to work with a non-nullable CaseId field without bidirectional associations. The executed (pseudo) SQL statements:

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

推荐答案

我认为您在这里可能不走运.位于 http://nhibernate.info/doc/nh/zh-CN的文档/index.html#collections-onetomany 状态:

I think you may be out of luck here. The docs at http://nhibernate.info/doc/nh/en/index.html#collections-onetomany state:

如果关联的列声明为NOT NULL,则NHibernate在创建或更新关联时可能会导致约束冲突.为防止出现此问题,您必须使用双向关联,将多个有价值的末端(集合或袋子)标记为inverse ="true"

这篇关于单向关联是否通过NHibernate导致不需要的外键字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆