Multiple DbContexts in a single project - entity-framework

I am working on a project using EF5 and am lost when it comes to adding a second DbContext to the project. I have created the DbContext but my migrations do not work. How do I make sure that my second DbContext (totally separate database) is set up and I can start updating the database?
Doing a "Enable-Migration" fails because a Configuration file/class already exists for my previous DbContext.

You should split your data access libraries into separate projects. This way you can treat each one separately, and they have no danger of conflicting with each other (so long as you call them something different). I would also suggest making sure they are in unique namespaces.

Related

Trying out Entity Framework Code-first; is the usage any different from Database-first?

When working with EF (v4,5,6) I have always used Database-first (I was mistakenly under the impression this was the only way to generate Entities from existing tables, EDMX, etc). But today I tryed Code-first, and it can also generate the POCOs (in a different way, no EDMX, different connection string, less cr8p lying around, etc..!)
So far, the usage of EF for CRUD appears to be exactly the same, can anyone who has used both please confirm there is nothing different (in usage), or gotchas I should be aware of?
And a supplementary question is, can I generate both in the same project ? (Not that i want to, but existing proj has EDMX within a folder, can I create another folder and generate Code-First Entities (different set of tables only), so i end up with DBContext and DBContext2 ?
Yes, the usage is the same. If you check the generated code you'll see they use the same System.Data.Entity.DbSet properties and they both inherit from the same System.Data.Entity.DbContext class.
Yes, you can generate both in the same project, but does not makes much sense, because you have to maintain both of them if the DB changes.

Changing Entity Framework Entity Class Without Changing Schema

I have an application already in production using EF 5.0. I'm about to start on the next major revision. But before I do that, I'm trying to clean up a lot of my existing code.
One thing I want to change, is use a different class for one of my table entities. The new class is functionally identical to the previous. The only real difference is the name. E.g. ReceiptEntity will become Receipt.
This is to help simplify things, and stick to a simple naming convention.
However, EF Migrations are wanting to drop-recreate the table. This is not an option because the application is already in production. And I cannot allow for any data-loss.
Is there any way to change the Entity type without recreating the table that would make EF happy?
I was able to fix this by altering the generated migration.
The generated migration tried to create a table(one that already existed), then immediately drop it(which would of resulted in the data-loss).
I deleted all of the generated code, and simply 'Update-Database'ed an empty migration, and this solved the problem for me.

Code First Migrations for dynamically assembled model

My database model (sometimes referred to as "context") is dynamically assembled at startup based on which services and/or plugins are installed. Plugins and services export their model definition fragments through my IoC container and the application core picks them up and runs them when the DbContext.OnModelCreating method is called.
The question is: Can I (and how do I) use Code First Migrations with this setup?
(below is more information on what I've tried and what particular problems are)
In my previous project, the database was inherited from some old code so we couldn't use any of the Code First database generation stuff anyway. We simply kept a long line of delta scripts and executed them manually on deploy (it was a single-host kind of project).
Now I'm starting a new project, and this time, the database is brand new, ready for Code First to play with. Initially, I was all excited about Code First Migrations, seemed like the way to go. Until I actually tried it. The initial attempt, quite obviously, failed due to the absence of an explicitly defined DbContext in my project.
So far, it looks like the only viable option is to manually code migrations, with which I am perfectly fine. However, it turns out that this is not as simple as just creating a few classes inherited from DbMigration.
After some experimentation on a small test project, I was able to find out that the migration autogenerator adds an implementation of IMigrationMetadata, which, among other things, contains a hash of my model as the values of the Source and Target properties. Presumably, this hash is then used to identify a path across migrations from the "current" state of the database (as recorded in the __MigrationHistory table) to the newest state as defined by the model in code. This totally makes sense, but...
Naturally, I have no idea where to get that hash for my model, which makes me unable to implement IMigrationMetadata on my migrations.
On the other hand, I see that the metadata interface is not included in the DbMigration class itself, which makes me think that it might be optional. It then follows that migrations can actually work without the hash values, but the question is - how?
All the information I could find on the internet is just simple, very basic tutorials. No information on how to create migrations manually (and whether it's even supported). No documentation on how it actually works and how to extend it. And it is not quite obvious from outside.
I am ready to resort to ILSpy at this point, but the whole EF is so complex that I fear I may not be able to find what I need in reasonable time.
Here are a few ideas that you could pull together to find a solution that works for you. I realize I mentioned some of these in our other thread, but I'm including them here for others reading this question.
Automatic migrations allow Code First to automatically calculate and apply changes to the database.
You can write your own code to generate and apply migrations. I've written a post about applying migrations and the MigrationsScaffolder class will help you create migrations.
When you run the project , an extra table is created in the database.
EdmMetadata table
The hash is always created with the help of EdmMetadata Entity and the current code first model. It is SHA-256 hash stored in the EdmMetadata table of the database. You can get it from that table.
Methodology to be followed will be:
Get the hash of the current model using
var hash=GetModelHash(OldContext);
Check whether the model in the code (new model) is compatible with the model in database(old model) using
CompatibleWithModel(hash,CurrentContext,ObjectContext)
This method returns bool.
If it is not compatible, then delete the existing tables in the database.
Create new tables
Save the current hash to the databse
Seed the data.
The code may look like:
{
var objectContext = ((IObjectContextAdapter)context).ObjectContext;
var modelHash = GetModelHash(objectContext);
if (CompatibleWithModel(modelHash, context, objectContext))
return;
DeleteExistingTables(objectContext);
CreateTables(objectContext);
SaveModelHashToDatabase(context, modelHash, objectContext);
SeedData(context);
}
Be sure to make the class inherited from
IDatabaseInitializer<T> where T:DbContext

EF Migration - One database, two projects

We are using EF Code First with manual migration (AutomaticMigrationsEnabled = false;). The problem is that we need to share one database between two projects.
Project-A
---DbContext-A
---------Model1
---------Model2
---------Model3
Project-B
---DbContext-A
---------Model2
---------Model3
---------Model4
Some of the migration files are the same but some of them are different. For example: Project-B needs Model4 but Project-A doesn't..
Currently, If I update the database with one migration, DbContext will not work in other project.
What would be the best way to handle this scenario?
My feeling is that this is working against the intentions with migrations. I think that you should break out the DbContext, the entities and the migrations to a separate assembly that is shared between the two projects.
If that's not an option, you have to disable the compatibility check with the model. The compatibility check is done as part of the IDBInitializer.InitializeDatabase implementation, which is responsible for calling Database.CompatibleWithModel, so writing your own custom DB Initializer that does nothing would get you past that step. This also means that you take over the responsibility of ensuring that the database is compatible with the model. EF can't help you any more.

Design Decision: Multiple EF EDMX Files

If you have used the Entity Framework then you know the EDMX is cool. You also know it can become HUGE and almost unmanageable.
When it gets large, it is tempting to create a second EDMX or third - even one for each Schema in your database (just as an example).
Such a seperation would help with organization of your EDMX, but it could seperate the context of entities in the same namespace.
Moreover, seperate EDMX files can create a situation where a JOIN operation across EDMX files results in excessive, redundant database communication.
But, the fact remains, the larger the EDMX, the more difficult it is to use. The more difficult it is to ensure it is correct. The easier it is to break.
Do you break your EDMX files apart? Do you have a rule of thumb for when to it?
One example for the need to split your EDMX would be
if you have a group of entities that are used in more than one project,
while others are project-specific and you are willing to forsake having navigation properties between the parts (and remain with only exposed FKs).
You can automatically merge the EDMXs into one if you want to maintain the separately, but open up a context to them all and query as one. This requires that they share the same namespace.
We've only gone as far as needing to use two separate EDMX in a single solution. This separation occurred for us with an EDMX for domain specific model entities and another for those more common across all of our solutions (Payment as an example). Logically you could say this for us was at the db schema level although that wasn't the hard rule of the separation.
Whilst we didn't have a requirement for joins across them we did need transactions. We accomplished this with a reusable UnitOfWorkContainer that would wrap the EF contexts within a TransactionScope. The contexts would be injected through DI into the container and we would only use the TransactionScope if there was more than one context held in the container.
The container itself implemented our IUnitOfWork interface so it was dead easy to plug into the existing codebase.