Reputation: 1013
I'm developing a plugin application with EF6, code first.
I have one main context with an entity called User
:
public class MainDataContext : DbContext
{
public MainDataContext(): base("MainDataContextCS") {}
public DbSet<User> Users { get; set; }
}
And then another context for PluginX, on another project which references the base one:
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; }
}
And this neatly creates, on the same Database (same connection string), the PluginX.Bookings
Table.
The problem here is that the Booking
entity contains a reference to User
entity:
public class Booking
{
public int Id { get; set;}
public virtual User CreationUser { get; set;}
public BookingStatus Status { get; set; }
}
And when running Add-Migration
for the plugin context EF will try to create another User
entity called PluginX.User
.
How can this be solved? Is there a way to share a common entity, in another DbContext
?
Upvotes: 16
Views: 11278
Reputation: 790
It's 2024 now, but still relevant.
One more way exits here.
You can add this line to your OnModelCreating
method in PluginDataContext
:
modelBuilder.Entity<User>().Metadata.SetIsTableExcludedFromMigrations(true);
this prevents User
from being involved into migration for PluginDataContext
.
If you have many tables with FK to another DbContext, perhaps reflection can be used for this approach
Upvotes: 0
Reputation: 21
You can try using views, declare the user as a view in PluginDataContext and when you perform the migration, type the method "create User view as ...", this allows you to relate the book to the user.
Upvotes: 2
Reputation: 2847
When you work with multiple contexts you have two options:
Upvotes: 16
Reputation: 39326
This solution could help you:Entity Framework 6 Code First Migrations with Multiple Data Contexts. However, in this case, both context are in the same project. I don't know if works with contexts that are in two different projects (I think it should if you are using the same class to map User). As the blog said, you need to comment the generated code related to the Users table when you run the Add-Migration
command for the PluginX Context.
Upvotes: 1
Reputation: 7066
When you add the Booking entity, don't use the DbSet.Add()
method. Instead use the DbSet.Attach()
method and set the DbContext.Entry(Entity).State
property for the Booking to EntityState.Added
and make sure the DbContext.Entry(Entity).State
for User stays EntityState.Unchanged
.
So for example instead of doing this:
pluginDataContext.dbBooking.Add(myNewBooking);
Do this:
pluginDataContext.dbBooking.Attach(myNewBooking);
pluginDataContext.Entry(myNewBooking).State = EntityState.Added;
This is because the Add()
method marks all entities in the object graph as EntityState.Added
which will cause inserts without checking if the entity already exists in the database. The Attach()
method simply makes the context begin tracking the entity.
This is why I almost never use DbSet.Add()
.
Upvotes: 2