Entity Framework Core updating database withing project - entity-framework-core

I have made a blazor project that is hooked up to a database that pulls information via a form. I have also gone ahead and added a migration for this DB. Now our production database has new tables being made every 90 days. My question is for EF Core is there something I can write in the code that would update my solution with the newest Db changes and runs once a day? I have read up on EF Core scripts but could not find any concrete examples. Any advice would be grealy appreciated.

Assuming it is a Blazor Server app, in your Program.cs you can migrate your database every time the application starts (if there are new migrations) by doing something like this:
var host = CreateHostBuilder(args).Build();
using var scope = host.Services.CreateScope();
var services = scope.ServiceProvider;
var context = services.GetRequiredService<YourDbContext>();
await context.Database.Migrate(); // or MigrateAsync();
host.Run();

Related

EFCore: migrations and initial DB creation

I'm using EFCore (recently migrated from EF) to do code-first DBs with coded migrations. EFCore updates the context model snapshot whenever I create a new migration. So when I create a new DB from scratch using
using (var db = new AudmDatabaseContext())
{
if (!db.Database.GetService<Microsoft.EntityFrameworkCore.Storage.IRelationalDatabaseCreator>().Exists())
{
db.Database.EnsureCreated();
}
}
I have the current DB structure. However, when I have an existing system, I need to run migrations
using (var db = new AudmDatabaseContext())
{
if (db.Database.GetService<Microsoft.EntityFrameworkCore.Storage.IRelationalDatabaseCreator>().Exists())
{
var pendingMigrations = db.Database.GetPendingMigrations();
if (pendingMigrations.Count() > 0)
{
db.Database.Migrate();
}
}
}
}
Now, imagine I created a new DB using my DB creation code. Then at some later point, I'm changing the DB schema, so I need to run migrations. But, when I do that, I get all migrations as pending, and the migrator tries to make changes to the DB schema that have already been made - which obviously doesn't work. (note that my initial migration has all code commented out as otherwise it would create the entire DB again but that's already being done with db.Database.EnsureCreated())
So what's the recommended approach here? I need to be able to create new DBs for new installations for my software, and I need to be able to migrate (so I actually set up my app to execute migrations automatically on startup to never miss any changes).
The most obvious that comes to mind would be to have some kind of flag that tells the migrator to run the migrations but actually not execute any sql code when doing the initial create - so a newly created DB would already appear to be fully migrated to the migrator.. and when at some later point I have new pending migrations, only these new pending migrations that have been added to the code since I created the initial DB would be executed.
I'm just curious what other people are doing since I seem to be unable to find the recommended approach to this problem in the official documentation.

Generating a database script from entity framework code-first model

I'm using entity framework with code-first (primarily because with RIA Services, you need to have some form of the code classes anyway for additional attributes).
I want to get a database generation script to easily update the visual studio database project. I don't want to use ef migrations, I prefer the database projects.
I can use something like
string sqlscript = (context as IObjectContextAdapter).ObjectContext.CreateDatabaseScript();
at runtime, but I want to have a convenient method to get the script without running the project in some way, and without using migrations.
Does anybody have any ideas?
I'm using ef4.1 and ef5 in different projects.
[EDIT: One way of answering this question would be a way to call above line from the package manager console.]
One way is using the Entity Framework Power Tools. They add a context menu entry for the file containing the DbContext class which generates a DDL file for the database.
Another way is using LinqPad. After opening the dll in LinqPad, one can execute the code snippet given in the question in a query:
(this as IObjectContextAdapter).ObjectContext.CreateDatabaseScript()
Both ways are slightly inconvenient though as they require third-party tools.
I have enabled migrations but I always do get the script at runtime without using the Package Manager Console to update the database as I have dynamic entities that can only be discovered at runtime depending on what references are included in the project.
The code to get the script looks like this:
var config = new DbMigrationsConfiguration<MyContext> { AutomaticMigrationsEnabled = true };
var migrator = new DbMigrator(config);
var scriptor = new MigratorScriptingDecorator(migrator);
string script = scriptor.ScriptUpdate(sourceMigration: null, targetMigration: null);
You can also generate custom queries using the `ObjectQuery class.
Here's an example:
var query = from emp in context.Employees
select emp;
var sqlScript = ((ObjectQuery)query).ToTraceString();
An approach you can consider is to use ef migrations to generate the script, then use MSBuild post build task to copy the script over to the database project at build time.

Entity Framework 4.3 migrations on existing "Shared" database

We have a huge database with different database schemas for different web applications.
For example: WebApp1 uses Schema1.Tables. WebApp2 uses Schema2.Tables and so on.
Now, I am developing a new web application (WepApp3) which will use Entity Framework 4.3.1. WebApp3 should only be concerned with Schema3 and use only those database object which are part of Schema3. If i create some Entities in WepApp3, How do i migrate these entities to database as schema3.tables? Do i still need to do Initial Migration?
Please help.
I don't think it's possible to have multiple EF models in the same database. EF shouldn't try to touch tables that are nothing to do with its model, but if you wanted to add another EF app to the same database you'd run into trouble because they'd try to share the same MetaData tables.
When generating new models using code-first, you can specify which schema they should be part in the DbContext:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<MyEntity>().ToTable("MyEntity", "Schema3");
}
Is it an option to migrate your schemas out into different databases if there are no shared apps?
It seems to WORK. I started with an existing database. created an mvc app (app1) with couple of models. I then created a schema for this app in database. I specified schema for the models as per your comment. Then I used the power of code based migration script to update the database. Migration script created 2 tables under the new schema without corrupting existing stuff. I noticed EF created __MigrationHistory table with a row with change info.
Then i created another app, a new schema and repeated the migration process with a little tweak in migration script. The script had code to re-create 2 tables of app1. i deleted that code from script. EF then successfully created new tables under new schema and also created new row in __MigrationHistory table with info about new changes. All existing stuff remain unchanged including data.

Refreshing Data Using Entity Framework

I'm trying to use Entity Framework to query database and I have following code that I'm using to get some data.
var students= MyEntities.Students.Where(s => s.Age > 20).ToList();
This code works fine and returns correct data. However, if I run this code, then go to database and update records to change the data this code should return, and then re-run this code without shutting down the app, I'm getting original data.
I'm pretty sure it used to work fine, but now this doesn't refresh data.
No it never worked. This is essential behavior of entity framework (and many ORM tools) called identity map (explanation here).
If you run the query on the same context you will not get your entities updated. It will only append new entities created in the database between running those two queries. If you want to force EF to reload entities you must do something like this:
ObjectQuery query = MyEntities.Students;
query.MergeOption = MergeOption.OverwriteChanges;
var students = query.Where(s => s.Age > 20).ToList();
You are running into issues because EF caches data, so if the data changes behind the scenes, and you dont dispose/reopen your context you are going to run into issues.
The general rule of thumb is to keep the lifetime of the context as short as possible, to circumvent issues like you just mentioned.
Please do not disregard what I said above, but if you would like to force a refresh from the DB you could use the Refresh() method.

EntityFramework 4.1 EdmMetadata ModelHash

I am trying to deploy an EF 4.1 Code-First application from Dev to Test without letting EF "blow-away" the entire database.
I copy the database over from Dev to Test, rebuilt the application and deploy the code. For EF still thinks it needs to rebuild the DB or that the data models are different. How can I predict which ModelHash the application will want to see when it is deployed to a different server?
As far as I can tell, the only difference between the two builds is the configuration I use to build them (one is Test, and the other Dev).
If you want someone else to use your DB and now have to Re Create it each time.
I set my DB Initializer = CreateDatabaseIfNotExists
Then delete the "EdmMetadata" table from the DB.
I am not sure if this is the "correct" way to do it. But it works for me.
System.Data.Entity.Infrastructure.EdmMetadata.TryGetModelHash(DbContext)
will return you hash string of the model.
That's what the EF want to see in ModelHash column at EdmMetadata table.