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

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

В примечании, можно ли вызвать инициализатор без ссылки на мой DatabaseContext в клиенте?

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

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

  1. Я удалил строку подключения (так как в любом случае по умолчанию используется sqlexpress, только имя изменилось)
  2. Я изменил 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);
}

Ответы [ 12 ]

37 голосов
/ 13 июня 2011

Вот так выглядят все мои классы 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
    }
}

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

10 голосов
/ 11 февраля 2012

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

9 голосов
/ 22 ноября 2012

Это моя грустная маленькая сказка.

Сначала извлеченные уроки:

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

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

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

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

  1. У меня был свой собственный класс Initializer в моем файле Global.asax.cs. У меня была точка останова на моем методе Seed Initializer; Я запустил приложение, и метод никогда не получил удар. (
  2. Я указываю точку останова в своем вызове Database.SetInitializer в Application_Start. Это никогда не получало удар. (
  3. Я понял, что у меня не было изменений схемы БД, поэтому я изменил DropCreateDatabaseIfModelChanges на DropCreateDatabaseAlways. Еще ничего. (
  4. Я наконец-то зашел на страницу, которая использует контекст, и это сработало. : /
3 голосов
/ 15 апреля 2013

Вы можете вызвать update-database, чтобы вручную запустить метод seed внутри класса 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" }
        );
    }
}
2 голосов
/ 14 июня 2012

У меня сработало следующее изменение в файле 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()); 
        ...
    }
1 голос
/ 28 декабря 2012

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

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

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

    }

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

0 голосов
/ 21 августа 2016

У меня возникла та же проблема, и после изменения как файла 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>
0 голосов
/ 05 января 2016

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

0 голосов
/ 09 июля 2013

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

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

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

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

public MyApp_Context()
{
    // some code
}

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

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

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

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

public MyApp_Context() : base()
{
    // some code
}
0 голосов
/ 16 июня 2012

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

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

...