Entity Framework: sharing entities in different DbContexts

I am developing a plugin application with EF6, code first.

I have one main context with an object called User :

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

And then another context for PluginX, in another project that references the base:

 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 the PluginX.Bookings table in the same database (same connection string).

The problem is that the Booking object contains a link to the User object:

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

And when you start Add-Migration for the context of the plugin, EF will try to create another User object called PluginX.User .

How can this be solved? Is there a way to share a common entity in another DbContext ?

+6
source share
3 answers

When working with multiple contexts, you have two options:

  • Treat each context as separate applications. Imagine that your user is an external resource that you receive from a web service. You cannot add a foreign key to it. What you will do in this is to add only userId to your tables, and when you need user data to call an external service to receive it or have a local light copy of the user in the context of the โ€œOrdersโ€ that you will update every time, and then from the Users context. This approach is good when working with a large system, and you want to isolate parts (read about DDD and limited contexts).
  • Part of your two contexts, create the third context of the entire model (users, orders, etc.). You will use the full context to create migrations and support the database structure, but in the application you will use smaller contexts. This is a very simple solution. It is easy to support migrations with a single context, and it still allows you to isolate a database operation in smaller contexts that do not have access to unrelated objects.
+5
source

This solution can help you: Entity Framework 6 First migration steps with multiple data contexts . However, in this case, both contexts are in the same project. I donโ€™t know if it works with contexts that are in two different projects (I think this should happen if you use the same class to map the user). As the blog said, you need to comment on the generated code associated with the Users table when you run the Add-Migration command for the PluginX context.

+2
source

When adding a Reservation object, do not use the DbSet.Add() method. Instead, use the DbSet.Attach() method and set the DbContext.Entry(Entity).State to reserve EntityState.Added and make sure that DbContext.Entry(Entity).State for the user remains EntityState.Unchanged .

So, for example, instead:

 pluginDataContext.dbBooking.Add(myNewBooking); 

Do it:

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

This is because the Add() method places all objects in the object graph as EntityState.Added , which will EntityState.Added inserts without checking if the entity exists in the database. The Attach() method simply makes the context begin to track the object.

This is why I almost never use DbSet.Add() .

+1
source

Source: https://habr.com/ru/post/981069/


All Articles