My Seed() method is never called in Code First EF 5 - entity-framework

My Seed() method is never called. It is called when I do an Update-Database from the Package Manager Console, but never when I run from code.
If I delete my database, all tables are created ( so my migration classes are executed), but my Seed() code is never called.
MVC 4, Entity Frame Work 5 Code First.
Global.asax:
protected void Application_Start()
{
Database.SetInitializer<MyContext>(new DbInitializer());
}
DBInit:
internal class DbInitializer : MigrateDatabaseToLatestVersion<MyContext, Migrations.Configuration>
{
}
DBContext:
public partial class MyContext : DbContext
{
public MyContext() : base("DefaultConnection")
{
}
// public DBSets....
}
Configuration:
internal sealed class Configuration : DbMigrationsConfiguration<MyContext>
{
public Configuration()
{
// The constructor is actually called
AutomaticMigrationsEnabled = false;
}
protected override void Seed(MyContext context)
{
// My seed code, never called
}
What could be wrong?

So the reason was that I needed to specify my custom Initializer in the config file:
<entityFramework>
<contexts>
<context type="EFTest2.MyContext, EFTest2">
<databaseInitializer type="EFTest2.Initializers.DbInitializer, EFTest2" />
</context>
</contexts>
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlConnectionFactory, EntityFramework" />
</entityFramework>
After that, my Seed method is called.

Please first refer to the accepted answer.
I just want to add a very important note to this issue.
I was facing EXACTLY the same problem which described by this question (and this lead me to here). BUT I was using CreateDatabaseIfNotExists instead of MigrateDatabaseToLatestVersion and my seed method was not executed even after applying the accepted answer.
My problem was the following :
According to the documentation of the for the Seed method :
the Seed method of the DbMigrationsConfiguration will not be executed if the Database Initializer is one of the following
DropCreateDatabaseAlways
DropCreateDatabaseIfModelChanges
CreateDatabaseIfNotExists
If you are using one of those types, you should create your own class which inherits from one of those types, and then override the seed method in your own class.
In my case, adding the following class solved the problem.
public class CreateNotifierDatabaseIfNotExists : CreateDatabaseIfNotExists<NotifierContext>
{
protected override void Seed(NotifierContext context)
{
// the code of the seeding is go here
}
}

In my experience, this can happen when you stop trying to access DataContext. We had a method that was throwing errors when DataContext was finished creating the DataBase. We commented it out in order to resolve the problems with DataBase creation.
The problem was, this was the only method that actually used DataContext on initial loading. That meant that no DbInitialization logic executed, because an instance wasn't yet required.
When we added a less-problematic data retrieval logic instead of the commented-out one, the DbCreation and Seeding logic took place as normal.

Related

Can I inject dependency into migration (using EF-Core code-first migrations)?

I tried to inject IConfiguration into the migration (in constructor), and got exception: "No parameterless constructor defined for this object."
any workaround?
you cannot, the migrations need to be able to run outside the context of your application.
Since the Entity-framework command-line tool analyzes your code but does not run the startup.cs class.
Also it is not advisable. your migrations should be plain simple and not depend on anything. if it would, it could lead to major runtime side-effects where missing config could lead to missing tables or columns in production.
additional advise
If it involves a lot of small/equal/manual changes. Best way is to generate your migration file. Why? This way your migration will be deterministic: you know what the outcome will be. If a line in your migration fails, it is simple and clear why that is and easily(er) fixable.
There's a way to do what you want to do. In my scenario, I would like to use the database name in the connection string through the DbContext. EF core 2.1.1 is used. The code is modified from here
Create a custom MigrationsAssembly service
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Internal;
using Microsoft.EntityFrameworkCore.Migrations;
using Microsoft.EntityFrameworkCore.Migrations.Internal;
using System;
using System.Reflection;
public class ContextAwareMigrationsAssembly : MigrationsAssembly
{
private readonly DbContext context;
public ContextAwareMigrationsAssembly(
ICurrentDbContext currentContext,
IDbContextOptions options,
IMigrationsIdGenerator idGenerator,
IDiagnosticsLogger<DbLoggerCategory.Migrations> logger) : base(currentContext, options, idGenerator, logger)
{
context = currentContext.Context;
}
/// <summary>
/// Modified from http://weblogs.thinktecture.com/pawel/2018/06/entity-framework-core-changing-db-migration-schema-at-runtime.html
/// </summary>
/// <param name="migrationClass"></param>
/// <param name="activeProvider"></param>
/// <returns></returns>
public override Migration CreateMigration(TypeInfo migrationClass, string activeProvider)
{
var hasCtorWithDbContext = migrationClass
.GetConstructor(new[] { typeof(DbContext) }) != null;
if (hasCtorWithDbContext)
{
var instance = (Migration)Activator.CreateInstance(migrationClass.AsType(), context);
instance.ActiveProvider = activeProvider;
return instance;
}
return base.CreateMigration(migrationClass, activeProvider);
}
}
Replace the IMigrationAssembly service in your DbContext with your custom class
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.ReplaceService<IMigrationsAssembly, ContextAwareMigrationsAssembly>();
}
Then you can add a DbContext parameter in your migration.
public Migration20180801(DbContext context)
{
DatabaseName = context.Database.GetDbConnection().Database;
}
In your case, you can replace all the DbContext references with IConfiguration and the relevant instance in the CreateMigration override.
If it is just about your connection-string (is it?), you may want to check this answer, which basically suggests this code in your startup-project (not in your migrations-project):
var myConnectionString = Configuration.GetConnectionString(myConnectionStringName);
services.AddDbContext<MyDbContext>(options => options.UseSqlServer(
myConnectionString ,
x => x.MigrationsAssembly(myDbContextAssemblyName)));

