I would like to be able to unit test using my code first/migrations entity framework project.
My current method does the following:
Create the DataContext
Creates the repository
Creares unit of working using DataContext
Creates my service layer
After step 1. I would like to be able say to entity framework, using my migrations/migrations folder recreate the database every time it runs.
I current send in my Datacontext a custom string which represents what connection string to use, my code looks like:
[TestCase]
public void TestMethod1()
{
var systemContextTest = new SystemContext("SystemContextTest");
IRepository<PublicQueries> repos = new Repository<PublicQueries>(systemContextTest);
var uow = new UnitOfWork(systemContextTest);
var service = new PublicQueryService(repos);
service.Find(0);
}
I just want to be able to create the database, using migrations everytime this test is ran!
Thanks
-UPDATE-
I have tried:
Database.SetInitializer<YourContext>(new MigrateDatabaseToLatestVersion<YourContext, YourMigrationConfiguration>());
But this results in
System.Data.Entity.Core.EntityCommandExecutionException : An error occurred while executing the command definition. See the inner exception for details.
----> System.Data.SqlClient.SqlException : Invalid object name
Which means its still not creating it.
I just want to using my migration files/code first migrations to create a new fresh database.
-- UPDATE 2 --
When adding Database.SetInitializer(new DropCreateDatabaseAlways<SystemContext>());
I get the following error:
System.InvalidOperationException : The DropCreateDatabaseAlways initializer did not drop or create the database backing context 'SystemContext' because Migrations are enabled for the context. Use Migrations to manage the database for this context, for example by running the 'Update-Database' command from the Package Manager Console.
My SystemContext Constructor i am using for testing looks like:
public SystemContext(string connectionstringname) :
base(connectionstringname)
{
Database.SetInitializer<SystemContext>(null);
Configuration.ProxyCreationEnabled = false;
}
Updatad answer:
Implement a custom database initializer
private DbMigrationsConfiguration configuration;
public void InitializeDatabase(C context) {
context.Database.Delete();
context.Database.Create();
var migrator = new DbMigrator(configuration);
migrator.Update();
}
and put this line at the beginning of the test method.
Database.SetInitializer(new MyCustomInitializer<SystemContext>());
Related
In certain test environments, I have configured my application to create a new instance of it's database using Entity Framework migrations when the database does not already exist.
I am also using Hangfire, and have configured it use SQL Server in my OWIN startup class. At present I am instantiating a new instance of my DbContext to force database creation prior to configuring Hangfire to use the database:
public class Startup
{
public void Configuration(IAppBuilder app)
{
using (var dbContext = new MyDbContext())
{
// Force database creation before configuring Hangfire to use it.
}
GlobalConfiguration.Configuration.UseSqlServerStorage("myConnection");
// ...
}
}
This feels a bit hacky. What is the recommended way to ensure Entity Framework has created the database before it is used outside of the DbContext?
Turns out that the snippet in the question isn't necessarily enough by itself (depending upon platform and other EF configuration settings), so we actually make it explicit in the code now (as per Diana's comment), which also makes it feel less hacky:
// Trigger database creation before Hangfire tries to use it.
var initializer = new MigrateDatabaseToLatestVersion<MyDbContext, MyConfiguration>(true);
Database.SetInitializer(initializer);
var connectionString = this.Configuration.GetConnectionString("MyConnectionString");
using (var dbContext = new MyDbContext(connectionString))
{
dbContext.Database.Initialize(false);
}
I'm writing a web api attached to a database that I created using Model First.
Being new I was confusing Model First with Code First.
As it's my first EF/Web app I didn't realize that migration wasn't yet implemented by Model First and I followed the procedure to implement it. When it ran I received some errors, looked them up and only then realized I'd need to remove it again.
Following somebody's instructions I deleted the migrations folder, plus the _migrationHistory table from the database.
But now I receive the following exception whenever the _migrationhistory table is missing from the database.
protected void Application_Start()
{
// Call initializer
Database.SetInitializer(new PulseDbInitializer());
new ApplicationDbContext().Database.Initialize(true); <- error here
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
"An exception of type 'System.NotSupportedException' occurred in EntityFramework.dll but was not handled in user code
Additional information: Model compatibility cannot be checked because the database does not contain model metadata. Model compatibility can only be checked for databases created using Code First or Code First Migrations."
The following is a partial description of my initializer
public partial class PulseDbInitializer : DropCreateDatabaseIfModelChanges<ApplicationDbContext>, IPulseDbInit
//public partial class PulseDbInitializer :DropCreateDatabaseAlways<ApplicationDbContext>, IPulseDbInit
{
private ApplicationDbContext _context;
protected override void Seed(ApplicationDbContext context)
{
_context = context;
var pid = new PulseDbInitializionData(context);
pid.Init(this);
}
}// class PulseDbInitializer
It seems that the app is trying to use migrations (because it's creating the _migrationhistory table) even though I've removed the migrations subfolder.
Being new at this, I'm not sure where to go. I'm aware that I've created my initializer, see above, so am I missing something?
EDIT - Too long for a comment
Im not sure we're understanding each other.
Very simply, I don't know what's generating the _MigrationHistory table in my database as afaik if I remove the Migration subdirectory from my project and delete the database, then I thought that's all I need to do to drop migrations.
In my model first, the DropCreateDatabaseIfModelChanges is what I've always used for generating the database and is working as expected. It creates a new database, or recreates when the model changes.
Until I added the migration I didn't notice this _MigrationHistory table and I don't have a clue if the add-migration command added any code to my project that I need to delete or change (I really hate things happening and not being told exactly what was done in some kind of log. Please microsoft, for future reference)
Or am I totally wrong and the _MigrationHistory table was always there but I never noticed? It all seems to work, as long as I don't remove the table.
Your initializer is inheriting from DropCreateDatabaseIfModelChanges, which checks for model changes. Since you are not using code first you can't check for model changes in code (since your code doesn't define the model -that'd be code-first-... the model defines the code -that's model-first-)... so you need to implement your own IDatabaseInitializer which only checks (for example) that the database exists:
public partial class PulseDbInitializer : IDatabaseInitializer<ApplicationDbContext>, IPulseDbInit
{
public void InitializeDatabase(ApplicationDbContext context)
{
var exists = new DatabaseTableChecker().AnyModelTableExists(context.InternalContext);
if (exists == DatabaseExistenceState.Exists)
{
// maybe check if certain data exists and call the `Seed` method if
// it doesn't
return;
}
// Throw some error if it doesn't exist
}
protected override void Seed(ApplicationDbContext context)
{
_context = context;
var pid = new PulseDbInitializionData(context);
pid.Init(this);
}
}
We run migrations from within our application to create databases on the fly. We also use migrations in our unit/integration tests to create databases for the tests to use. A few months ago we noticed the run-time of our tests substantially increased and we've been able to narrow it down to the instantiation of the DbMigrator class. Even with a very simple Configuration class it still takes ~10 seconds to create the DbMigrator.
For example, here's the Configuration class taken from the "Elastic DB Tools - Entity Framework" sample application.
internal sealed class Configuration : DbMigrationsConfiguration<ElasticScaleContext<int>>
{
public Configuration()
{
this.AutomaticMigrationsEnabled = false;
this.ContextKey = "CodeFirstNewDatabaseSample.BloggingContext";
}
}
Here is the code used to create and run the migrations.
var configurator = new Configuration();
configurator.TargetDatabase = new DbConnectionInfo(connStrBldr.ConnectionString, "System.Data.SqlClient");
var migrator = new DbMigrator(configurator);
migrator.Update();
And here's the trace information from VS2015.
Time to instantiate Configuration
Time to set the TargetDatabase property
Time to instantiate DbMigrator
We're using Entity Framework 6.1.3. Has anyone else experienced this?
I have three database environments, Developer, Testing and Production. To setup database with sample data i created a console app where user selects environment to setup the database. I am using Entity Framework database first but stuck with how to select instance at run time. There is only one database model is it possible to change db connection at run time?
i used following code and it throws exception.
// Truncate all Data
if (env.Key == ConsoleKey.D)
{
db.Database.Connection.ConnectionString = System.Configuration.ConfigurationManager.ConnectionStrings["db_dev"].ToString();
}
Model Entities has no constructor to get Connection String..
Ensure you have a constructor on your DbContext class that takes a connection string and then simply pass it to the base class (Entity Framework will do the rest)
public MyDbContext : DbContext
{
public MyDbContext(string connectionString) : base (connectionString)
{
}
}
Then when you instantiate your Context you simply pass in the connection string that you would like to use... example using your code above would be...
var connectionString = System.Configuration.ConfigurationManager.ConnectionStrings["db_dev"].ToString();
using (var context = new MyDbContext(connectionString))
{
}
When you're creating your instance of database context (db variable) there should be a constructor overload that accepts a string. That's how you can set it up with your custom connection string.
If your class that inherits from the DbContext doesn't have that overload, just create it because the base class does have it.
I created a DbContext like so :
public class myDB : DbContext
{
public DbSet<Party> Parties { get; set; }
public DbSet<Booking> Bookings { get; set; }
}
This generated my DataBase and the two tables above..Great
I then decided to add another DbSet into the mix & I got an error:
the model backing the 'Party' context has changed since the database was created
I'm aware of the fixes for this using modelbuilder.IncludeMetadataInDatabase = false; and Database.SetInitializer<ClubmansGuideDB>(null);
1) What's the correct way to add my new classes to the context and have them generated in the DataBase?
2) In my futile attempts to solve this myself I deleted the tables and tried to re-run the app with no success I then deleted the full database and re-run and it doesn't re-generate the DB. How can I start from scratch - is there some cache somewhere?
I believe you're looking for:
Database.SetInitializer<ClubmansGuideDB>(new DropCreateDatabaseIfModelChanges<ClubmansGuideDB>());
As of EF 4.1 and above.
Note that this assumes you have permission to even drop your database. I do this locally for ease of development but disable it in staging/production (I do a manual Schema Compare and push my changes).
By the way, for testing, if you need to force recreate the database, you can do:
using (var context = new ClubmansGuideDB()) {
context.Database.Initialize(force: true);
}
(using if you don't already have a reference to your DB)
You can let the Entity Framework recreate the whole database by using a Database Initializer or if you want to migrate data you can look at the Code First Migrations
The following would recreate your database when the model changes:
Database.SetInitializer<myDB>(new DropCreateDatabaseIfModelChanges<myDB>());
Try putting this in your Global.asax.cs Application_Start() method.
Database.SetInitializer<DatabaseContext>(null);
To reset the database from scratch on app run make a class like this
//Where myDB is your context
public class EntityBase: DropCreateDatabaseAlways<myDB>
{
}
Then in your Application_Start() method you can do this
Database.SetInitializer(new EntityBase());