Обновление
Добавлены сопоставления ниже
Краткое изложение вопроса
У меня есть база данных со многими обязательными полями внешнего ключа и база кода со многими однонаправленными ассоциациями. Я хочу использовать NHibernate, но, насколько я могу судить, я должен либо сделать поля внешнего ключа в базе данных NULLable (нереалистичный вариант), либо изменить ассоциации на двунаправленные (тоже не идеальные). Любые другие варианты, которые я пропустил?
Фон
Я присоединился к проекту, который использует NHibernate для отображения таблиц 1: 1 на так называемые «технические» объекты. После извлечения данных объекты сопоставляются с фактической моделью предметной области (стиль AutoMapper, реализованный по-другому). Я знаю, что это ненужный шаг, и я хочу предложить удалить его команде. Однако я столкнулся с проблемой.
Модель предметной области содержит множество однонаправленных ассоциаций: у объекта Case есть список лиц, связанных с делом, но у людей нет ссылки на объект Case. В базовой схеме базы данных таблица Person имеет обязательное поле внешнего ключа, которое ссылается на идентификатор дела. Модель данных:
[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; }
}
Вызов session.Save () для Case приводит к ошибке базы данных (CaseId требуется при вставке в Person), потому что NHibernate начинается со вставки записей Person, затем следует запись Case и заканчивается обновлением столбца CaseId в Person записей. Если столбец CaseId в базе данных изменен на необязательный (разрешить NULL), все работает должным образом ... однако, в данный момент это изменение не вариант (модель базы данных используется несколькими приложениями, по крайней мере, для другого). год).
Я нашел единственный способ заставить NHibernate правильно выполнять действия с базой данных, изменив связь на двунаправленную, то есть изменив Person на
public class Person : DomainEntity
{
public virtual Case Case { get; set; }
}
Однако это повлечет за собой значительные изменения в существующей кодовой базе, поэтому я бы предпочел альтернативы, если они существуют. Я играл с сопоставлениями компонентов, но это плохо подходит, поскольку большинство ассоциаций в нашей модели не являются реальными (UML) композициями. Есть ли другие варианты, которые я пропустил? ТИА!
EDIT
(Свободное) отображение для 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 для тестовой базы данных, это создает таблицу Person с обнуляемым столбцом CaseId. Я не нашел способа для этого работать с ненулевым полем CaseId без двунаправленных ассоциаций. Выполненные (псевдо) операторы SQL:
- INSERT INTO
Case
...
- выберите @@ идентичность
- INSERT INTO
Person
/ * (все столбцы, кроме CaseId) * /
- выберите @@ идентичность
- ОБНОВЛЕНИЕ
Person
SET CaseId =? ГДЕ Id =?; @ P0 = 2, @ p1 = 1