How to set EF context initialization through configuration file and seed when needed?

I am using Entity Framework 6.1 and would like to set the initialization through a configuration file. At the same time I would like run a seed method when the setting in the configuration file is one that that drop and (re)create the database.
Unless I am mistaken the Seedmethod will only be called when setting an initializer through code. Any way to specify what initializer to run in a configuration file (or whatever) in order to make the Seed method run when the configuration file species the database to be dropped and created?
If not, what other option is recommended?
You can put it in the DbContext constructor as follow.
public class AppContext : DbContext
{
public AppContext()
{
if (ConfigurationManager.AppSettings["Initializer"] == "DropAlways")
{
Database.SetInitializer(new DropCreateDatabaseAlways<AppContext>());
}
else if (ConfigurationManager.AppSettings["Initializer"] == "DropIfModelChanges")
{
Database.SetInitializer(new DropCreateDatabaseIfModelChanges<AppContext>());
}
else
{
Database.SetInitializer(new CreateDatabaseIfNotExists<AppContext>());
}
}
}

DbContext not initializing with SQL Server Compact in ASP.Net MVC

I have created a simple project using ASP.Net MVC template in Visual Studion 2013 Express for Web. It does not use any authentication. Then I installed EntityFramework (v6.0.1), EntityFramework.SqlServerCompact packages.
My DbContext class is very simple:
public class EditTestContext : DbContext
{
public EditTestContext() : base("EditTestContext")
{
}
public EditTestContext(string connectionString) : base(connectionString)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer(
new DropCreateDatabaseIfModelChanges<EditTestContext>());
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
modelBuilder.Configurations.Add(new EditTestConfig());
}
}
The actual context object is created in the Unit of Work class:
public class EditTestUoW:IEditTestUoW,IDisposable
{
private DbContext dbContext;
public EditTestUoW()
{
CreateDbContext();
}
private void CreateDbContext()
{
dbContext = new EditTestContext();//NEW DBCONTEXT OBJECT IS CREATED
dbContext.Configuration.LazyLoadingEnabled = false;
dbContext.Configuration.ProxyCreationEnabled = false;
dbContext.Configuration.ValidateOnSaveEnabled = false;
}
public IRepository<EditTestModel> EditTestRepo
{
get
{
return new EFRepository<EditTestModel>(dbContext);
}
}
}
The connection string being used is:
<add name="EditTestContext" connectionString="Data Source=
|DataDirectory|EditTestDb.sdf;Max Database Size=256;
Max Buffer Size=1024;File Mode=Shared Read;
Persist Security Info=False;" providerName="System.Data.SqlServerCe.4.0" />
Now when I try to access any thing using this Context like:
var rep=UoW.EditTestRepo;
var list=rep.GetAll().ToList();
I am getting following exception on rep.GetAll() function:
System.InvalidOperationException: Sequence contains no matching element
On digging deeper, IQueryable from Repository class (DbSet<EditTest>) is throwing following exception:
The context cannot be used while the model is being created. This exception may
be thrown if the context is used inside the OnModelCreating method or if the same
context instance is accessed by multiple threads concurrently. Note that instance
members of DbContext and related classes are not guaranteed to be thread safe.
I thought it might have been caused by ninject, but it is still there even after I removed it.
What I am doing wrong here or something (some assembly reference etc.) is missing?
Well after some other search on the issue, I got this MSDN forum link. As was suggested by Rowan, I tried to manually initialize the context using following statement in my EFRepository class:
dbContext.Database.Initialize(false);
The application failed way before it was hitting the GetAll() method. But this exposed the stack trace which gave me some direction:
[InvalidOperationException: Sequence contains no matching element]
System.Linq.Enumerable.Single(IEnumerable`1 source, Func`2 predicate) +2614017
System.Data.Entity.Utilities.DbProviderManifestExtensions.GetStoreTypeFromName
(DbProviderManifest providerManifest, String name) +146
.....Other Lines.....
System.Data.Entity.Internal.InternalContext.Initialize() +31
System.Data.Entity.Internal.InternalContext.GetEntitySetAndBaseTypeForType
(Type entityType) +38
System.Data.Entity.Internal.Linq.InternalSet`1.Initialize() +138
System.Data.Entity.Internal.Linq.InternalSet`1.get_InternalContext() +38
System.Data.Entity.Infrastructure.DbQuery`1.System.Linq.IQueryable
.get_Provider() +99
System.Linq.Queryable.Any(IQueryable`1 source) +50
Then searching for DbProviderManifestExtensions.GetStoreTypeFromName revealed that this is the line where EF was trying to get column type. I had specified UNIQUEIDENTIFIER for my Id column:
Property(x=> x.Id).HasColumnType("UNIQUEIDENTIFIER")
Once I commented this, all was well.
Though there is a request on Codeplex to provide the proper error message in case the column type is not valid for database provider.

