6

我正在开发一个带EF6的插件应用程序,代码优先。实体框架:跨不同的DbContexts共享实体

我有一个实体的一个主要方面称为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实体,称为PluginX.User

这怎么解决?有没有办法共享一个共同的实体,在另一个DbContext

+0

为什么不从MainContext继承PluginContext。 – hazimdikenli 2015-01-16 07:32:36

回答

5

当你与多个环境工作,你有两个选择:

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

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

因此,例如,而不是这样做:

pluginDataContext.dbBooking.Add(myNewBooking); 

这样做:

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

这是因为Add()方法标志着对象图中的所有实体EntityState.Added这将导致插入,而不检查如果实体已经存在于数据库中。方法只是简单地使上下文开始跟踪实体。

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

2

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