Entity Framework 6 database migrations for isolated multi-tenant setup - c#

I understand database migrations might not be the best method to deploy this solution, so any suggestions would be greatly appreciated.
I have x identical database schemas, one per client.
I also have models for each one of these databases and am able to deploy a migration which creates a new clone. Up until this point, I had been using PHP and scripts to loop through all the schemas and update any changes to the structure. We are moving over to C# and EF6 due to Web API 2 and attribute routing.
My question is; Is there a way to:
Deploy a build command which will do what update-database would do for a migration, and pass it a database name (in order to create a new clone schema of the account database?
Deploy a build command which might do what update-database would do recursively through each one of the target databases?

"I have x identical database schemas, one per client "
and
"I also have models for each one of these databases"
Did you mean I also have models for each one of these Schemas?
Ef model entities are linked to a Schema/TableName.
entity.ToTable("tableName", "schemaName");
So if each client gets their own schema, then each model has all tables in that schema and the client gets their own model.
So how do I run update-database on each Context model. I another way of looking at the issue.
So the answer lies with how you are tracking the schema per client info.
Powershell migrate.exe approach might be interest for your so that you can trigger migration on many context models.
Custom migration operations might also be interesting. Rowan is an EF developer.
EDIT: based on Auto Migration comment, this is worth a look
Managing migration triggers in code

Related

Entity Framework Core scaffold additional tables not context

From Microsoft documentation:
https://learn.microsoft.com/en-us/ef/core/get-started/aspnetcore/existing-db
When trying to reverse engineer your models and dbcontext from an existing database, you can run a command like this:
Scaffold-DbContext "Server=myserver; Database=mydatabase; Integrated Security=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Entities -Tables FirstTable, SecondTable
This will create me two models and a dbcontext based on my connection details.
If I want to come back later and add another few tables, is it possible to run the same command, or something similar with different parameters that will not create the dbcontext again, as I already have this from my initial scaffold.
Currently we are running the command over and over again and deleting the context each time, or manually building any new models based on the database tables. It seems counter productive.
In Entity Framework 6 and below we would just maintain the edmx diagram but obviously this is not included in EfCore.
It's logged as a request with the EF Core team, but has been pending for a good while now.
Github link
In EFCore, there really isn't support for database first design. The scaffolding feature is only meant to be a one-time operation to build your code first models/contexts so that you don't have to hand code them in order to get started using EF. Once run the first time, you should be moving to EF Migrations instead of scaffolding to deal with additions/updates/deletes to the schema.
Here is MS documentation for migrations: https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/
You can just re-generate the files again, all the generated classes are partial, and you can implement any customizations in parrallel partial classes.
EF Core Power Tools allows you to just generate the POCO classes or just the DbContext.

Entity Framework Core Database First

My team has inherited a database application that contains hundreds of tables. The application uses Entity Framework and takes a database first approach for development. Our current process is to pull a table or two at a time into the edmx using the Update Model From Database... tool.
We are considering making a new API with .Net Core, but as far as I can tell from the research I have done, there is no equivalent process in the Entity Framework Core tools. The closest thing I can find is to reverse engineer the entire database with Scaffold-DbContext, and then use migrations for all future database changes. We can't scaffold the entire database, because some of the tables have errors, and fixing all those errors is not a viable option for us right now.
I have found that I can supply a list of tables that I want scaffolded with the initial Scaffold-DbContext call, but I'm not sure if migrations can be used in a similar way to the Update Model From Database... tool. Can I use migrations to add tables that already exist in our database? If not, what other options should I be looking at?

Create SQL View With Entity Framework 6 Code First

I am new to Entity Framework 6 Code First and am trying to perform what I thought would be a simple task. I want to create a SQL View and then have an Entity in my database context that I can use to query the view.
I have tried articles such as this but the key difference in my case is that the SQL View is not an existing view coming from another existing database.
I examined the proposition made in this article but it seems like overkill to me that I would need to create some extension methods to do something as simple as create a view/entity combo and use it in my database context.
Am I missing something? I know it would be much easier if I weren't using Code First but please keep in mind it's Code First and I am trying to create a view, not reuse one from an existing database.
Colin and Kevin, Thank you for the link to your answer on the other post and your concise answer. I have used several resources to finally create a queryable entity based on a new SQL view. Just in case anyone else is new to EF 6.0 Code First and is just getting their feet wet, I do have a few steps that will hopefully benefit others in the future.
It may seem obvious to more seasoned Entity Framework developers, but in order to execute the 'Migration' approach you need to disable automatic migrations and actually dive into the guts of the Code First Migrations inner workings. Since automatic migrations is turned on out of the box, I had already created a fairly complex database with seed scripts all relying on automatic migrations and rebuilding the database on every run of my application. This post helped me wipe my migrations history and get to square 1 with automatic migrations turned off (I went with the web.config approach in case you were wondering)
After I had cleared my migrations information, I deleted the mdf from within solution explorer. That guaranteed that I wouldn't run into any problems when running Update-Database (further down the list of steps).
In the Package Manger console, I then executed Add-Migration Initial to generate an "Initial" migration. The result of this was the editable Up and Down methods as described in Colin's answer. I then followed the steps in Colin's answer by commenting out the table create statement (Entity Framework tries to create a table but we really want to create a view and map it to the Entity) and inserting my own view create sql statement at the end of the Up method. It's important to put the create statement after the creation of any tables that it may depend on. I also performed my Seed activities in the Configuration.Seed method instead of in my Context's Seed method. I see how this would be important if you were dealing with multiple migrations. Finally, as Colin suggested I added the table mapping to my context's OnModelCreating event.
The final step in this was to actually apply the migration to the database. In order to do that, in the Package Manager console you execute the Update-Database command. That statement will rebuild the database with the "Initial" migration you created and edited in earlier steps.
It still surprises me that I need to do all of this custom work to create a view and map it to an entity with Code First, but at the end of the day it was helpful in getting me started on migrations as you can only rely on the "automatic migrations" for so long anyways.
You can manually add the sql to create the view to a migration then consume it as per your first link.
The answer in the link provided by Colin does the job.
In case there are lots of views to be created, it can be a good idea to save the view queries in separate files and add them in a resource (.resx) file instead of hard-coding the sql queries in the Migration Up() method.
For e.g.
public override void Up()
{
Sql("ResourceFileName.ResourceName");
}
instead of hard coding like
{
Sql("EXEC ('CREATE View [dbo].[ClientStatistics] AS --etc");
}

Removing all automatic migrations and creating code-based migrations in their place

As you're about to learn, I'm inexperienced with building applications using ASP.NET MVC, I'm deliberately coming out of my comfort zone in order to learn.
I'm using code-first migrations with Entity Framework, and I created a Train.cs model and used the Enable-Migrations command. For some reason I thought it would be a good idea to enable automatic migrations in Migrations/Configuration.cs and I continued developing with automatic migrations enabled for a while.
Then I read somewhere that automatic migrations are generally a bad thing, so I disabled them. My Train model needed a new field called Description, so I added it. I ran Add-Migration AddDescriptionToTrains, then did Update-Database. It's throwing me back this error:
Cannot find the object "dbo.Trains" because it does not exist or you do not have permissions.
I think this is happening because I deleted the mdf file that was under App_Data in order to wipe out my database and start fresh, and it doesn't have a migration to create the Trains table before it tried to add a Description field to it.
Basically my question is, can I delete all of my migrations down to InitialCreate, and then just generate one from my model? I only have one model so it should only create one migration. I just want to create the migration from the entire model, not what it thinks has changed in the model.
In short, yes you can. In my experience, anytime you can delete the content of the _MigrationsHistory table and restart generating migrations.

Prefix tables with entity framework automatic code migrations

I started a new project C#, and I used the "enable-migrations" command in the package console window. This naturally added migrations to my project. I then set automatic migrations to true, so that as I call "update-database" it will create my tables for me with all keys and that.
The only problem is that I have multiple websites where want to do this, which all use the ASP.NET membership provider to login. Which through automatic code migrations create a bunch of account tables for me to use. But the tables are all called the same, so if I do this targeting the same database for different sites they will overwrite eachother. So the question I got is this: How can I specify a prefix for my tables created by the entity framework?
I've seen several ideas on how to do this while searching, but they didn't work for me (the necessary properties wasn't there for some reason and so on.)
Thank you
Xenoxsis
I'm not sure how do you plan to do just that - if I'm getting it right you'd want to keep one database (shared) in between number of web sites - yet, have each site has its own membership tables, named differently, with different prefixes, right?
First problem is that for each Db/table name change - you need a 'code to match' - i.e. code first entities and code, the 'migration table' in the Db - and tables are all in sync - so it could all work together as it should. In that sense, just changing script or table names in Db won't work. It has to be done at the level of attributes (as #Steven suggested) or fluent configuration.
Which in your case, it means that somehow you'd need to 'build' separate configurations for each site, deploy them separately (code) to each site - and build one mega Db that contains all the small variants of each merged together.
That's going to be tough to manage - but you could try (what I described above) - I have no idea if it'd work (as this requires lot of 'infrastructure' to try this one) - but maybe along these lines...
put Table attributes (or via fluent config)
Build code - 'vary' the Table names for each - and rebuild (ideally you might need to employ some tool, code-generator to do this automatically in a batch - i.e. you build, copy files externally, change names and repeat)
Build 'migrations' for each case (Table name) also - save migrations
as files - and also do Update-Database -Script to save the actual
scripts for each case (important).
Save each migration - or we can
say a 'script' to represent.
Once done - you'd need to merge the
migrations - scripts - into one big master script - i.e. remove the
identical set of tables (leave just one of course) - and copy all
different sets for membership tables.
Remove the migration table
from the database - as that'd surely be out of sync and won't let you
do anything (or there is also a flag in code I think to just ignore
that, don't have it right now). For details see below in my other
post.
Deploy one master Db - using script you created
Deploy the
specific code - to each of the sites.
Pray it'd all work :)
There must be something smarter - but on the other hand, migrations are not made to work for such scenarios, so it's going to be hard if not impossible to pull this off.
Some general info that might help...
How to synchronize migrations with existing databases - geared toward production scenarios, maintaining Db-s and CF to match. It's not exactly what you need but has a detailed description, possible ways to resolve this which I wrote a while ago...
MVC3 and Code First Migrations - "model backing the 'blah' context has changed since the database was created"
To summarize...
What works for me is to use Update-Database -Script
That creates a script with a 'migration difference', which you can
manually apply as an SQL script on the target server database (and you
should get the right migration table rows inserted etc.).
If that still doesn't work - you can still do two things...(more inside)...
I don't know of anyway to make Entity Framework do this automatically across all entities. But you could force a table name, or schema using attributes or fluent API to get the desired effect. For example:
[Table("[put prefix here]_Users", Schema = "[put schema here]")]
public class User {
// ...
}

Categories

Resources