简体   繁体   中英

One entity type multiple database contexts?

Context Inheritance

// MobileContext has VisitPlan, Customer, etc. that all the following contexts need.
public MobileContext : DbContext { } 
public AuthenticationEntities : MobileContext { }
public OrderEntities : MobileContext { }
public ThriftEntities : MobileContext { }

The contexts are code-first and I do not use them to create the database.

Description

I create an instance of UserPermissionService which has repositories for VisitPlan , UserBranch , etc. All of the repositories are in the AuthenticationEntities with Customer and VisitPlan being a part of MobileContext which AuthenticationEntites and all other contexts inherit from.

Problem

When I try to execute a query that joins UserBranch and VisitPlan it tells me I cannot query between two contexts, but if I look in the debugger at the DbContext of the repositories they are both of type AuthenticationEntities .

Is there a way to accomplish this?


The Query

//
// USER-BRANCHES: Check the user branches table for permissions.
//
var branches = Branches
    .GetAll()
    .Where(x => x.AzureUser.Username == username && x.StartDate <= effective && x.EndDate >= effective);

//
// USER-ROUTES: Check the user routes table for permissions.
//
var routes = Routes
    .GetAll()
    .Where(x => x.AzureUser.Username == username && x.StartDate <= effective && x.EndDate >= effective);

//
// USER-DRIVERS: Check the user driver number table for permissions.
//
var drivers = DriverNumbers
    .GetAll()
    .Where(x => x.AzureUser.Username == username && x.StartDate <= effective && x.EndDate >= effective);

//
// VISIT PLANS: Retrieve a list of visit plans currently active.
//
var vpQuery = VisitPlans
    .GetAll()
    .Where(
        x => x.FromDate <= effective && x.ToDate >= effective
          && (
                 branches.Any(b => b.Branch == x.Branch)
              || routes.Any(r => r.Route == x.Route)
              || drivers.Any(d => d.DriverNumber == x.DriverNumber)
          )
    );

//
// QUERY: Retrieve all the customers which have effective stop plans and are included in one of the above queries.
//
var customerQuery = vpQuery
    .Join(
        inner: Customers.GetAll(),
        outerKeySelector: x => x.SAPCustomerID,
        innerKeySelector: x => x.SAPCustomerID,
        resultSelector: (vp, c) => c
    );

Where:

  • VisitPlans is of type Repository<VisitPlan> which is using AuthenticationEntities as its DbContext
  • Customers is of type Repository<Customer> which is using AuthenticationEntities as its DbContext
  • Branches is of type Repository<UserBranch> which is using AuthenticationEntities as its DbContext
  • Routes is of type Repository<UserRoute> which is using AuthenticationEntities as its DbContext
  • DriverNumbers is of type Repository<UserDriverNumber> which is using AuthenticationEntities as its DbContext

It doesn't matter that they are of the same type. You must be using a single instance of your DbContext . A single query ( Join in this case) must be done on that single context instance when using entity framework.

Ideally, you should only be using a single DbContext instance that's responsible for making all of the queries to the database. The only reason you would have multiple instances (for a single request) would be if you are using multiple databases.

However, let's assume that you DO need to have multiple context objects. What you would need to do is query each context and pull the results into memory. This can be done by calling .ToList() at the end of each query.

Once the data is memory you can join them together. Here's an example:

var vpQuery = authContext.VisitPlan.Where(x => x == something).ToList();
var ubQuery = permissionContext.UserBranch.Where(u => u == somethingElse).ToList();
var joined = vpQuery.Join(vpQuery, vp => vp.UserKey, ub => ub.UserKey, (vp, ub) => new { Property1 = ub.Something, Property2 = vp.SomethingElse);

However, based on what you posted, you definitely don't need multiple context instances. Most likely your repository code, which is probably unnecessary, is holding or creating a context that is different from the other repositories's context object(s). They should all be sharing a single context instance if you want to use lazy loading and actually generate & execute the query only when needed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM