DBContext overwrites previous migration - c#

I currently have two DbContexts, ApplicationDbContext and CompanyDBContext. However the problem is that when I run my MVC web application only the CompanyDBContext gets reflected on the database and I see none of the implementation made in ApplicationDbContext being shown in the database. Both my contexts use the same connection string. The ApplicationDbContext was auto-generated when I created my MVC application as I had selected Individual accounts
Currently the ApplicationDbContext looks like this
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("DevConnection", throwIfV1Schema: false)
{
}
public static ApplicationDbContext Create()
{
return new ApplicationDbContext();
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Ignore<CompanyDetails>();
}
}
and here is my CompanyDbContext
public class CompanyDBContext : DbContext
{
public CompanyDBContext() : base("DevConnection")
{
}
public DbSet<CompanyDetails> companies { get; set; }
}

I would delete the migrations you have now if you dont need them then use the command below to enable them separately by specifying their names and directories, so they are created separately.
enable-migrations -ContextTypeName MyCoolContext -MigrationsDirectory MyCoolMigrations
http://www.mortenanderson.net/code-first-migrations-for-entity-framework

I was curious, so I looked around, and it seems like the solution for migrations and multiple DbContexts is to have a single DbContext that serves as a complete representation of the database through which initialization and migration is handled, and disable database initialization in the constructor of all other DbContext classes.
You could do this through a combination of Database.SetInitializer and an explicit call to DbContext.Database.Initialize()
Sources
Entity Framework: One Database, Multiple DbContexts. Is this a bad idea?
Shrink EF Models with DDD Bounded Contexts

It's seems like only one dbContext can be updated at a moment. You must Enable-Migration , Add-Migration and Update-Database for each dbContext. This is the way i do it. But my dbContext were in different projects, so may be it can be the same for you! Update separately didn't overwrite my database. It works for me !

In think the problem you have, it that your database tables / migrations are not separated.
In EF6 if you work with more than one context, I recommend to specify the name for the default schema in the OnModelCreating method of you DbContext derived class (where the Fluent-API configuration is).
public partial class ApplicationDbContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("Application");
// Fluent API configuration
}
}
public partial class CompanyDBContext : DbContext
{
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.HasDefaultSchema("Company");
// Fluent API configuration
}
}
This example will use "Application" and "Company" as prefixes for your database tables (instead of "dbo") in your (single) database.
More importantly it will also prefix the __MigrationHistory table(s), e.g. Application.__MigrationHistory and Company.__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
e.g.
add-migration NAME_OF_MIGRATION -ConfigurationTypeName ApplicationConfiguration
if ApplicationConfiguration is the name of your configuration class.
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 ApplicationConfiguration: DbMigrationsConfiguration<ApplicationDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
MigrationsDirectory = #"Migrations\Application";
}
}
internal sealed class CompanyConfiguration : DbMigrationsConfiguration<CompanyDBContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
MigrationsDirectory = #"Migrations\Company";
}
}

Related

Override "dbo" schema name in EntityFramework Code First Migrations

