Как создать отношения между моделями, которые находятся на разных DbContext? - PullRequest
0 голосов
/ 11 сентября 2018

Я разрабатываю приложение по шаблону DDD.

У меня есть следующие контексты для управления сотрудниками и управления учетными записями пользователей, которые называются

EmployeeManagementContext

и

UserAccountManagementContext

Оба контекста находятся в отдельном проекте.
Проект управления сотрудниками имеет следующие модели.

public class Employee  
{  
    public int Id { get; private set; }  
    public string Name { get; private set; }  
    public DateTime DateOfBirth { get; private set; }  
}  

Проект для управления учетными записями пользователей имеет следующие модели.

public class Employee  
{  
    public int Id { get; private set; }  
    public string Name { get; private set; }   
}

public class UserAccount  
{  
    public int Id { get; private set; }  
    public string Username { get; private set; }  
    public string Password { get; private set; }  
}  

EmployeeManagementContext

public class EmployeeManagementContext : DbContext  
{  
    public DbSet<Employee> Employees { get; set; }  
}  

UserAccountManagementContext

public class UserAccountManagementContext : DbContext  
{  
    public DbSet<UserAccount> UserAccounts { get; set; }  
}  

Я могу успешно перенести оба контекста, используя разныеконтекстные ключи, но проблема в том, что я теряю связь между моделями Employee и UserAccount.

Wrong Employee to UserAccount relationship

В основном, бизнес-правила, которые мне нужно реализовать между двумя моделями, следующие:

Сотрудникможет иметь или не иметь UserAccount.
UserAccount принадлежит только одному Сотруднику.

Это означает, что я должен иметь отношение один к нулю или один между Employee и UserAccount, как показано на рисунке ниже.

Correct Employee to UserAccount relationship

Пожалуйста, не обращайте внимания на неправильные обозначения отношений, кажется, это ограничение инструмента, который я использую, но это однозначныйНулевые отношения, уверяю вас.

Я попробовал следующие конфигурации в проекте UserAccount:

public class UserAccountConfiguration : EntityTypeConfiguration<UserAccount>  
{  
    HasKey(x => x.Id);  

    Property(x => x.Id)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);  
}

public class EmployeeConfiguration : EntityTypeConfiguration<Employee>  
{  
    HasKey(x => x.Id);  

    Property(x => x.Id)
        .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);  

    HasOptional(x => x.UserAccount)
        .WithRequired(x => x.Employee);
}  

public class UserAccountManagementContext : DbContext  
{  
    public DbSet<UserAccount> UserAccounts { get; set; }  

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Configurations.Add(new UserAccountConfiguration());
        modelBuilder.Configurations.Add(new EmployeeConfiguration());
        base.OnModelCreating(modelBuilder);
    }
}  

Приведенные выше конфигурации приводят к ошибке, поскольку таблица Employee уже существует из-за EmployeeManagementContext в проекте управления сотрудниками.

Если я попытаюсь добавить следующую конфигурацию в EmployeeConfiguration проекта управления сотрудниками,

ToTable («Пользователи»);

EF больше не жалуется и создает таблицу Users, которая затем создает необходимые мне отношения между Employee и UserAccount.Но проблема в том, что, если я попытаюсь запросить Employee / Users в UserAccountManagementContext, он не будет ничего содержать, и я не думаю, что его хороший дизайн - продолжать создавать меньшие таблицы, которые получены из оригинальной таблицы, потому что это только загромождаетбаза данных, верно? ...

Буду очень признателен за вашу помощь, спасибо.

1 Ответ

0 голосов
/ 11 сентября 2018

Вы должны сосредоточиться больше на домене и меньше на базе данных.

Из того, что я вижу, у вас есть два Агрегата (Employee и UserAccount), в возможных 2 ограниченных контекстах (я не могу назвать их, так как у меня недостаточно данных) , В общем случае не рекомендуется принудительно устанавливать любой инвариант строго согласованным образом между двумя агрегатами, но есть исключения. Они могут быть также в разных базах данных, имеющих разные технологии. Давайте теперь посмотрим, как вы можете применить два инварианта:

Сотрудник может иметь или не иметь учетную запись пользователя.

Это можно смоделировать с помощью обнуляемого UserAccountId на Employee без каких-либо низкоуровневых ссылок на базу данных. В зависимости от бизнес-правил, когда UserAccound удален (если это допустимая бизнес-операция над ним), с помощью Saga / Process Manager вы можете установить на null соответствующий UserAccountId в Employee который имел этот аккаунт.

UserAccount принадлежит только одному Сотруднику.

Простейший способ применения этого инварианта имеет технологический характер: создать уникальный индекс для UserAccountId. Другие решения предполагают использование Sagas, но не так хороши, как это, например, позволили бы в течение короткого периода времени нарушить инвариант.

...