Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Entity Framework: One Database, Multiple DbContexts. Is this a bad idea? [closed]

My impression to date has been that a DbContext is meant to represent your database, and thus, if your application uses one database, you'd want only one DbContext.

However, some colleagues want to break functional areas out into separate DbContext classes.

I believe this comes from a good place -- a desire to keep the code cleaner -- but it seems volatile. My gut's telling me it's a bad idea, but unfortunately, my gut feeling is not a sufficient condition for a design decision.

So I'm looking for:

A) concrete examples of why this might be a bad idea;

B) assurances that this will all work out just fine.

like image 727
Josh Schultz Avatar asked Jun 25 '12 21:06

Josh Schultz


People also ask

Can we use multiple DbContext in Entity Framework?

In code first, you can have multiple DBContext and just one database. You just have to specify the connection string in the constructor. Yes you can, but how can you query from different entities from different db contexts?

Why you should not use Entity Framework?

One of the biggest reasons not to use Entity Framework Core is that your application needs the fastest possible data access. Some applications do a lot of heavy data operations with very high-performance demands, but usually business applications don't have that high of a performance demand.

Should I reuse DbContext?

As a result, it's advisable to avoid managing the lifetime of DbContext instances separately from business transactions. Instead, each service method (i.e. each business transaction) should create its own DbContext instance and dispose it at the end of the business transaction (i.e. before returning).

How does Entity Framework handle many to many relationships?

To configure many-to-many relationship Using Data Annotations, you need to create the Join Table in the model. The Join Table BookCategory will have properties for the primary key of both the table. It will have two navigational properties one each for Book and Category class.

What is multiple dbcontext in Entity Framework?

Entity Framework - Multiple DbContext. In this chapter, we will be learning how to migrate changes into the database when there are multiple DbContext classes in the application. Multiple DbContext was first introduced in Entity Framework 6.0. Multiple context classes may belong to a single database or two different databases.

How many dbcontexts do I Need?

Closed 2 years ago. My impression to date has been that a DbContext is meant to represent your database, and thus, if your application uses one database, you'd want only one DbContext. However, some colleagues want to break functional areas out into separate DbContext classes.

Can you have multiple contexts for a single database?

See my answer : stackoverflow.com/questions/8244405/… You can have multiple contexts for single database. It can be useful for example if your database contains multiple database schemas and you want to handle each of them as separate self contained area.

What's wrong with separate DB contexts?

TL;DR: separate DB contexts don't handle relations (FKs) between them well, each context only has information about its own entities. When specifying "-data-annotations" switch on dotnet ef dbcontext scaffold, these informations arent stored in each separate context, but on DB objects themselves.


3 Answers

You can have multiple contexts for single database. It can be useful for example if your database contains multiple database schemas and you want to handle each of them as separate self contained area.

The problem is when you want to use code first to create your database - only single context in your application can do that. The trick for this is usually one additional context containing all your entities which is used only for database creation. Your real application contexts containing only subsets of your entities must have database initializer set to null.

There are other issues you will see when using multiple context types - for example shared entity types and their passing from one context to another, etc. Generally it is possible, it can make your design much cleaner and separate different functional areas but it has its costs in additional complexity.

like image 112
Ladislav Mrnka Avatar answered Oct 13 '22 19:10

Ladislav Mrnka


I wrote this answer about four years ago and my opinion hasn't changed. But since then there have been significant developments on the micro-services front. I added micro-services specific notes at the end...

I'll weigh in against the idea, with real-world experience to back up my vote.

I was brought on to a large application that had five contexts for a single database. In the end, we ended up removing all of the contexts except for one - reverting back to a single context.

At first the idea of multiple contexts seems like a good idea. We can separate our data access into domains and provide several clean lightweight contexts. Sounds like DDD, right? This would simplify our data access. Another argument is for performance in that we only access the context that we need.

But in practice, as our application grew, many of our tables shared relationships across our various contexts. For example, queries to table A in context 1 also required joining table B in context 2.

This left us with a couple poor choices. We could duplicate the tables in the various contexts. We tried this. This created several mapping problems including an EF constraint that requires each entity to have a unique name. So we ended up with entities named Person1 and Person2 in the different contexts. One could argue this was poor design on our part, but despite our best efforts, this is how our application actually grew in the real world.

We also tried querying both contexts to get the data we needed. For example, our business logic would query half of what it needed from context 1 and the other half from context 2. This had some major issues. Instead of performing one query against a single context, we had to perform multiple queries across different contexts. This has a real performance penalty.

In the end, the good news is that it was easy to strip out the multiple contexts. The context is intended to be a lightweight object. So I don't think performance is a good argument for multiple contexts. In almost all cases, I believe a single context is simpler, less complex, and will likely perform better, and you won't have to implement a bunch of work-arounds to get it to work.

I thought of one situation where multiple contexts could be useful. A separate context could be used to fix a physical issue with the database in which it actually contains more than one domain. Ideally, a context would be one-to-one to a domain, which would be one-to-one to a database. In other words, if a set of tables are in no way related to the other tables in a given database, they should probably be pulled out into a separate database. I realize this isn't always practical. But if a set of tables are so different that you would feel comfortable separating them into a separate database (but you choose not to) then I could see the case for using a separate context, but only because there are actually two separate domains.

Regarding micro-services, one single context still makes sense. However, for micro-services, each service would have its own context which includes only the database tables relevant to that service. In other words, if service x accesses tables 1 and 2, and service y accesses tables 3 and 4, each service would have its own unique context which includes tables specific to that service.

I'm interested in your thoughts.

like image 36
Francisco d'Anconia Avatar answered Oct 13 '22 18:10

Francisco d'Anconia


Distinguishing contexts by setting the default schema

In EF6 you can have multiple contexts, just specify the name for the default database schema in the OnModelCreating method of you DbContext derived class (where the Fluent-API configuration is). This will work in EF6:

public partial class CustomerModel : DbContext
{   
    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.HasDefaultSchema("Customer");

        // Fluent API configuration
    }   
}

This example will use "Customer" as prefix for your database tables (instead of "dbo"). More importantly it will also prefix the __MigrationHistory table(s), e.g. Customer.__MigrationHistory. So you can have more than one __MigrationHistory table in a single database, one for each context. So the changes you make for one context will not mess with the other.

When adding the migration, specify the fully qualified name of your configuration class (derived from DbMigrationsConfiguration) as parameter in the add-migration command:

add-migration NAME_OF_MIGRATION -ConfigurationTypeName FULLY_QUALIFIED_NAME_OF_CONFIGURATION_CLASS


A short word on the context key

According to this MSDN article "Chapter - Multiple Models Targeting the Same Database" EF 6 would probably handle the situation even if only one MigrationHistory table existed, because in the table there is a ContextKey column to distinguish the migrations.

However I prefer having more than one MigrationHistory table by specifying the default schema like explained above.


Using separate migration folders

In such a scenario you might also want to work with different "Migration" folders in you project. You can set up your DbMigrationsConfiguration derived class accordingly using the MigrationsDirectory property:

internal sealed class ConfigurationA : DbMigrationsConfiguration<ModelA>
{
    public ConfigurationA()
    {
        AutomaticMigrationsEnabled = false;
        MigrationsDirectory = @"Migrations\ModelA";
    }
}

internal sealed class ConfigurationB : DbMigrationsConfiguration<ModelB>
{
    public ConfigurationB()
    {
        AutomaticMigrationsEnabled = false;
        MigrationsDirectory = @"Migrations\ModelB";
    }
}


Summary

All in all, you can say that everything is cleanly separated: Contexts, Migration folders in the project and tables in the database.

I would choose such a solution, if there are groups of entities which are part of a bigger topic, but are not related (via foreign keys) to one another.

If the groups of entities do not have anything to do which each other, I would created a separate database for each of them and also access them in different projects, probably with one single context in each project.

like image 58
Martin Avatar answered Oct 13 '22 20:10

Martin