Заполнение не работает в Entity Framework Code First Approach

Я разрабатываю проект .Net. Я использую первый подход кода структуры сущности для взаимодействия с базой данных. Я загружаю некоторые фиктивные данные в свою базу данных во время разработки. Но посев не работает. Я перешел по этой ссылке - http://www.entityframeworktutorial.net/code-first/seed-database-in-code-first.aspx.

Это мой класс ContextInitializer

public class ContextInitializer : System.Data.Entity.CreateDatabaseIfNotExists<StoreContext>
    {

        protected override void Seed(StoreContext context)
        {
            IList<Brand> brands = new List<Brand>();
            brands.Add(new Brand { Name = "Giordano" ,TotalSale = 1 });
            brands.Add(new Brand { Name = "Nike" , TotalSale = 3 });

            foreach(Brand brand in brands)
            {
                context.Brands.Add(brand);
            }
            base.Seed(context);
            context.SaveChanges();

        }
    }

Это мой класс контекста

public class StoreContext : DbContext,IDisposable
    {
        public StoreContext():base("DefaultConnection")
        {
            Database.SetInitializer(new ContextInitializer());
        }

        public virtual DbSet<Category> Categories { get; set; }
        public virtual DbSet<Brand> Brands { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
        }
   }

Это мой класс бренда

public class Brand
    {
        public int Id { get; set; }
        [Required]
        [MaxLength(40)]
        public string Name { get; set; }
        public int TotalSale { get; set; }
    }

Я искал решения в Интернете и следовал инструкциям. Я также запускаю context.SaveChanges. Но это не заполнение данных в базе данных. Почему это не работает?


person Wai Yan Hein    schedule 06.07.2016    source источник


Ответы (3)


Вы берете неправильный инициализатор, CreateDatabaseIfNotExists вызывается только в том случае, если база данных не существует!

Вы можете использовать, например, DropCreateDatabaseIfModelChanges:

Решение 1)

public class ContextInitializer : System.Data.Entity.DropCreateDatabaseIfModelChanges<StoreContext>
{

Вы должны быть осторожны с этим подходом, он !!!удаляет!!! все существующие данные.

Решение 2)

Создайте пользовательскую конфигурацию DbMigrationsConfiguration:

public class Configuration : DbMigrationsConfiguration<StoreContext>
{
    public Configuration()
    {
        // Take here! read about this property!
        this.AutomaticMigrationDataLossAllowed = true;
        this.AutomaticMigrationsEnabled = false;
    }

    protected override void Seed(StoreContext context)
    {
        IList<Brand> brands = new List<Brand>();
        brands.Add(new Brand { Name = "Giordano", TotalSale = 1 });
        brands.Add(new Brand { Name = "Nike", TotalSale = 3 });

        foreach (Brand brand in brands)
        {
            context.Brands.AddOrUpdate(m => m.Name, brand);
        }
        base.Seed(context);
        context.SaveChanges();
    }
}

Таким образом, вы можете вызывать ( !! Перед созданием DbContext или в конструкторе DbContext !!):

// You can put me also in DbContext constuctor     
Database.SetInitializer(new MigrateDatabaseToLatestVersion<StoreContext , Yournamespace.Migrations.Configuration>("DefaultConnection"));

Заметки:

  • DbMigrationsConfiguration необходимо знать о строке подключения, которую вы можете предоставить в конструкторе или извне.
  • In Your DbMigrationsConfiguration you can configure also:
    • MigrationsNamespace
    • МиграцииСборка
    • Каталог миграций
    • целевая база данных

Если оставить все по умолчанию, как в моем примере, то ничего менять не надо!

person Bassam Alugili    schedule 06.07.2016

Установка инициализатора для базы данных должна происходить ДО, когда контекст будет создан, поэтому...

    public StoreContext():base("DefaultConnection")
    {
        Database.SetInitializer(new ContextInitializer());
    }

