3

I have a class library project containing an EF Core db context. This is part of a framework.

I want to extend this context but without making changes to the framework project. The second context would use the same database.

I created another db context in a different class library (something similar to this). This works ok, I can make queries and create migrations separately from the other context.

But for example if I have a User entity in the first context and UserBooks in the second, when I try to make a join between the two contexts it doesn't work, getting exception

System.ArgumentNullException: Value cannot be null. Parameter name: entityType

This is a known issue.

Also tried with latest NuGet package 3.0.0-preview3.19153.1 but the only difference is that the error message is better

Cannot use multiple DbContext instances within a single query execution. Ensure the query uses a single context instance

Is there any way to

a. make joins between two contexts

or

b. extend a context in a separate project without making any (or minimal) changes to the 'main' context

SzilardD
  • 1,611
  • 2
  • 22
  • 40

2 Answers2

2

Two db-contexts means two connections. You can't join through different connections.

1. Load Data into Program

You can load you data to your program and join there. Be aware, that this is dangerous on big datasets.

var customers = new Ctx1().Customers.ToList(); // ToList() loads the data into your program
var orders = new Ctx2().Orders.ToList();

// Now we're not in the db anymore. We can do a simple List-Join:
customers.Join(orders, c => c.CustomerId, o => o.CustomerId, (c, o) => new { Customer = c, Order = o });

2. Extend your existing Context

If you want to stick to one connection you could simply extend your Context. Be aware that you're in one transaction this way.

public class FrameworkContext : DbContext
{
    public DbSet<Customer> Customers { get; set; }
}

public class ExtendedContext : FrameworkContext
{
    public DbSet<Order> Orders { get; set; }
}

Now you're allowed to join:

var ctx = new ExtendedContext();

var myResult = ctx.customers.Join(ctx.orders, c => c.CustomerId, o => o.CustomerId, (c, o) => new { Customer = c, Order = o });
kara
  • 3,205
  • 4
  • 20
  • 34
  • 1
    I know, but I would need to retrieve all data from db, then join on the 'client' side. I would like the join to be made on the db in a single query – SzilardD Mar 29 '19 at 07:20
  • This may be OK for small datasets, but it is definitely not the recommended approach. – Knelis Mar 29 '19 at 07:24
  • If it is one Db and one connection can be used, the obious solution is to extend the context. Added the 2nd solution. – kara Mar 29 '19 at 07:41
1

You could make your second context inherit the first.

public class MyFirstContext : DbContext
{
    public DbSet<User> Users { get; set; }
}

public class MySecondContext : MyFirstContext
{
    public DbSet<UserBook> UserBooks { get; set; }
}

Of course, your second context could be in a different assembly. Now you only need MySecondContext in your application. You will be able to join Users and UserBooks.

Knelis
  • 6,782
  • 2
  • 34
  • 54