Splitting DbContext into multiple contexts with overlapping DbSets

后端 未结 1 1936
无人共我
无人共我 2021-02-09 21:54

I have a DbContext that houses +80 entities at the moment with only 4 of the main modules done, but there are 3 more to go, and they are quite bigger so it will get up to 150 ea

相关标签:
1条回答
  • 2021-02-09 22:23

    You will have problems if you need to use a transaction that spans more than one DbContext. It will be promoted to a distributed transaction no matter if all of the DbContexts connect to the same database. This makes things very slow.

    You will also lose the benefit of the unit of work because the DbContexts will track their models independently.

    You could still separate the models and duplicate the shared ones. This will not cause the various DbContexts to break relationships or deadlock any more than two people running two copies of your software at the same time would.

    However, to keep things manageable you can stay in one DbContext, but hide the models that are not needed in each module.

    Take the following DbContext -

    public class MyContext : DbContext
    {
        public DbSet<Person> People { get; set; }
        public DbSet<Vehicle> Cars { get; set; }
        public DbSet<Trip> Trips { get; set; }
        public DbSet<Company> Employers { get; set; }
        public DbSet<Employee> Employees { get; set; }
    }
    

    If you wanted to make a driving module, you might only use People, Cars, & Trips. If you wanted a payroll module, you might only use Company, Employee, & People. So you would need the following interfaces:

    public interface IDrivingContext
    {
        DbSet<Person> People { get; }
        DbSet<Vehicle> Cars { get; }
        DbSet<Trip> Trips { get; }
    }
    
    public interface IPayrollContext
    {
        DbSet<Person> People { get; }
        DbSet<Company> Employers { get; }
        DbSet<Employee> Employees { get; }
    }
    

    Then you change your context to implement both interfaces:

    public class MyContext : DbContext, IDrivingContext, IPayrollContext
    {
        public DbSet<Person> People { get; set; }
        public DbSet<Vehicle> Cars { get; set; }
        public DbSet<Trip> Trips { get; set; }
        public DbSet<Company> Employers { get; set; }
        public DbSet<Employee> { get; set; }
    }
    

    And when you use the DbContext, only type the variable as IDrivingContext or IPayrollContext, depending on which module you are coding inside of:

    using (IDrivingContext db = new MyDbContext())
    {
         // ...
    }
    
    using (IPayrollContext db = new MyDbContext())
    {
        // ...
    }
    
    0 讨论(0)
提交回复
热议问题