I'm trying to create an schema independent model with EntityFramework Codefirst and an Oracle database but EF uses as defaults for migrations dbo as schema.
I overridden OnModelCreating method on my DBContext to solve this and use the user in the connectionString instead
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.HasDefaultSchema(string.Empty);
}
The problem is that __MigrationHistory ignores this default schema and I get this error when running first migration:
ORA-01918: User 'dbo' does not exist
Tried this msdn entry to customize the schema for this table.
CustomHistoryContext:
public class CustomHistoryContext : HistoryContext
{
public CustomHistoryContext(DbConnection dbConnection, string defaultSchema)
: base(dbConnection, defaultSchema) {}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.HasDefaultSchema(String.Empty);
}
}
And DBConfiguration:
public sealed class Configuration :
DbMigrationsConfiguration<Model.MyDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
SetHistoryContextFactory("Oracle.ManagedDataAccess.Client",
(connection, defaultSchema) => new CustomHistoryContext(connection, defaultSchema));
}
protected override void Seed(Model.Model1 context)
{
}
}
And is working fine for the first migration. But when I modify my entity model and try to reflect this change with add-migration command I get the following error:
Unable to generate an explicit migration because the following
explicit migrations are pending: [201706281804589_initial,
201706281810218_pp2]. Apply the pending explicit migrations before
attempting to generate a new explicit migration.
Looks like EF gets lost and can't find migrations history at this point.
When I comment the SetHistoryContextFactory instruction in Configuration it works for subsequent add-migration commands but this workaround isn't enough for scenarios when I want to run all migrations from scratch like deploying.
Does anyone knows if I'm in the good way to accomplish this or if there is a better workaround for this?
Go to Migrations -> Configuration.cs and below mentioned code. This fix worked for me!
class Configuration : DbMigrationsConfiguration<CodeFirstOracleProject.Context>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
var historyContextFactory = GetHistoryContextFactory("Oracle.ManagedDataAccess.Client");
SetHistoryContextFactory("Oracle.ManagedDataAccess.Client",
(dbc, schema) => historyContextFactory.Invoke(dbc, "YourSchemaName"));
}
}
Try runnig Enable-Migrations -force again. Then run Add-Migration SomeDescription –IgnoreChanges. After that, run "Update-Database - Verbose". This worked to me
I successfully tried the following inside the Configuration : DbMigrationsConfiguration class for Oracle, in order to change the history schema to "Test":
var historyContextFactory = GetHistoryContextFactory("Oracle.ManagedDataAccess.Client");
SetHistoryContextFactory("Oracle.ManagedDataAccess.Client",
(dbc, schema) => historyContextFactory.Invoke(dbc, "Test"));
So basically, instead of trying to register a custom history context with unchanged default schema, I tried to register the default history context with changed default schema.
The result: when I run Update-Database -Script, the resulting script contains the new schema for creation of the __MigrationHistory table as well as for inserting the new history values:
create table "Test"."__MigrationHistory"
-- ...
insert into "Test"."__MigrationHistory"("MigrationId", "ContextKey", "Model", "ProductVersion") ...
However, lets be perfectly clear: I just tried what I expected to work by intuition and it did work for me. I didn't find any reliable documentation to support this solution.
open Migrations -> Configuration.cs and add
public Configuration()
{
AutomaticMigrationsEnabled = false;
var historyContextFactory = GetHistoryContextFactory("Oracle.ManagedDataAccess.Client");
SetHistoryContextFactory("Oracle.ManagedDataAccess.Client",
(dbc, schema) => historyContextFactory.Invoke(dbc, "your_schema_name_hear"));
}

what is the reason of getting 'Unable to update database error' when giving enable-migrations command

I use EF 6 and code first in a project
I try to understand using 'enable-migrations' command.
DbContext and Initializer examples are in simplest form like below .
When I give the command 'enable-migrations' package-manager console outputs an error like below :
Unable to update database to match the current model because there are pending changes and automatic migration is disabled. Either write the pending model changes to a code-based migration or enable automatic migration. Set DbMigrationsConfiguration.AutomaticMigrationsEnabled to true to enable automatic migration.
But If I do not call InitializeDatabase();method from MyDbContext constructor no error occures and no data imports or seed method does not run.
Only database creates.
I want to learn what's the reason and what's the mean of this error If I use InitializeDatabase() method.
Thank you
public class MyDbContext : DbContext
{
public MyDbContext():base("TestDb")
{
Database.SetInitializer(new DbContextInitializer());
InitializeDatabase();
}
protected virtual void InitializeDatabase()
{
if (!Database.Exists())
{
Database.Initialize(true);
}
}
public DbSet<TestModel> TestModels { get; set; }
}
public class DbContextInitializer : CreateDatabaseIfNotExists<MyDbContext>
{
protected override void Seed(MyDbContext context)
{
base.Seed(context);
context.TestModels.Add(new TestModel() {
Name = "Lorem",
Surname = "Ipsum"
});
}
}
Your initializer is inheriting from CreateDatabaseIfNotExists which is not a logical choice for migrations. You have some pending model changes that are not being applied because the model has changed and your initializer is only going to run when the database does not exist.
You could delete your database so it reinitializes with the changes, or switch your initializer to MigrateDatabaseToLatestVersion. Here is a good article on initializers and seeding.