слишком поздно. Если бы вы сделали его статическим, то он мог бы работать:

    static StoreContext()
    {
        Database.SetInitializer(new ContextInitializer());
    }
person Erik Philips    schedule 06.07.2016
comment
Я добавил этот статический StoreContext() { Database.SetInitializer(new ContextInitializer()); } ниже существующего конструктора. Но это не работает. Я не могу удалить существующий конструктор, потому что он определяет строку подключения и выдает ошибку, если я это сделаю. Пожалуйста, что не так с тем, что я делаю, пожалуйста? - person Wai Yan Hein; 06.07.2016
comment
Ой. Я думаю, мне нужно добавить этот ‹contexts› ‹context type=PatheinFashionStore.Domain.Concrete.ContextInitializer, PatheinFashionStore› ‹databaseInitializer type=PatheinFashionStore.Domain.Concrete.StoreContext, PatheinFashionStore /› ‹/context› ‹/contexts› в сеть. файл конфигурации. Но когда я добавляю, он говорит, что не может установить инициализатор. Я установил PatheinFashionStore.Domain.Concrete.StoreContext в качестве класса контекста и основного проекта PatheinFashionStore. Так что, пожалуйста, это правильно. То, как я устанавливаю. - person Wai Yan Hein; 06.07.2016
comment
У меня такое чувство, что вы не понимаете сценарий">Когда вызывается метод Seed в сценарии первой миграции кода EF?. - person Erik Philips; 06.07.2016
comment
Метод Seed() в инициализаторе базы данных вызывается при создании базы данных и не обрабатывает существующие данные (начальное значение из DbMigrationsConfiguration обрабатывает их, проверяя, существуют ли указанные объекты). - person Erik Philips; 06.07.2016

Ваш код работает, если вы удалите существующую базу данных, а EF создаст и заполнит данные

Или

Вы можете использовать DbMigrationsConfiguration вместо CreateDatabaseIfNotExists и изменить свой код следующим образом:

Сначала вам нужно удалить существующую базу данных

Класс ContextInitializer

public class ContextInitializer : System.Data.Entity.Migrations.DbMigrationsConfiguration<StoreContext>
{
    public ContextInitializer()
    {
        this.AutomaticMigrationDataLossAllowed = true;
        this.AutomaticMigrationsEnabled = true;
    }
    protected override void Seed(StoreContext context)
    {
        IList<Brand> brands = new List<Brand>();
        brands.Add(new Brand { Name = "Giordano", TotalSale = 1 });
        brands.Add(new Brand { Name = "Nike", TotalSale = 3 });

        foreach (Brand brand in brands)
        {
            context.Brands.AddOrUpdate(m => m.Name, brand);
        }
        base.Seed(context);
        context.SaveChanges();

    }
}

StoreContext

public class StoreContext : DbContext, IDisposable
    {
        public StoreContext() : base("DefaultConnection")
        {
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<StoreContext, ContextInitializer>());
            //  Database.SetInitializer(new ContextInitializer());
        }

        public virtual DbSet<Category> Categories { get; set; }
        public virtual DbSet<Brand> Brands { get; set; }

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
        }
    }

Затем любое изменение в вашем семени будет автоматически отражено в вашей базе данных.

person Abdul Hadi    schedule 06.07.2016
comment
Если я наследую от DbMigrationsConfiguration, он выдает ошибку во время компиляции. - person Wai Yan Hein; 06.07.2016
comment
попробуйте добавить с помощью System.Data.Entity.Migrations; - person Abdul Hadi; 06.07.2016
comment
Когда я запускаю, выдается исключение Невозможно обновить базу данных, соответствующую текущей модели. Когда я обновляю базу данных из консоли, она говорит, что в сборке «PatheinFashionStore.Domain» найдено более одного типа конфигурации миграции. Укажите имя используемого. Я использую второй способ. - person Wai Yan Hein; 06.07.2016