实体框架:在不同的DbContext中共享实体

问题描述 投票:11回答:3

我正在使用EF6开发插件应用程序,首先编写代码。

我有一个名为User的实体的主要上下文:

public class MainDataContext : DbContext
{
    public MainDataContext(): base("MainDataContextCS") {}
    public DbSet<User> Users { get; set; }
}

然后是另一个项目的PluginX的另一个上下文,该上下文引用了基类:

public class PluginDataContext : DbContext
{
    public PluginDataContext () : base("MainDataContextCS") {
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder) {
        modelBuilder.HasDefaultSchema("PluginX");
        base.OnModelCreating(modelBuilder);
    }

    public DbSet<Booking> Bookings { get; set; }
}

这将在同一数据库(相同的连接字符串)上巧妙地创建PluginX.Bookings表。

这里的问题是Booking实体包含对User实体的引用:

public class Booking
{
    public int Id { get; set;}
    public virtual User CreationUser { get; set;}
    public BookingStatus Status { get; set; }
}

并且在插件上下文中运行Add-Migration时,EF将尝试创建另一个名为UserPluginX.User实体。

如何解决?是否有一种方法可以在另一个DbContext中共享一个公共实体?

entity-framework ef-code-first entity-framework-6 ef-migrations
3个回答
8
投票

当使用多个上下文时,有两个选择:

  1. 对待每个上下文就像它们是单独的应用程序一样。假设您的用户是从Web服务获得的外部资源。您将无法为其添加外键。您要做的就是要么仅在表中添加userId,然后在需要用户详细信息时调用外部服务以获取它们,要么在Bookings上下文中拥有该用户的本地轻量副本,您将不时更新从用户上下文中。当您使用大型系统并且想要隔离各个部分(了解DDD和有界上下文)时,此方法很好。
  2. 除您的2个上下文外,请使用整个模型(用户,预订等)创建第三个上下文。您将使用完整的上下文来创建迁移并维护数据库结构,但是在应用程序中,您将使用较小的上下文。这是一个非常简单的解决方案。使用单个上下文维护迁移很容易,并且仍然可以让您在无法访问无关实体的较小上下文中隔离数据库操作。

1
投票

添加预订实体时,请勿使用DbSet.Add()方法。而是使用DbSet.Attach()方法,并将预订的DbContext.Entry(Entity).State属性设置为EntityState.Added,并确保用户的DbContext.Entry(Entity).State保持EntityState.Unchanged


1
投票

此解决方案可以为您提供帮助:Entity Framework 6 Code First Migrations with Multiple Data Contexts。但是,在这种情况下,两个上下文都在同一个项目中。我不知道是否可以在两个不同项目中使用上下文(如果您使用相同的类来映射User,我认为应该这样做)。正如博客所说,在为PluginX Context运行Add-Migration命令时,需要注释与Users表相关的生成代码。

© www.soinside.com 2019 - 2024. All rights reserved.