EF Code-First from existing db add models into existing DbContext

So maybe this is a stupid question, because I know that when creating a Code-first model from an existing database, Visual Studio will create a new ADO.NET Entity Data Model, and add the models in a new DbContext.
I am using Microsoft Identity in my project, hence there is already a ApplicationDbContext (IdentityDbContext). I think just having all my models in a single DbContext would be easier to handle. I am generating my code-first models from an existing database.
But Is there a way such that the generated models add up into the already existing DbContext (In this case, the IdentityDbContext?)
I have like, many models, so currently I am compelled to add each of them into existing ApplicationDbContext manually, and remove from the created DbContext.
As far as I remember there is no way to add the generated models objects to the existing DbContext automatically. You need to add them manually.
public partial class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext()
: base("name=DefaultConnection")
{
}
//Add your Model objects here, You can copy them from automatically generated DbContext
public virtual DbSet<ModelObjectName> PropertyName { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//Copy the modelBuilder configuration here from automatically generated DbContext here
base.OnModelCreating(modelBuilder);
}
}
Here's an alternative that works:
Mark your ApplicationDbContext class as partial:
public partial class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext() : base("DefaultConnection")
{
//unchanged
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//unchanged
}
}
Do the same with your custom Data model class, and remove the inheritance from DbContext. Also, remove constructor form it and change the OnModelCreating into a regular private method with some different name. Keep the rest unchanged.
public partial class MyDataModels
{
//unchanged
private void OnModelCreating2(DbModelBuilder modelBuilder)
{
//unchanged
}
}
Refactor (Ctrl + R + R : default shortcut) name of your Data model class, and change it to ApplicationDbContext. Visual Studio might give you a conflict warning during refactoring, ignore that and refactor. Finally, call OnModelCreating2() from OnModelCreating() method of ApplicationDbContext class.
public partial class ApplicationDbContext : IdentityDbContext<ApplicationUser>
{
public ApplicationDbContext() : base("DefaultConnection")
{
//unchanged
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
//unchanged
OnModelCreating2(modelBuilder);
}
}
Another nice approach suggested by #DevilSuichiro is to simply inherit your Data model class from ApplicationDbContext.
Cheers!

How to do integration test using Entity Framework Code First V6.1.2

I'm trying to add some integration tests for my database access logic using EF code-first 6.1.2. I'd like to do this on a separate database so that I don't mess up m production database with test data.
Also, the test should be repeatable which means the database should be created if not exists, seed test data, run the tests and finally delete it when done.
I don't see how this can be done without Enable-Migrations command for the test database too.
This would be my dbContext for production:
public partial class ApplicationDbContext :
IdentityDbContext<ApplicationUser, ApplicationRole, int, ApplicationUserLogin, ApplicationUserRole, ApplicationUserClaim>, IApplicationDbContext
{
public ApplicationDbContext() : base("name=DefaultConnection") { }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
if (base.Database.Connection.ConnectionString == "DefaultConnectionTest")
Database.SetInitializer(new DropCreateDatabaseAlways<ApplicationDbContext>());
else
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext, Configuration>());
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<ApplicationUser>().ToTable("Users");
modelBuilder.Entity<ApplicationRole>().ToTable("Roles");
modelBuilder.Entity<ApplicationUserRole>().ToTable("UserRoles");
modelBuilder.Entity<ApplicationUserLogin>().ToTable("UserLogins");
modelBuilder.Entity<ApplicationUserClaim>().ToTable("UserClaims");
}
public DbSet<Order> Orders { get; set; }
public DbSet<Product> Products { get; set; }
public DbSet<Person> Persons { get; set; }
}
I have everything set up using Dependency Injection from Ninject.
Adding an extra constructor with the connection string as parameter public ApplicationDbContext(string dbConnection) : base(dbConnection) { }, would still leave me to run the Enable-Migrations command.
Is there some way to automate this process? Or can anyone suggest something else?
I'd like to stick with SQL Server database as working with a different database for testing might give me false positives.
You have to use a database initialiser. There are a few available :
Database.SetInitializer(new CreateDatabaseIfNotExists<InterstoneContext>());
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<InterstoneContext>());
Database.SetInitializer(new DropCreateDatabaseAlways<InterstoneContext>());
you need the third option. Be careful with your connectionstring that you don't overwrite your production database.

