Reputation: 6202
In my project I have 2 databases: one is my custom database and the other one is ApplicationDbContext
that Microsoft Identity
gives me.
In my Startup.cs
I have this code:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
ApplicationDbContext db, MyContext dbPSC)
{
// ...
db.Database.EnsureCreated();
db.Database.Migrate();
dbPSC.Database.EnsureCreated();
dbPSC.Database.Migrate();
}
I don't know when there is a migration to migrate, right? Then, I have 2 errors:
ApplicationDbContext
raises an error every time the application starts apart from the first timeWhat is the best practise to use? Is it necessary to call the migration for ApplicationDbContext
?
I have removed the Migration
folder. Then, changed the Startup.cs
like
public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
ApplicationDbContext db, MyContext dbPSC)
{
// ...
db.Database.EnsureCreated();
dbPSC.Database.EnsureCreated();
}
but when the application starts, it doesn't create any tables at all. AuditDbContext
is because I use Audit.net
public class MyContext : AuditDbContext
{
public MyContext(DbContextOptions<MyContext> options) : base(options) { }
public DbSet<Message> Messages { get; set; }
public DbSet<AuditMessage> Audit_Messages { get; set; }
#region Common Tables
public DbSet<Country> Countries { get; set; }
public DbSet<AuditCountry> Audit_Countries { get; set; }
#endregion
#region Seed
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Seed();
}
#endregion
}
I tried another solution but it doesn't work. The solution is to use RelationalDatabaseCreator
like the following code
public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
ApplicationDbContext db, MyContext dbPSC)
{
// ...
db.Database.EnsureCreated();
dbPSC.Database.EnsureCreated();
RelationalDatabaseCreator databaseCreator =
(RelationalDatabaseCreator)context.Database.GetService<IDatabaseCreator>();
databaseCreator.CreateTables();
}
As the Migrate()
, the first time the app runs it creates the tables but the second time it raises an error because the tables are already exist in the database.
Upvotes: 1
Views: 4961
Reputation: 6202
Based on the replies you guys sent to me, my solution is to use migration. In the Startup.cs
I added those lines of code (dbPSC is a DbContext
)
dbPSC.Database.EnsureCreated();
if (dbPSC.Database.GetPendingMigrations().Count() > 0)
dbPSC.Database.Migrate();
Upvotes: 1
Reputation: 3636
The issue is most likely that you're calling EnsureCreated()
.
From the docs:
Note that this API does not use migrations to create the database. In addition, the database that is created cannot be later updated using migrations. If you are targeting a relational database and using migrations, you can use the DbContext.Database.Migrate() method to ensure the database is created and all migrations are applied.
So, it's enough to call Migrate()
. But I don't blame you, because EnsureCreated()
is definitely a misleading method name. It does a lot, since it also creates the DB schema that is not even based on migrations, but on the current state of the entities.
But if you don't want to use migrations for Identity context (because you don't extend those entities in any way), then the reverse is true: You don't need to call Migrate()
, and calling EnsureCreated()
is enough to make sure that the schema is created the first time.
Migrate()
necessary?As for what's best practice: Some developers don't like to call Migrate()
at all from code, because they believe that DB schema operations like that should be more controlled (I'm sure you know that you can execute db update from CLI too). It depends on your requirements I guess.
And with respect to this specific case on having a separate database for Identity tables: They most likely will never change, and they especially won't create a migration by themselves. So I'd say that calling Migrate()
on it is unnecessary, besides the fact that it can create and migrate the database if it didn't exist (so it might be useful to keep for that reason; if you're using migrations for that context to begin with).
You can use context.Database.GetPendingMigrationsAsync()
to check if migration is needed. How it's done is that the DB has an EFMigrationsHistory
table that stores the Id of the applied migrations, which can be compared to the migrations files in your solution.
But I think most developers don't call this GetPendingMigrationsAsync()
(or the sync version, for that matter), because you can just call Migrate()
, and if the DB is already updated, no harm is done.
EnsureCreated
I'm not sure how much have you worked with EF, so chances are this is obvious. But Migrate()
is used when you already created migrations with e.g. dotnet ef migrations add <migrationname>
, which is a way to incrementally alter the database schema with a code-first approach.
But if you don't use migrations at all, you have a very simple schema that won't be needed to be altered incrementally with migrations, and you just want to make sure that the DB exists with a schema, then use only EnsureCreated()
, and don't use Migrate()
.
The issue is that if you happen to change your entities, EnsureCreated()
won't update the database; if the database already exists, it does nothing. So you'd have to call EnsureDeleted()
followed by EnsureCreated()
to achieve an up-to-date DB schema without migrations. Which obviously involves losing all your data. This is why migrations are useful. EnsureCreated()
is mostly used for e.g. integration testing.
Btw, you can use the same DB context for your own tables and Identity; I'd hazard to say that's the 'normal' way of working with EF. Of course you could have your specific reasons for separating I suppose.
Upvotes: 5
Reputation: 3726
You don't need to use both db.Database.EnsureCreated();
and db.Database.Migrate();
You need to use db.Database.EnsureCreated();
when you don't have migrations enabled in your application. If you have migrations enabled then only use db.Database.Migrate();
and that would be enough.
But if you don't enable migrations then on every change you have to re create your db. Because "EnsureCreated" only verifies if the db already exists. So better to enable Migrations.
So if you don't want to change anything in ApplicationDbContext so you can use db.Database.EnsureCreated();
but if you want to change something or may be you want to add more fields in AspNetUsers etc then you should enable migrations and use db.Database.Migrate();
Btw you can also add your custom tables in ApplicationDbContext if you want.
Upvotes: 2