Entity Framework Database.SetInitializer просто не работает
У меня такая "загадочная" проблема.
В настоящее время я использую Entity Framework 4.1 Code First с моим приложением ASP.NET MVC 3, он отлично работал до вчерашнего дня...
Произошло что-то действительно плохое, из-за чего моя Database.SetInitializer перестала работать.
Разъяснение:
У меня есть эта простая модель
public class User
{
public int Id { get; set; }
public int RoleId { get; set; }
[Required]
[StringLength(50)]
[DataType(DataType.Text)]
public string Login { get; set; }
[Required]
[StringLength(150)]
[DataType(DataType.EmailAddress)]
public string Email { get; set; }
[Required]
[StringLength(32)]
[DataType(DataType.Password)]
public string Password { get; set; }
[DataType(DataType.DateTime)]
public DateTime RegisteredDate { get; set; }
public virtual Role Role { get; set; }
}
И вот мой DbContext
public class MyContext : DbContext
{
public DbSet<Models.User> Users { get; set; }
}
Также я настраиваю пользовательский инициализатор (для теста)
public class MyInitializer
: DropCreateDatabaseIfModelChanges<MyContext>
{
}
Теперь я уже установил строку подключения в Web.config(с тем же именем, что и MyContext)
Поэтому в Global.asax я вызываю этот простой код в методе Application_Start()
Database.SetInitializer(new MyInitializer());
Но проблема в том, что Database.SetInitializer WONT создает любую базу данных, а тем более, даже не пытается заполнить существующую базу данных таблицами из контекста...
Я пытался отлаживать, но похоже, что приложение просто перескакивает через код инициализации базы данных...
Я нашел одно решение - использовать эту строку кода
var ctx = new MyContext();
ctx.Database.Initialize(true);
Итак, я просто заставляю код создавать БД в любом случае...
Но факт, что Database.SetInitializer не работает, действительно раздражает... он отлично работал раньше, я не знаю, что произошло.
Я заглянул в журнал событий Windows, журналы sql-сервера... но ничего не существует. Просто молчание.
Но может быть, я просто смотрю в неправильном месте?: S
Кто-нибудь может сказать мне, что происходит?
P.S Я использую Visual Web Developer 2010 + SQL Server Express 2008 R2
Ответы
Ответ 1
База данных будет создана только при использовании контекста.
Если вы переопределили метод Seed в своем инициализаторе следующим образом:
protected override void Seed(MyContext context){...}
Код семени будет запускаться только при использовании экземпляра MyContext.
Вот почему он работает, когда вы используете
var ctx = new MyContext();
ctx.Database.Initialize(true);
Вы всегда можете заставить его создать, используя свой контекст в методе Application_Start() в Global.asax.cs, например:
System.Data.Entity.Database.SetInitializer(new MyInitializer());
MyContext db = new MyContext();
db.Database.Initialize(true);
//or even something like db.Users.Count();
Или он будет создан позже, когда вы используете свой контекст. Возможно, это выглядело так, будто оно перестало работать, потому что вы удалили код, который использовал бы контекст при запуске приложения.
Ответ 2
Другой способ создания базы данных
Database.SetInitializer(new CreateDatabaseIfNotExists<MyContext>());
var context = new MyContext();
context.Database.Create();
Ответ 3
В файле Global.asax.cs
Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext, DbMigrationConfig>());
где DbMigrationConfig - это класс конфигурации в папке миграции, которую я переименовал.
Также убедитесь, что вы включили автоматические миграции в конструкторе config
Ответ 4
У меня была такая же проблема с моими определениями First Code и сузилась до нескольких DBInitializer, определенных в одном файле класса. Таким образом, правило большого пальца после проверки синтаксиса и использования:
1) Имейте только одно определение инициализатора в одном физическом файле
2) Определите DbContext и Initializer в отдельных файлах
НТН