Entity Framework: Running code before all migrations

I want to migrate stored procedures and views in my DB. Since I always migrate to the latest version, a source-control-friendly approach is to drop/recreate all procedures/views during migration process (with this approach there is one file per procedure, instead of one-per-version).
Since old procedures/functions/views might not be compatible with new schema changes, I want to do drop before all migrations, then do the create after all.
Previously I used a customized FluentMigrator, but now I am researching Entity Framework Code First Migrations. I see that I can use Seed to always run code after all migrations.
Is there something I can use to always run code before all migrations?
If you want some code to run before migrations kick in, you can specify a custom database initializer:
public class AwesomeEntity
{
public int Id { get; set; }
}
public class AwesomeDbContext : DbContext
{
static AwesomeDbContext()
{
Database.SetInitializer(new AwesomeDatabaseInitializer());
}
public IDbSet<AwesomeEntity> Entities { get; set; }
}
public class AwesomeDatabaseInitializer : MigrateDatabaseToLatestVersion<AwesomeDbContext, AwesomeMigrationsConfiguration>
{
public override void InitializeDatabase(AwesomeDbContext context)
{
// TODO: Run code before migration here...
base.InitializeDatabase(context);
}
}
public class AwesomeMigrationsConfiguration : DbMigrationsConfiguration<AwesomeDbContext>
{
public AwesomeMigrationsConfiguration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(AwesomeDbContext context)
{
// TODO: Seed database here...
}
}
This sets the custom initializer to a custom AwesomeDatabaseInitializer, which inherits from MigrateDatabaseToLatestVersion. If you want to drop and rebuild the database every time, you should use the DropCreateDatabaseAlways as base class instead, though I'm not sure this lets you run migrations.
In the initializer, you can override the InitializeDatabase method, where you can run code before you call base.InitializeDatabase, which will trigger the database initialization and in turn the Seed method of the migration configuration, AwesomeMigrationsConfiguration.
This is using EF6. I'm not sure if there is an equivalent in earlier versions of entity framework.
I have a solution that is pretty horrible, but works for migrate.exe.
Here is the idea:
Use Seed for AfterAll, as suggested by #khellang.
For BeforeAll, register a custom IDbConnectionInterceptor in MigrationsConfiguration constuctor to capture first connection after the MigrationsConfiguration has been created, then make it unregister itself. Obviously this is absolutely not thread-safe and only OK in application startup or migrate.exe.
Example code:
public class DbMigrationsInterceptingConfiguration<TContext> : DbMigrationsConfiguration<TContext>
where TContext : DbContext
{
public DbMigrationsInterceptingConfiguration() {
BeforeFirstConnectionInterceptor.InterceptNext();
}
protected override void Seed(TContext context) {
Console.WriteLine("After All!");
}
}
internal class BeforeFirstConnectionInterceptor : IDbConnectionInterceptor {
public static void InterceptNext() {
DbInterception.Add(new BeforeFirstConnectionInterceptor());
}
public void Opened(DbConnection connection, DbConnectionInterceptionContext interceptionContext) {
// NOT thread safe
Console.WriteLine("Before All!");
DbInterception.Remove(this);
}
// ... empty implementation of other methods in IDbConnectionInterceptor
}
I am not sure I would be actually using it though.

Categories

Resources