Как я могу получить свою базу данных для семени, используя Entity Framework CodeFirst?

База данных создается успешно (как и таблицы), но не засеяна. Я провел несколько часов и прочитал множество статей, но не смог их получить. Любые предложения?

С другой стороны, можно ли вызвать инициализатор без ссылки на мой DatabaseContext на клиенте?

Я включил весь соответствующий код, о котором я мог думать. Если что-нибудь еще будет полезно, пожалуйста, дайте мне знать.

Вещи, которые я пробовал:

  • Я удалил строку подключения (поскольку она по умолчанию имеет значение sqlexpress, только имя изменено)
  • Я изменил DropCreateDatabaseIfModelChanges на DropCreateDatabaseAlways, все тот же.

Изменить: действительно странно, что это сработало один раз, но я понятия не имею, как и почему он снова сломался. Я предполагаю строки подключения, но кто знает.

DatabaseInitializer.cs

public class DatabaseInitializer : DropCreateDatabaseIfModelChanges<DatabaseContext>
{
  protected override void Seed(DatabaseContext context)
  {
    // Seeding data here
    context.SaveChanges();
  }
}

DatabaseContext.cs

public class DatabaseContext : DbContext
{
  protected override void OnModelCreating(DbModelBuilder mb)
  {
    // Random mapping code
  }

  public DbSet<Entity1> Entities1 { get; set; }
  public DbSet<Entity2> Entities2 { get; set; }

}

Global.asax.cs - Application_Start()

protected void Application_Start()
{
  Database.SetInitializer<DatabaseContext>(new DatabaseInitializer());
  AreaRegistration.RegisterAllAreas();
  RegisterGlobalFilters(GlobalFilters.Filters);
  RegisterRoutes(RouteTable.Routes);
}

Клиент web.config

<connectionStrings>
  <add name="DatabaseContext" connectionString="data source=.\SQLEXPRESS;Database=Database;Integrated Security=SSPI;" providerName="System.Data.SqlClient" />
</connectionStrings>

РЕШЕНИЕ

Для документации я поделился своим решением здесь. В любом случае, перемещение всех комментариев было бы болью. В итоге у меня были DatabaseInitializer и DatabaseContext в отдельных классах. Я не понимаю, хотя эти крошечные изменения исправили его, но вот оно.

DatabaseInitializer.cs

public class DatabaseInitializer : CreateDatabaseIfNotExists<DatabaseContext>
{
  protected override void Seed(DatabaseContext context)
  {
    // Seed code here
  }
}

DatabaseContext.cs

public class DatabaseContext : DbContext
{
  public DatabaseContext() : base("MyDatabase") { }

  protected override void OnModelCreating(DbModelBuilder mb)
  {
    // Code here
  }

  public DbSet<Entity> Entities { get; set; }
  // Other DbSets
}

Global.asax.cs - Application_Start()

protected void Application_Start()
{
  Database.SetInitializer(new DatabaseInitializer());
  AreaRegistration.RegisterAllAreas();
  RegisterGlobalFilters(GlobalFilters.Filters);
  RegisterRoutes(RouteTable.Routes);
}

Ответ 1

Это то, что все мои классы DbContext выглядят, и они семена просто отлично:

public class MyDbContext : DbContext
{
    public DbSet<MyClass> MyClasses { get; set; }

    protected override void OnModelCreating (DbModelBuilder modelBuilder)
    {
        base.OnModelCreating (modelBuilder);
        modelBuilder.Conventions.Remove<System.Data.Entity.ModelConfiguration.Conventions.PluralizingTableNameConvention> ();

        // Add any configuration or mapping stuff here
    }

    public void Seed (MyDbContext Context)
    {
        #if DEBUG
        // Create my debug (testing) objects here
        var TestMyClass = new MyClass () { ... };
        Context.MyClasses.Add (TestMyClass);
        #endif

        // Normal seeding goes here

        Context.SaveChanges ();
    }

