Entity Framework didn't apply migrations using Database.SetInitializer() - entity-framework

I have a simple ASP.NET Web Pages site using Entity Framework 6.1 (the Web Pages live in the standard project with csproj so that I could use EF Code First with migrations). This is in my _AppStart.cshtml:
#{
Database.SetInitializer(new MigrateDatabaseToLatestVersion<MyContext, Configuration>());
}
It all compiles fine, I have confirmed that the code indeed go through this line but the migrations aren't applied - I have confirmed that by manually executing Update-Database which did the work correctly.
What could be wrong? Do I need to set something else for it to work?

Calling SetInitializer (as name says) does not create database or apply migrations. It just sets the initializer. It will be invoked for instance when you would like to save data to db with SaveChanges method and the database won't exist at that time. To force immediate migration you should use DbMigrator class:
var migrator = new DbMigrator(new MyMigrationsConfiguration());
migrator.Update();

Related

Nested Transactions In EF6

I have a method where the DBContext is pass in (this is only POC code).
I then try to open another nested transaction, With this code
using (var cxt = new TestEntities(context.Database.Connection, false))
{
using (DbContextTransaction dbContextTransaction = cxt.Database.BeginTransaction())
{
The call to "BeginTransaction" gives this error:
An exception of type 'System.Data.Entity.Infrastructure.UnintentionalCodeFirstException' occurred in TestEF6.exe but was not handled in user code
Additional information: The context is being used in Code First mode with code that was generated from an EDMX file for either Database First or Model First development. This will not work correctly. To fix this problem do not remove the line of code that throws this exception. If you wish to use Database First or Model First, then make sure that the Entity Framework connection string is included in the app.config or web.config of the start-up project. If you are creating your own DbConnection, then make sure that it is an EntityConnection and not some other type of DbConnection, and that you pass it to one of the base DbContext constructors that take a DbConnection. To learn more about Code First, Database First, and Model First see the Entity Framework documentation here: http://go.microsoft.com/fwlink/?LinkId=394715
I have a Database First Model
Any clues?
Regards
GregJF

EDMX for legacy code _and_ Code First for new development together in one MVC project

The situation as follows:
we have one big MVC project with database first approach on EF5.0:
ObjectContext constructor:
namespace xxx.Models
{
(...)
public partial class xxxEntities : ObjectContext
{
#region Constructors
/// <summary>
/// (...)
/// </summary>
public xxxEntities() : base("name=xxxEntities", "xxxEntities")
{
this.ContextOptions.LazyLoadingEnabled = true;
OnContextCreated();
}
(...)
connection string:
<add name="xxxEntities"
connectionString="metadata=res://*/Models.xxxModel.csdl|
res://*/Models.xxxModel.ssdl|res://*/Models.xxxModel.msl;
provider=System.Data.SqlClient;provider connection string="
data source=.;Initial catalog=xxxdb;
integrated security=True;
multipleactiveresultsets=True;
App=EntityFramework""
providerName="System.Data.EntityClient" />
We choose Code First for testing the new development on separated namespace.
connection string:
<add name="xxxCFContext"
connectionString="Data Source=.;
Initial Catalog=xxxdb;
Integrated Security=True;
User Instance=False;
MultipleActiveResultSets=True"
providerName="System.Data.SqlClient" />
DbContext constructor:
namespace xxx.Models.CodeFirst
{
public partial class xxxCFContext : DbContext
{
static xxxCFContext()
{
Database.SetInitializer<xxxCFContext>(new ValidateDatabase<xxxCFContext>());
}
public xxxCFContext()
: base("Name=xxxCFContext")
{
}
(...)
We run add-migrations, update-database without problem, the build completed with success.
But on the first time with the code-first db access:
xxxCFContext cfdb = new xxxCFContext();
foreach (Xobject xobject in cfdb.Xobjects)
Appear the error:
"Could not find the conceptual model type 'xxx.models.yyyclass'", but this yyyclass exist in edmx, NOT the codefirst part.
Uninstall EF5.0, install EF6.0 and the error disappeared. But i need the EF5.0 not the 6.0 alfa3 prerelease.
What's wrong? How can we use edmx mixed with codefirst with EF5.0?
I would be very grateful for any idea.
EDIT
I know this workarounds, but not help for me:
Have anyone used Entity Framework with code first approach mixed with Edmx file?
http://blog.oneunicorn.com/2012/02/26/dont-use-code-first-by-mistake/
Could not find the conceptual model type
http://blog.oneunicorn.com/2012/02/26/dont-use-code-first-by-mistake/
Entity Framework (4.3) looking for singular name instead of plural (when entity name ends with "s")
Building an MVC 3 App with Database First and Entity Framework 4.1
The problem of generating (with xxxmodel.Context.tt and xxxModel.tt) the large existing edmx heavily exploits the advantages of ObjectContext, so we can not simply change from the ObjectContext to the DbContext (behind the existing edmx).
Edit II
From DB First to CodeFirst, we choose the following:
Moved from old edmx file to Code generation. With EF 5.x DbContext Fluent Generator was generated the model objects, so we have the model objects.
(Right-click into EDMX editor and add code generation item. If you do not seem, to be installed: Tools menu, Extensions and Updates, EF 5.x DbContext Fluent Generator)
The model objects and the context is copied from the EDMX.
The EDMX was deleted anything that was under him.
Set the ConnectionString from was difficult EDMX-style to simple codefirst form.
and tadam, in about 10 minutes, we moved from Database First to Code First. During development, with existing 80 tables in db.
run Enable-Migrations in Power Management Console, and continued with CodeFirst.
It may help to keep the different "types" of EF (code-first, database first, etc.) in separate assemblies: a limitation of EF is that it is not possible use code-first in an assembly with certain database-first attributes - though a newer version of EF may fix this (perhaps that's why EF6 alphas work for you).

Entity Framework 5 model first - Where is IDisposable gone?

In Entity Framework 5 model first, there seem to be some breaking changes due to the way the class files are generated (No more code generation, but T4 templates)
2 examples:
The generated context file doesn't implement IDisposable anymore
There isn't a constructor which takes a connectionstring anymore
Are there more breaking changes? And what is the solution to them?
The default code generated from a model in Entity Framework 5 now inherits DbContext instead of ObjectContext.
This still implements IDisposable, but if you're getting an error from a line of code similar to this:
using (var mymodel = new MyModelContext()) { ... }
...complaining about not implementing IDisposable, then your problem is most likely that your model is defined in a separate assembly that references EF5 and you have not added an EF5 reference to your project.
As Ladislav Mrnka has already mentioned in his answer, if you want to pass a connection string to the constructor you have to create your own constructor manually to do this.
If you want to switch Entity Framework back to the older style of generated code, which will automatically generate the constructor you're looking for, then follow these steps:
Click on the designer surface of your EDMX file, and look at the properties window. Find a property called "Code Generation Strategy" and set this to "Default" instead of "None". This will tell Visual Studio to start creating the code for your object model in MyModel.Designer.cs in one big file, this time using ObjectContext instead of DbContext.
Delete the following sub files from below your EDMX file: MyModel.Context.tt, MyModel.tt. These are the auto generated files that you don't want anymore. If you don't delete them you'll get class naming conflicts because your objects will be created twice.
The generated context file doesn't implement IDisposable anymore
IDisposable is still implemented by the parent context type. The generated type is still disposable.
There isn't a constructor which takes a connectionstring anymore
It now uses convention to get connection string but you can add your own constructor either to template or to your partial class part of the context.
Are there more breaking changes? And what is the solution to them?
It is whole breaking change because it uses different API - DbContext API instead of ObjectContext API which means different types, different methods, POCO entities etc. If you want to get back to original code generation you have to delete those T4 templates and enable code generation as described in .Designer.cs file but the current recommended way is to use POCOs and DbContext API.
I was having the same issue with the using statement needing a type that extended IDisposable... Turns out that I forgot to reference System.Data.Entity in my project... Added the reference and it fixed the problem.
Just clean and build the project, don't forget to add the reference to your entity.

How to implement IDbContextFactory for use with Entity Framework data migrations

I am trying to use Entity Framework data migrations, as described in this post.
However, when I try to execute the Enable-Migrations step, I receive the following error in Package Manager Console:
The target context 'MyDataContext' is not constructible. Add a default constructor or provide an implementation of IDbContextFactory
So, I created a factory class that implements IDbContextFactory in the project that contains my DbContext class, but data migrations doesn't appear to recognize it.
Is there something that I should explicitly do to instruct data migrations to use this factory class?
I also hit this problem as i wrote my context to take a connection string name (and then used ninject to provide it).
The process you've gone through seems correct, here is a snippet of my class implementation if it's of any help:
public class MigrationsContextFactory : IDbContextFactory<MyContext>
{
public MyContext Create()
{
return new MyDBContext("connectionStringName");
}
}
That should be all you need.
Like #Soren pointed out, instead of using IDbContextFactory, not supported on some earlier EF Core releases (i.e. EF Core 2.1), we can implement IDesignTimeDbContextFactory<TContext>, which supports the missing ConnectionString parameter.
For a settings.json based aproach, which you can use with either of the referred interfaces, check #Arayn's sample which allows us to define "ConnectionStrings:DefaultConnection" value path
Update 1
According to #PaulWaldman's comment, on EF Core 5 support for IDbContextFactory was reintroduced. For further details, check his comment below.

How to ignore derived DbContext during EF4.3.1 Code First migration

I am trying to use code-first migrations, but the project that contains my CustomContext also has a derived class, TracingCustomContext which I use when tracing the SQL generated:
DbContext => CustomContext => TracingCustomContext
The problem I have during code-first migrations is that when trying to run
Enable-Migrations
in Package Manager Console, this results in the (not unexpected) warning:
More than one class deriving from DbContext found in the current project.
Edit the generated Configuration class to specify the context to enable migrations for.
In order to get past this message and move on to Add-Migration -Initial, I had to comment out my TracingCustomContext class, then run Enable-Migrations. The Configuration class that had been generated looked fine, so the suggestion in the warning didn't seem relevant.
So the question I have is whether there is any way to configure Migrations so it ignores a specific Context like TracingCustomContext? For example, an attribute to decorate the class, or a configuration setting somewhere?
Any ideas gratefully received.
As per the error message:
Edit the generated Configuration class to specify the context to enable migrations for.
Open the created Configuration.cs class (int the Migrations folder) and you will see:
internal sealed class Configuration : DbMigrationsConfiguration</* TODO: put your Code First context type name here */>
Replace /* TODO: put your Code First context type name here */ with the type name of the context (do the same in the Seed method or remove the Seed method if you are not using it) and it should work.