如何在不同DbContext上找到的模型之间创建关系?

时间:2018-09-11 08:17:37

标签: c# entity-framework domain-driven-design

我正在按照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);
    }
}  

由于雇员管理项目中的EmployeeManagementContext,上述配置导致错误,因为Employee表已经存在。

如果我尝试在员工管理项目的EmployeeConfiguration中添加以下配置,

  

ToTable(“ Users”);

EF不再抱怨,并创建了一个Users表,然后在Employee和UserAccount之间创建了我需要的关系。但是问题是,如果我尝试在UserAccountManagementContext中查询Employee / Users,它不包含任何内容,而且我认为继续创建从原始表派生的较小表的良好设计也不可行,因为它只会使数据库,对吧?

非常感谢您的帮助,谢谢。

1 个答案:

答案 0 :(得分:2)

您应该更多地关注域而不是数据库。

据我所见,您有两个聚合(EmployeeUserAccount),可能有2个受约束的上下文(我无法命名它们,因为我没有没有足够的数据)。通常,不建议在两个集合之间以强烈一致的方式强制任何不变式,但是有例外。它们可能也位于具有不同技术的不同数据库中。现在让我们看看如何执行两个不变式:

  

员工可能拥有或可能没有UserAccount。

可以在UserAccountId上使用可为空的Employee进行建模,而无需任何低级数据库引用。根据业务规则,当删除UserAccound (如果这是有效的业务操作)时,可以使用Saga /流程管理器将相应的{{ 1}}中拥有此帐户的null

  

一个UserAccount仅由一个员工拥有。

强制执行此不变式的最简单方法是技术性的:在UserAccountId上创建唯一索引。其他解决方案暗示使用Sagas,但不如Sagas好,例如,允许在短时间内破坏不变式。

相关问题