Registration problem of IRepository with MultiDbContext and joins #6896
Hi, we would like to share an issue when you have multiple dbcontext and you want to join tables owned by two different context. Is not simple to explain so we have done a poc to better understand.
Scenario: Multiple DB Context referencing same table
ContextA DbSet<MyTableA> DbSet<MyTableB> ContextB DbSet<MyTableC> DbSet<MyTableA> In ContextB IRepository<MyTableC> TableC IRepository<MyTableA> MyTableA Join TableC on TableA <- Error Null reference for TableA because in registered only in ContextA
Problem The table is registered only on the first context discovered and when an other context requires access to the same table, his context is missing the table. You can't join table owned by two different contexts, also if you registrer the dbset in both of them.
Desired behaviour Register the dbset in both context
Workaround Register a DbSet using an empty class that extends the firts DbSet.
You can find the code to download here
Hi @maliming sorry I didn't report the link to the previous thread
What you say is what we are doing now and you said that is a valid solution, but is a workaround and we are loosing the IRepository behaviours. Every "deviation" to the standard path/architecture can cause problems in the future if the implementaion changes, and as our project is very big, we dont' want to take the wrong way. How would you solve the problem?
There is a flipside with this workaround? Is compatible with what have you planned for the next releases ? This is our main fear.
Yes @ismcagdas you are right. Due to the fact that is not possible join two different context, we have created a new QueryContext that has the responsability to make all cross context queries. The use of
dbContextProvider.GetDbContext().Set<YourEntity>()....is suitable for our requirements, but the side effect is that another context fails to retrive the correct IRepository because is registered twice.
What we think that could resolve the issue is the possibility to NOT register the IRepository for all the dbsets on the QueryContext but only for the all other contexts (For example with an attribute in the context that skips the registration). This solution could also resolve the huge problem of very slow startup when you need to resolve many respository in ctor.
Hi @ivanosw1, does your
QueryContextrequire any database write operation?
if it does not, you can try to change your QueryContext to inherit from
You might also need to enable query filter in
Hi @ryancyq and @ismcagdas We have investigated more deeply in source code and probably found a solution thas is also an ANZ standard. Please tell me what do you think about.
- Use for every crud operations your contexts as usual (: AbpContext and IRepository).
- For the context used only for for queries, use :AbpContext but with a different AutoRepositoryType
[AutoRepositoryTypesAttribute(typeof(INullRepo<>), typeof(INullRepoKey<,>), typeof(NullRepo<>), typeof(NullRepoKey<,>), WithDefaultRepositoryInterfaces = false)]
INullRepo, INullRepoKey don't do nothing so the IRepository is not registered twice and at runtime is used the only one configured in the owner repository (so only one class and one configuration)
Our tests look good but I would like to hear some thoughts from your team. Thank you.