I have a project that I created and enabled Migrations on. It created it with 4.3 so I think it is the latest. I have some code in the constructor of the context that executes the update (see code below) and that seems to work everytime I add something like a nullable string column or do something that does not change the database in non consistent manner. My scenario is I change my model, and when I watch sql trace, it does the alter columns for me automatically.
My question is I want to do the "up" and "down" methods but am confused on when they run. That is say I'm on version 1 now, I put some code in my "up" method to add a column, then later when I want to go to version 3, how does it know which "up" method to call?
Confused. -Peter
namespace MigrationsAutomaticDemo.Migrations
{
using System.Data.Entity.Migrations;
public partial class AddBlogRating : DbMigration
{
public override void Up()
{
AddColumn("Blogs", "Rating", c => c.Int(nullable: false, defaultValue: 3));
}
public override void Down()
{
DropColumn("Blogs", "Rating");
}
}
}
,
public SiteDB()
{
UpdateDatabase();
}
// http://joshmouch.wordpress.com/2012/04/22/entity-framework-code-first-migrations-executing-migrations-using-code-not-powershell-commands/
public static int IsMigrating = 0;
private static void UpdateDatabase()
{
if (0 == Interlocked.Exchange(ref IsMigrating, 1))
{
// Manually creating configuration:
var migratorConfig = new DbMigrationsConfiguration<SiteDB>();
migratorConfig.AutomaticMigrationsEnabled = true;
// Using configuration defined in project:
//var migratorConfig = new DbMigrationsConfiguration();
// 3
//var dbMigrator = new DbMigrator(new Settings());
var dbMigrator = new DbMigrator(migratorConfig);
dbMigrator.Update();
Interlocked.Exchange(ref IsMigrating, 0);
}
}
If you enable the automatic migration in the migration configuration, then you don't need to specify the target migration. The migrator will automatically scaffold the changes based on the snapshot of current context and target database.
var migratorConfig = new DbMigrationsConfiguration<SiteDB>();
migratorConfig.AutomaticMigrationsEnabled = true;
In your case, you want to upgrade your database by using specific migration. All you need to do is mentioning explicitly which migration to upgrade.
Configuration configuration = new Configuration();
DbMigrator migrator = new DbMigrator(configuration);
migrator.Update("201204250656061_AddBlogRatingVersion2");
migrator.Update("201204250656061_AddBlogRatingVersion3");
migrator.Update("201204250656061_AddBlogRatingVersionX");
Related
I'm using EF6 code first approach to create database. When i add migration and update database it always create Non-cluster Index for every foreign key in the table by default.
My Question: Is there any global setting for EF6 to not create Non-Cluster indexon foreign key ?
I have search and found the following solutions
Solution 1: Remove index line from migration before updating database
Solution 1 not suits me because i have a lot of tables and my db is already created. Manually remove index creation line takes much much time.
Moreover i'm also using fluent api is there any option related to this issue ?
Well, I think this might have been an 'If all you have is a hammer...' kinda situation.
The answer that I gave before works (and I stand by it, because it is totally fun and awesome), but it's probably not the best way to do it.
Recently I checked all the default conventions EF uses the generate the database, and there is one that's responsible for generating the non-clustered indices on FK-s. Just remove that convention altogether, and the problem is solved:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
// using System.Data.Entity.ModelConfiguration.Conventions;
modelBuilder.Conventions.Remove<ForeignKeyIndexConvention>();
}
I don't believe there is a simple solution to this, but I have an idea about what you could do: create a custom migration generator.
Migration generators are the components that are responsible for creating the SQL script that is run on the database from the migration code files. I assume you have SQL Server based on the screenshot. In this case, you can write a custom sql generator that simply overrides the index creation operation so that if the index is non-clustered, nothing is written to the script:
public class NoIndexGenerator : SqlServerMigrationSqlGenerator
{
protected override void Generate(CreateIndexOperation createIndexOperation)
{
if (!createIndexOperation.IsClustered)
{
return;
}
}
}
Then you have to register this component in the Configuration class of the migration:
internal sealed class Configuration : DbMigrationsConfiguration<MyCtx>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
// Add this line to register the sql generator
this.SetSqlGenerator("System.Data.SqlClient", new NoIndexGenerator());
}
}
Now if you run Add-Migration, you'll have a normal migration file, with the CreateIndexOperation in it. But if you run Update-Database, the non-clustered indices will not be created. You can also check this if you run Update-Database -Script. The resulting script does not have the non-clustered indices.
If you want, you can go even higher up in the pipeline, and create a custom C# migration scaffolder. It applies the same logic as the sql generator:
internal class NoIndexMigrationCodeGenerator : CSharpMigrationCodeGenerator
{
protected override void Generate(CreateIndexOperation createIndexOperation, IndentedTextWriter writer)
{
if (!createIndexOperation.IsClustered)
{
return;
}
}
}
Then, you can register it in the Configuration class like this:
internal sealed class Configuration : DbMigrationsConfiguration<MyCtx>
{
public Configuration()
{
AutomaticMigrationsEnabled = false;
// Add this line to register the C# code generator
this.CodeGenerator = new NoIndexMigrationCodeGenerator();
}
}
Now, if you run Add-Migration, the CreateIndex operations will disappear from the generated migration cs files as well.
I'd probably go with the second solution (it can be confusing for others reading your code to see that there are CreateIndex operations in the migration cs file, but not in the SQL scripts), but ultimately it is your choice :)
You can play with other properties of the createIndexOperation parameter of the Generate() methods to implement more sophisticated index filtering, if you have to.
If you want, you can also override the Generate methods that have a parameter of type DropCreateIndexOperation but since indices are dropped with a 'drop-if-exists' pattern, I don't think this is necessary.
EDIT
While the above code samples seem to work, to be fair and follow general best-practices and principles, you should probably include calls to the base methods in both generators after the if statements.
After trying to use CSharpMigrationCodeGenerator I start to think in way to override the ForeignKeyIndexConvention.
So I implemented the check that allows to skip adding index on Primary Key column by assuming that PK naming convention was not overrided.
public class ForeignKeyIndexConventionFix : ForeignKeyIndexConvention
{
private const string Id = "Id";
public override void Apply(AssociationType item, DbModel model)
{
if (item == null)
{
throw new ArgumentNullException(nameof(item));
}
if (item.Constraint == null)
{
return;
}
if (item.IsForeignKey)
{
if (IsPrimaryKeyColumn(item.Constraint))
{
return;
}
}
base.Apply(item, model);
}
private static bool IsPrimaryKeyColumn(ReferentialConstraint constraint)
{
IEnumerable<string> dependentColumns = constraint.ToProperties.Select(p => p.Name);
if (dependentColumns.Count() == 1)
{
string dependentColum = dependentColumns.First();
if (dependentColum.Equals(Id, StringComparison.OrdinalIgnoreCase))
{
return true;
}
}
return false;
}
}
Then override your DbContext class:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Conventions.Remove<ForeignKeyIndexConvention>();
modelBuilder.Conventions.Add<ForeignKeyIndexConventionFix>();
}
There was problem to debug solution - Console.Write and Debug.Write were not giving output - so I just put tracing to some text file in temp location. Maybe there is a better way..?
And the code source of original implementation helped to figure out how to get dependent column names: https://github.com/dotnet/ef6/blob/master/src/EntityFramework/ModelConfiguration/Conventions/Edm/Db/ForeignKeyIndexConvention.cs
With EF Core 6.0, you need to remove ForeignKeyIndexConvention form all the convention sets that includes it. Here is a working solution:
Create a new ConventionSetBuilder class:
public class CustomSqlServerConventionSetBuilder : SqlServerConventionSetBuilder, IConventionSetBuilder
{
public CustomSqlServerConventionSetBuilder(ProviderConventionSetBuilderDependencies dependencies, RelationalConventionSetBuilderDependencies relationalDependencies,
ISqlGenerationHelper sqlGenerationHelper) : base(dependencies, relationalDependencies, sqlGenerationHelper)
{
}
public override ConventionSet CreateConventionSet()
{
var cs = base.CreateConventionSet();
//ForeignKeyAddedConventions
var foreignKeyAddedConvention = cs.ForeignKeyAddedConventions.FirstOrDefault(f => f is ForeignKeyIndexConvention);
if (foreignKeyAddedConvention != null)
cs.ForeignKeyAddedConventions.Remove(foreignKeyAddedConvention);
//ForeignKeyRemovedConventions
var foreignKeyRemovedConventions = cs.ForeignKeyRemovedConventions.FirstOrDefault(f => f is ForeignKeyIndexConvention);
if (foreignKeyRemovedConventions != null)
cs.ForeignKeyRemovedConventions.Remove(foreignKeyRemovedConventions);
//EntityTypeBaseTypeChangedConventions
var entityTypeBaseTypeChangedConventions = cs.EntityTypeBaseTypeChangedConventions.FirstOrDefault(f => f is ForeignKeyIndexConvention);
if (entityTypeBaseTypeChangedConventions != null)
cs.EntityTypeBaseTypeChangedConventions.Remove(entityTypeBaseTypeChangedConventions);
//KeyAddedConventions
var keyAddedConventions = cs.KeyAddedConventions.FirstOrDefault(f => f is ForeignKeyIndexConvention);
if (keyAddedConventions != null)
cs.KeyAddedConventions.Remove(keyAddedConventions);
//KeyRemovedConventions
var keyRemovedConventions = cs.KeyRemovedConventions.FirstOrDefault(f => f is ForeignKeyIndexConvention);
if (keyRemovedConventions != null)
cs.KeyRemovedConventions.Remove(keyRemovedConventions);
//ForeignKeyPropertiesChangedConventions
var foreignKeyPropertiesChangedConventions = cs.ForeignKeyPropertiesChangedConventions.FirstOrDefault(f => f is ForeignKeyIndexConvention);
if (foreignKeyPropertiesChangedConventions != null)
cs.ForeignKeyPropertiesChangedConventions.Remove(foreignKeyPropertiesChangedConventions);
//ForeignKeyUniquenessChangedConventions
var foreignKeyUniquenessChangedConventions = cs.ForeignKeyUniquenessChangedConventions.FirstOrDefault(f => f is ForeignKeyIndexConvention);
if (foreignKeyUniquenessChangedConventions != null)
cs.ForeignKeyUniquenessChangedConventions.Remove(foreignKeyUniquenessChangedConventions);
//IndexAddedConventions
var indexAddedConventions = cs.IndexAddedConventions.FirstOrDefault(f => f is ForeignKeyIndexConvention);
if (indexAddedConventions != null)
cs.IndexAddedConventions.Remove(indexAddedConventions);
//IndexRemovedConventions
var indexRemovedConventions = cs.IndexRemovedConventions.FirstOrDefault(f => f is ForeignKeyIndexConvention);
if (indexRemovedConventions != null)
cs.IndexRemovedConventions.Remove(indexRemovedConventions);
//IndexUniquenessChangedConventions
var indexUniquenessChangedConventions = cs.IndexUniquenessChangedConventions.FirstOrDefault(f => f is ForeignKeyIndexConvention);
if (indexUniquenessChangedConventions != null)
cs.IndexUniquenessChangedConventions.Remove(indexUniquenessChangedConventions);
//ModelFinalizingConventions
var modelFinalizingConventions = cs.ModelFinalizingConventions.FirstOrDefault(f => f is ForeignKeyIndexConvention);
if (modelFinalizingConventions != null)
cs.ModelFinalizingConventions.Remove(modelFinalizingConventions);
return cs;
}
}
And replace the ConventionSetBuilder within your DbContext configuration:
public partial class YourDbContext : DbContext
{
...
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
...
optionsBuilder.ReplaceService<IConventionSetBuilder, CustomSqlServerConventionSetBuilder>();
}
}
Is there any code to perform automatic migration in Entity Framework core code first in asp.net core project?
I do it simply in MVC4/5 by adding
Database.SetInitializer(new MigrateDatabaseToLatestVersion<AppDbContext, MyProject.Migrations.Configuration>());
public Configuration() {
AutomaticMigrationsEnabled = true;
}
This saves time when entities changed
You can call context.Database.Migrate()in your Startup.cs
eg:
using (var context = new MyContext(...))
{
context.Database.Migrate();
}
EF core doesn't support automatic migrations.So you have to do it manually.
From the perspective of automatic migrations as a feature, we are not
planning to implement it in EF Core as experience has showed code-base
migrations to be a more manageable approach.
You can read full story here : Not to implement Automatic Migrations
This is the way they do it in IdentityServer4 http://identityserver.io
public void ConfigureServices(IServiceCollection services)
{
var connectionString = Configuration.GetConnectionString("DefaultConnection");
var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
// Add framework services.
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(connectionString));
...
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
// this will do the initial DB population
InitializeDatabase(app);
}
private void InitializeDatabase(IApplicationBuilder app)
{
using (var scope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
scope.ServiceProvider.GetRequiredService<ApplicationDbContext>().Database.Migrate();
scope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate();
...
}
}
Automatic migrations is not supported in EF Core. Migration it is necessary to create hands. To automatically apply all existing handmade migrations need to add the following code in the class Program:
public class Program
{
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args).Build();
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<MyDbContext>();
context.Database.Migrate(); // apply all migrations
SeedData.Initialize(services); // Insert default data
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred seeding the DB.");
}
}
host.Run();
}
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>();
}
Following Microsoft's documentation
https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro
If you are using dependency injection, first, you need to setup a static class Data/DbInitializer.cs and add the following code:
public static class DbInitializer
{
public static void Initialize(ApplicationDbContext context)
{
context.Database.Migrate();
// Add Seed Data...
}
}
Notice, this is also where you can add seed data.
Next, in your Program.cs file, add the following code
public static void Main(string[] args)
{
var host = BuildWebHost(args);
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var environment = services.GetRequiredService<IHostingEnvironment>();
if (!environment.IsDevelopment())
{
var context = services.GetRequiredService<ApplicationDbContext>();
DbInitializer.Initialize(context);
}
}
catch (Exception ex)
{
var logger = services.GetRequiredService<ILogger<Program>>();
logger.LogError(ex, "An error occurred while seeding the database.");
}
}
host.Run();
}
In my case, I'm checking the environment to make sure I'm in development so I can control the migrations/updates. However, in production, I want them to be automatic for continuous integration. As others have mentioned, this is probably not best practices but on small projects it works great.
My working automigration code Asp Net Core 2.0.7.
// startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
// configure app
SeedData.Initialize(app.ApplicationServices);
}
// dbInitializer.cs
public static class SeedData
{
public static void Initialize(IServiceProvider serviceProvider)
{
using (var serviceScope = serviceProvider.CreateScope())
{
var context = serviceScope.ServiceProvider.GetService<ApplicationDbContext>();
// auto migration
context.Database.Migrate();
// Seed the database.
InitializeUserAndRoles(context);
}
}
private static void InitializeUserAndRoles(ApplicationDbContext context)
{
// init user and roles
}
}
You can call Database.Migrate() in db context constructor.
If the model changes a lot and you manage a medium - large team, migrations leads more problems than solution at least in development phase.
I published a nuget package with automatic migration for .net core, EFCore.AutomaticMigrations - https://www.nuget.org/packages/EFCore.AutomaticMigrations/, so manual migration not needed anymore.
You can call directly in Program class, like bellow:
public static void Main(string[] args)
{
var host = CreateWebHostBuilder(args);
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
var loggerFactory = services.GetRequiredService<ILoggerFactory>();
var logger = loggerFactory.CreateLogger<Program>();
try
{
var environment = services.GetRequiredService<IWebHostEnvironment>();
if (environment.IsDevelopment())
{
var context = services.GetRequiredService<ApplicationContext>();
MigrateDatabaseToLatestVersion.ExecuteAsync(context).Wait();
}
}
catch (Exception ex)
{
logger.LogError(ex, "An error occurred creating/updating the DB.");
}
}
host.Run();
}
Frank Odoom's answer works even 4 years later in .net 5, but it is not the intended context to call the migration at runtime... And, it appears it never was because it requires us to mock the DbContext with DbContextOptions whos documentation explicitly states:
"The options to be used by a DbContext. You normally override OnConfiguring(DbContextOptionsBuilder) or use a DbContextOptionsBuilder to create instances of this class and it is not designed to be directly constructed in your application code."
Here is my suggestion:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
// database provider is configured before runtime migration update is applied e.g:
optionsBuilder.UseSqlServer(ConnectionString);
Database.Migrate();
}
Edit:
My suggestion is actually horrible if you are using multiple DBContexts in the same project... It would migrate the database multiple times. Which would most likely not break anything, but it would slow startup considerably.
my best advice is not to use the automatic migration.It is always better to add migrations manually and also avoid bulk migration and stick to best practice for using manual migration
automatic migration is not a magic tool and there will be several occasions where you might want to add some addition changes to the migration. You only accomplish by using manual migration.
To enable migration, type "enable-migrations" in the package manager console
This way you will have full control of upgrading or downgrading your database and also easy to track migrations.
Just three simple steps in package manager console.
1) add-migrations [some name for your migration]
2) migrations is generated for the changes, you review them and also can
make changes to it
3) update-database your migration is complete now.
handling migration is less painful!
I have a code-first scenario with migrations enabled, AutomaticMigrationsEnabled is disabled, and the DB initializer is set to MigrateDatabaseToLatestVersion. I'd like to "catch" Migration events for logging purposes.
I tried to do it in the Seed() but it's called every single run, regardless of whether the underlying database needs a migration to match the model or not.
Is there a proper way to do this?
Solution 1)
Check if you need migration:
var migrator = new DbMigrator(new DbMigrationsConfiguration());
// If any migration is required then Count will be greater than 0
// 0 means no migration required
if (migrator.GetPendingMigrations().Count() > 0)
{
// Fire your event here!
}
Soultion 2)
Use a logging decorator to log progress, in this use case you do not need the event.
public class MyLogger : System.Data.Entity.Migrations.Infrastructure.MigrationsLogger
{
public override void Info(string message)
{
// Short status messages come here
}
public override void Verbose(string message)
{
// The SQL text and other info comes here
}
public override void Warning(string message)
{
// Warnings and other bad messages come here
}
}
To migrate to latest version, you have to call it like that:
DbMigrator migrator = new DbMigrator(new MyConfiguration());
MigratorLoggingDecorator logger = new MigratorLoggingDecorator(migrator, new MyLogger());
// This line will call the migration + logging
logger.Update();
Extra info:
You can create your custom MigratorLoggingDecorator decroator like that:
MyMigratorLoggingDecorator: MigratorLoggingDecorator {
internal override Upgrade(IEnumerable<string> pendingMigrations, string targetMigrationId, string lastMigrationId)
{
// Fire your event here!
base.Upgrade(..)
}
..}
Lets say we have the architecture model of web application where we have 1 database per 1 account. Database structure is the same for these accounts and differs only on data with in. How can i configurate a migrations in code first model.
Now I have next solution.
In the main method or in global.asax something like this:
var migration_config = new Configuration();
migration_config.TargetDatabase = new DbConnectionInfo("BlogContext");
var migrator = new DbMigrator(migration_config);
migrator.Update();
migration_config.TargetDatabase = new DbConnectionInfo("BlogContextCopy");
migrator = new DbMigrator(migration_config);
migrator.Update();
Connection strings for example in app_config file:
<connectionStrings>
<add name="BlogContext" providerName="System.Data.SqlClient" connectionString="Server=(localdb)\v11.0;Database=MigrationsDemo.BlogContext;Integrated Security=True;"/>
<add name="BlogContextCopy" providerName="System.Data.SqlClient" connectionString="Server=(localdb)\v11.0;Database=MigrationsDemo.BlogContextCopy;Integrated Security=True;"/>
</connectionStrings>
Configuration class and context:
internal sealed class Configuration : DbMigrationsConfiguration<MigrationsDemo.BlogContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
AutomaticMigrationDataLossAllowed = true;
}
protected override void Seed(MigrationsDemo.BlogContext context) {
}
}
public class BlogContext : DbContext {
public BlogContext() {}
public BlogContext(string connection_name) : base(connection_name) {
}
public DbSet<Blog> Blogs { get; set; }
}
In addition to your excellent answer, you can use an external config file (i.e. "clients.json") instead of hardcoding them, put all the database infos in key-value pairs into the json file and load it during startup.
Then, by iterating over the key-value pairs, you can do the initialization.
The clients.json:
{
"DatabaseA": "DatabaseAConnectionString",
"DatabaseB": "DatabaseBConnectionString",
"DatabaseC": "DatabaseCConnectionString",
...
}
Provide a method to handle the migrations:
public static void MigrateDatabases(IDictionary<string,string> databaseConfigs)
{
foreach (var db in databaseConfigs)
{
var config = new Configuration
{
TargetDatabase = new DbConnectionInfo(db.Value, "System.Data.SqlClient")
};
var migrator = new DbMigrator(config);
migrator.Update();
}
}
Then during startup, (I use OWIN, so it's in my Startup.cs, could also be global.asax.cs):
string json;
var path = HttpRuntime.AppDomainAppPath;
using (var reader = new StreamReader(path + #"Config\clients.json"))
{
json = reader.ReadToEnd();
}
var databases = JsonConvert.DeserializeObject<IDictionary<string, string>>(json);
MigrateDatabases(databases);
Works like a charm for me :)
See the page on automatic migrations during application startup.
If you use this method to apply your migrations, you can use any connection string (or whatever method you have to identify exactly which database to connect to) and upon connection, the migration will be performed.
I'm trying to setup some unit tests using EntityFramework 5, SQL Server Compact 4 and Xunit.
I'm using different context instances because I'm testing a ASP MVC app and I need to test the behavior of some update operations over detached entities.
[Fact, AutoRollback]
public void TestConnection()
{
using (var connection = this.GetDbConnection())
{
using (var context = new MyContext(connection, false))
{
// Do database stuff
}
using (var context = new MyContext(connection, false))
{
// Do database stuff
}
}
}
public DbConnection GetDbConnection()
{
string dataSource = "|DataDirectory|\\MyDb.sdf";
var sqlBuilder = new SqlCeConnectionStringBuilder();
sqlBuilder.DataSource = dataSource;
return new SqlCeConnection(sqlBuilder.ToString());
}
This gives me the following error:
System.Data.EntityException : The underlying provider failed on Open.
System.InvalidOperationException : The connection object can not be enlisted in transaction scope.
I know I can't open multiple DbContext instances inside a TransactionScope (that is probably what Xunit does when you put a FallbackAttribute in your method), so that's why I'm creating the connection beforehand.
If I try to open the connection myself, it still does not work:
using (var connection = this.GetDbConnection())
{
connection.Open();
using (var context = new MyContext(connection, false))
{
I get the following exception:
System.ArgumentException : EntityConnection can only be constructed with a closed DbConnection.
Does any one know how to solve that issue?
EDIT
The test classes that deal with the Db extend a "DomainFactsBase" where the database is initialized as the following:
public DomainFactsBase()
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<MyContext>());
using (var context = new MyContext(GetDbConnection(), true))
context.Database.Initialize(false);
}
EDIT
I can sucessfully run tests with autorollback when I create only one context instance. This was accomplished following the instructions in this article. I have a extension method:
public static void OpenConnection(this DbContext context)
{
((IObjectContextAdapter)context).ObjectContext.Connection.Open();
}
And I call it right after creating the context in the tests:
[Fact, AutoRollback]
public void SomeFact()
{
using (var context = new MyContext())
{
context.OpenConnection();
// Do stuff
}
}
That work with no problems. They arise when I try to open the context more than once in the same fact (with AutoRollback enabled), as I examplified in the beginning.
Initialize the database outside of the test. You can do this inside of the test class's constructor.
public MyTestClass()
{
using (var db = new MyContext(GetDbConnection(), true))
{
db.Database.Initialize(false);
}
}