"Signature of the body and declaration in a method implementation do not match"

UPDATE: I think I've eliminated Unity from the equation. See below for more details.
UPDATE 2: I think I may have eliminated Entity Framework fro the equation. See below for more details.
I have some code that is building a unity container, but it started failing with the above error message out of the blue. It works on other people's machines, but not mine. I deleted the folder the solution was in and refreshed everything from source control to ensure I had nothing that could be causing issues (e.g. duplicate assemblies lying around from a previous build).
Here is part of my code:
public static class UnityBootstrapper
{
public static IUnityContainer Initialise()
{
Trace.WriteLine("UnityBootstrapper.Initialise()");
var container = BuildUnityContainer();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
private static IUnityContainer BuildUnityContainer()
{
Trace.WriteLine("UnityBootstrapper.BuildUnityContainer()");
var container = new UnityContainer();
// Other dependencies are registered here
// If the following line is commented out the container is build
// but, obviously, it won't resolve this dependency.
container.RegisterType<IUserAccessEntities, UserAccessEntities>(WebRequestLifetime);
// Other dependencies are registered here
return container;
}
The code apparently fails on the call to BuildUnityContainer(), and I can see that the trace statement I put inside that method is never displayed.
However, if I comment out the line that registers the UserAccessEntities class (which was code generated from Entity Framework 5) then the container is built. Naturally, when I ask for that dependency it can't resolve it, so the code just fails elsewhere.
I've Googled for solutions and they all seem to resolve around generics and moving the generic type from the method to the class level. I can't do that as EF5 creates the class and it puts generics on the properties. e.g
DbSet<MyTable> Tables { get; set; }
The only other thing I can think of is that I've extracted an interface from the EF5 generated class called IUserAccessEntities and the problem could lie there... but I used ReSharper to generate that, so it should be perfectly aligned.
UPDATE
Just to eliminate Unity from the equation, I tried to new up the UserAccessEntities on its own
private static void TestUae()
{
var uae = new UserAccessEntities(); //container.Resolve<IUserAccessEntities>();
Trace.WriteLine("Got the entities: " + uae);
}
And the call to TestUae() fails instead.
UPDATE 2
I created a new class, AlternativeEntities based on the interface I'd previously extracted. When I try to construct that directly it has a new exception: Method 'Set' in type 'AlternativeEntities' from assembly 'UserAccess.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null' does not have an implementation.
However, it does. There are two methods called set, both of which I've given a basic implementation:
public class AlternativeEntities : IUserAccessEntities
{
public DbSet<TEntity> Set<TEntity>() where TEntity : class
{
Trace.WriteLine("public DbSet<TEntity> Set<TEntity>() where TEntity : class");
return null;
}
public DbSet Set(Type entityType)
{
Trace.WriteLine("public DbSet Set(Type entityType)");
return null;
}
// Other methods and properties here.
}

Entity Framework Code First - No Detach() method on DbContext

I'm wondering why there is no Detach method on the DbContext object like there is for ObjectContext.  I can only assume this omission was intentional, but I have a hard time figuring out why.  I need to be able to detach and re-attach entities (for putting in the cache in an ASP.NET project, for example).  However, since I can't detach an entity, when I try to attach an entity that was associated with a previous context, I get the "An entity object cannot be referenced by multiple instances of IEntityChangeTracker" exception.
What's the guidance here?  Am I missing something?
For people that might stumble upon this question, as of CTP5 you now need to write
((IObjectContextAdapter)context).ObjectContext
in order to get to ObjectContext.
DbContext uses an ObjectContext internally and EF team make this available as a protected property just in case you ever need to drop down to the lower level API and sounds like this is the case here, so you can use or expose the required functionality from a derived DbContext:
public class YourContext : DbContext
{
public void Detach(object entity)
{
ObjectContext.Detach(entity);
}
}
Then you can call this method from your controller to detach an entity.
Alternatively, you can change it to even have a richer API:
public class YourContext : DbContext
{
public void ChangeObjectState(object entity, EntityState entityState)
{
ObjectContext.ObjectStateManager.ChangeObjectState(entity, entityState);
}
}
Here is how DbContext looks like from metadata:
public class DbContext : IDisposable
{
protected System.Data.Objects.ObjectContext ObjectContext { get; }
...
}
EF:CF 4.1 RC1 and EF:CF 4.1 RTW have the same explicitly implemented IObjectContextAdapter:
public static class DbContextExtensions
{
public static void Detach(this System.Data.Entity.DbContext context, object entity)
{
((System.Data.Entity.Infrastructure.IObjectContextAdapter)context).ObjectContext.Detach(entity);
}
}
Microsoft decided "Detach is too advanced technology and should be hidden". IMHO the man who invented this should be shot - because if you add brand new entity, it is otherwise difficult to just remove it without commiting changes to db (you can manipulate with DbEntityEntry but that's another story).
Edit 4 years later:
With EF6 (i somehow skipped EF5 :) ) you dont need detach() anymore, becouse removing freshly added entry does not generate delete from [table] where [Id] = 0 as in EF4 - you can just call mySet.Remove(myFreshlyCreatedAndAddedEntity) and everything will be allright.
I usually extend the base class(inherits from the DbContext) with the property:
public class MyDbContext : DbContext
{
public ObjectContext ThisObjectContext
{
get
{
return ((IObjectContextAdapter)this).ObjectContext;
}
}
}
later you can use this property for variety of useful stuff ... like Detach :)