    public class DropCreateIfChangeInitializer : DropCreateDatabaseIfModelChanges<MyDbContext>
    {
        protected override void Seed (MyDbContext context)
        {
            context.Seed (context);

            base.Seed (context);
        }
    }

    public class CreateInitializer : CreateDatabaseIfNotExists<MyDbContext>
    {
        protected override void Seed (MyDbContext context)
        {
            context.Seed (context);

            base.Seed (context);
        }
    }

    static MyDbContext ()
    {
        #if DEBUG
        Database.SetInitializer<MyDbContext> (new DropCreateIfChangeInitializer ());
        #else
        Database.SetInitializer<MyDbContext> (new CreateInitializer ());
        #endif
    }
}

Я использовал этот шаблон несколько раз, и для меня это получилось очень хорошо.

Ответ 2

Мой метод Seed не был вызван даже при правильном вызове Database.SetInitializer в Application_Start... Причина этого была очень простой: инициализатор вообще не может быть вызван, если у вас еще нет кода что использует контекст базы данных.

Ответ 3

Это моя печальная маленькая сказка.

Во-первых, извлеченные уроки:

  • Метод семени не будет вызываться до тех пор, пока не будет использован контекст.
  • Global.asax.cs не ударит точку останова при первом запуске bc, который он запускает до присоединения отладчика. Чтобы попасть в точку останова на Global.asax.cs, вы можете добавить некоторое пробел в Web.config и ударить страницу; то он получит удар.
  • Если есть VS-соединения к дБ, посев не произойдет. Приложение выведет ошибку.

Итак, чтобы избежать грусти:

  • Отключите соединение VS.
  • Переключить базовый класс DropCreateDatabaseAlways за один раз.
  • Нажмите страницу, использующую контекст.

