实体框架:跨不同的DbContexts共享实体

时间:2015-01-15 17:53:03

标签: entity-framework ef-code-first entity-framework-6 ef-migrations

我正在使用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会尝试创建另一个名为User的{​​{1}}实体。

如何解决这个问题?有没有办法在另一个PluginX.User

中共享一个共同的实体

4 个答案:

答案 0 :(得分:6)

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

  1. 将每个上下文视为单独的应用程序。想象一下,您的用户是您从Web服务获得的外部资源。您将无法为其添加外键。你要做的是在表中只添加userId,当你需要用户详细信息时,调用外部服务来获取它们,或者在Bookings上下文中有一个本地的用户副本,你不时会更新来自Users上下文。当您使用大型系统并且想要隔离部件时,这种方法很好(阅读有关DDD和有界上下文的信息)
  2. 来自您的2个上下文的一部分,使用整个模型(用户,预订等)创建第三个上下文。您将使用完整上下文来创建迁移并维护数据库结构,但在应用程序中,您将使用较小的上下文。这是一个非常简单的解决方案。使用单个上下文维护迁移很容易,它仍然允许您在无法访问不相关实体的较小上下文中隔离数据库操作。

答案 1 :(得分:2)

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

答案 2 :(得分:1)

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

例如,而不是这样做:

pluginDataContext.dbBooking.Add(myNewBooking);

这样做:

pluginDataContext.dbBooking.Attach(myNewBooking);
pluginDataContext.Entry(myNewBooking).State = EntityState.Added;

这是因为Add()方法将对象图中的所有实体标记为EntityState.Added,这将导致插入而不检查实体是否已存在于数据库中。 Attach()方法只是让上下文开始跟踪实体。

这就是为什么我几乎从不使用DbSet.Add()

答案 3 :(得分:0)

您可以尝试使用视图,在PluginDataContext中将用户声明为视图,然后在执行迁移时,键入“创建用户视图为...”方法,这使您可以将书与用户相关联。