Теперь грусть:

  • В моем файле Global.asax.cs был свой класс Initializer. У меня была точка останова на моем методе Initializer Seed; Я начал приложение, и метод никогда не попадал.: (
  • Я указываю точку останова в вызове Database.SetInitializer в Application_Start. Это никогда не попадалось.: (
  • Я понял, что у меня нет изменений схемы db, поэтому я изменил DropCreateDatabaseIfModelChanges на DropCreateDatabaseAlways. Еще ничего.: (
  • Наконец я перешел на страницу, в которой используется контекст, и это сработало.:/

Ответ 4

Вы можете вызвать update-database, чтобы вручную запустить метод семени внутри класса Configuration. Для этого требуется enable-migrations.

PM> update-database
Specify the '-Verbose' flag to view the SQL statements being applied to the target database.
No pending code-based migrations.
Running Seed method.

internal sealed class Configuration : DbMigrationsConfiguration<ProjectManager.Data.Database.ProjectDb>
{
    public Configuration()
    {
        AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(ProjectManager.Data.Database.ProjectDb context)
    {
        context.Status.AddOrUpdate(
            new Status() { Id = 1, Text = "New" },
            new Status() { Id = 2, Text = "Working" },
            new Status() { Id = 3, Text = "Completed" },
            new Status() { Id = 4, Text = "Skipped" }
        );
    }
}

Ответ 5

В файле Global.asax изменилось следующее изменение:

Старый код:

    protected void Application_Start()
    {
        Database.SetInitializer<mycontextclassname>(new DropCreateDatabaseAlways<mycontextclassname>());             
       ...
    }

Новый код:

    protected void Application_Start()
    {
        Database.SetInitializer<mycontextclassname>(new DropCreateDatabaseAlways<mycontextclassname>()); 
        Database.SetInitializer(new Initializer()); 
        ...
    }

Ответ 6

Мне тоже было сложно получить Seed() для вызова. И я действительно ценю все полезные предложения выше, и мне повезло с помощью DropCreateDatabaseAlways... но не ВСЕГДА!!

Совсем недавно я добавил в конструктор моего репозитория следующую строку кода:

    public CatalogRepository()
    {
        _formCatalog.FormDescriptors.GetType();

    }

Достаточно было вызвать вызов Seed(). Если вы пробовали все выше этого ответа и до сих пор не повезло, попробуйте. Удачи в этом было много времени.

Ответ 7

Событие посева в вашем примере будет запускаться только один раз, когда вы используете DropCreateDatabaseIfModelChanges, вы можете изменить это на DropCreateDatabaseAlways, я думаю, и он должен запускать семенное событие каждый раз.

Изменить

Это мой DataContext

public WebContext()
{   
    DbDatabase.SetInitializer(new DropCreateDatabaseIfModelChanges<WebContext>());
}

Ответ 8

Это произошло со мной, когда я обнаружил функции Code First. Эта ситуация часто возникает, когда вы сначала использовали Code First для создания своей базы данных без какой-либо стратегии инициализации.

Если вы решите сделать это позже, реализовав стратегию на основе DropCreateDatabaseIfModelChanges, но без изменения модели, то ваш метод Seed не будет вызываться, поскольку генерация базы данных и ваша стратегия будут применены только в следующий раз вы меняете свою модель.

Если это произойдет с вами, попробуйте немного изменить свою модель, чтобы проверить эту гипотезу, и я уверен, ваша база данных будет заполнена;)

У меня пока нет решения, кроме использования стратегии, которая всегда генерирует базу данных, но я действительно не уверен в том, что вы ставите стратегию инициализации в свой DbContext, так как этот класс будет использоваться в вас хотя стратегия инициализации, по-видимому, в основном используется для свободного развития окружающей среды.

Ответ 9

Я только что столкнулся с этой проблемой. Я удалил раздел "connectionstrings" из файла Web.config, и в настоящее время приложение запущено - без раздела connectionstrings! Я добавляю раздел назад, и база данных снова не посеяна. Это не правильное решение, но я просто добавляю здесь пункт данных, который может потенциально решить проблему.

К счастью, это просто небольшое "отброшенное" приложение, которое я скоро отброшу...

Ответ 10

Обновлено, чтобы отметить, что этот ответ неверен! Причина того, что моя БД не получает семя, остается загадкой (но это не было отсутствие вызова конструктора по умолчанию, как отмечено @JaredReisinger)

Я понимаю, что этот вопрос немного старый, но я оказался здесь, чтобы кто-то еще мог. Здесь моя таппенция стоит:

Моя БД создавалась отлично, но не была посевной, даже если я удалил базу данных и снова начал использовать DropDatabaseInitialiser.

После прочтения вышеприведенного кода я заметил, что мой конструктор контекста был этим

public MyApp_Context()
{
    // some code
}

тогда как приведенный выше пример будет следующим для моей установки

public MyApp_Context() : base("name=MyApp_Context")
{
    // some code
}

Yup, я не вызывал конструктор базового объекта! Я бы не ожидал, что все, кроме посева, будут работать в этом экземпляре, но это кажется (повторяемым) случаем.

NB, мне действительно не нужно указывать имя контекста в вызове базового конструктора; Я только написал это так, потому что я копировал формат решения выше. Итак, мой код теперь это, и сеяние работает при первоначальном создании базы данных.

public MyApp_Context() : base()
{
    // some code
}

Ответ 11

Тщательно убедитесь, что вы не объявляли свою переменную контекста более одного раза. Если вы объявите его снова после посева, семя будет перезаписано.

Ответ 12

У меня была такая же проблема, и после изменения в файле Global.asax и Intializer он работал. Я надеюсь, что это сработает для тех, у кого по-прежнему возникают проблемы при посеве данных.

Новый код в Global.asax:

    protected void Application_Start()
    {
        Database.SetInitializer<mycontextclassname>(new DropCreateDatabaseAlways<mycontextclassname>()); 
        Database.SetInitializer(new Initializer()); 
        ...
    }

код для файла Intializer:

public class Initializer : System.Data.Entity.DropCreateDatabaseAlways<Context>