如何避免将重复项添加到由Seed方法导致的EntityFramework管理的数据库中?

Yod*_*oda 5 c# entity-framework seed duplicates asp.net-mvc-5.1

每次运行应用程序时,都会将相同的对象添加到数据库中(重复).

我的Global.asax:

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using WebApplication2.Migrations;
using WebApplication2.Models;


namespace WebApplication2 {
    public class MvcApplication : System.Web.HttpApplication {
        protected void Application_Start() {
            Database.SetInitializer(new MigrateDatabaseToLatestVersion<ApplicationDbContext, Configuration>()); 
            //Database.SetInitializer(new DropCreateDatabaseAlways<ApplicationDbContext>());
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

和我Configuration.csSeed方法:

namespace WebApplication2.Migrations
{
    using System;
    using System.Collections.Generic;
    using System.Data.Entity;
    using System.Data.Entity.Migrations;
    using System.Linq;
    using WebApplication2.Models;

    internal sealed class Configuration : DbMigrationsConfiguration<WebApplication2.Models.ApplicationDbContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = true;
            ContextKey = "WebApplication2.Models.ApplicationDbContext";
        }

        protected override void Seed(WebApplication2.Models.ApplicationDbContext context) {
            var persons = new List<Person> { 
         new Person{FirstName = "John", LastName = "Doe", CellNumber = "123-456-789", SecondaryPhoneNumber = "98873213", Address = "1street 2",BirthDate = DateTime.Now.Date, Pesel = "312312312", Notes = "Annoying"},
         new Person{FirstName = "Anna", LastName = "Doe", CellNumber = "113-456-789", SecondaryPhoneNumber = "98873213", Address = "1street 2",BirthDate = DateTime.Now.Date, Pesel = "548555672", Notes = "Less Annoying"}
        };

        persons.ForEach(person => context.Persons.AddOrUpdate(person));
        context.SaveChanges();

        var meetings = new List<Meeting>{
            new Meeting{PersonId = 1, Body = "Body of meeting", Date = DateTime.Now}
        };

        meetings.ForEach(meeting => context.Meetings.AddOrUpdate(meeting));
        context.SaveChanges();

        var statuses = new List<Status> {
            new Status{Name = "OK"},
            new Status {Name = "NOT_OK"}
        };

        statuses.ForEach(status => context.Statuses.AddOrUpdate(status));
        context.SaveChanges();

        }
    }
}
Run Code Online (Sandbox Code Playgroud)

每次运行应用程序时都会Seed添加重复记录:

在此输入图像描述

我需要评论Seed方法的内容以防止添加重复项.

问题:(1)我应该更改哪些Seed方法只会在迁移后重新创建数据库?

编辑:

Seed方法中有评论:

  //  This method will be called after migrating to the latest version.

            //  You can use the DbSet<T>.AddOrUpdate() helper extension method 
            //  to avoid creating duplicate seed data. E.g.
            //
            //    context.People.AddOrUpdate(
            //      p => p.FullName,
            //      new Person { FullName = "Andrew Peters" },
            //      new Person { FullName = "Brice Lambson" },
            //      new Person { FullName = "Rowan Miller" }
            //    );
            //
Run Code Online (Sandbox Code Playgroud)

但我的方法不仅在迁移后被称为ALWAYS.为什么会这样?

Jos*_*rer 9

这个页面(大约一半),这个来自这个答案

注意:向Seed方法添加代码是将固定数据插入数据库的众多方法之一.另一种方法是将代码添加到每个迁移类的Up和Down方法中.Up和Down方法包含实现数据库更改的代码.您将在"部署数据库更新"教程中看到它们的示例.

您还可以使用Sql方法编写执行SQL语句的代码.例如,如果您要将"预算"列添加到"部门"表并希望将所有部门预算初始化为$ 1,000.00作为迁移的一部分,则可以将以下代码行添加到该迁移的Up方法中:

Sql("UPDATE Department SET Budget = 1000");

您也可以考虑使用此答案中AddOrUpdate引用的方法,该方法也适用于您的目的.

我很快就改变了从上面链接的答案中获得的代码,如果下面的代码存在问题,请耐心等待.我相信,这个概念应该仍然相对清晰.

context.People.AddOrUpdate(c => c.PK, new Person() { PK = 0, FirstName = "John", ... })
context.People.AddOrUpdate(c => c.PK, new Person() { PK = 1, FirstName = "Anna", ... })
Run Code Online (Sandbox Code Playgroud)

  • 我现在使用了"AddOrUpdate",它仍然添加了重复项. (2认同)

Ant*_*Chu 6

您可以完全访问方法中的上下文Seed,因此您可以查询数据是否已存在.

例如,只有在表空的情况下才能对表进行播种...

protected override void Seed(WebApplication2.Models.ApplicationDbContext context) {

    if (!context.Persons.Any())
    {   
        var persons = new List<Person> { 
            new Person{FirstName = "John", LastName = "Doe", CellNumber = "123-456-789", SecondaryPhoneNumber = "98873213", Address = "1street 2",BirthDate = DateTime.Now.Date, Pesel = "312312312", Notes = "Annoying"},
            new Person{FirstName = "Anna", LastName = "Doe", CellNumber = "113-456-789", SecondaryPhoneNumber = "98873213", Address = "1street 2",BirthDate = DateTime.Now.Date, Pesel = "548555672", Notes = "Less Annoying"}
        };

        persons.ForEach(person => context.Persons.Add(person));
        context.SaveChanges();
    }

    if (!context.Meetings.Any())
    {
        var meetings = new List<Meeting>{
            new Meeting{PersonId = 1, Body = "Body of meeting", Date = DateTime.Now}
        };

        meetings.ForEach(meeting => context.Meetings.Add(meeting));
        context.SaveChanges();
    }

    if (!context.Statuses.Any())
    {
        var statuses = new List<Status> {
            new Status{Name = "OK"},
            new Status {Name = "NOT_OK"}
        };

        statuses.ForEach(status => context.Statuses.Add(status));
        context.SaveChanges();
    }

}
Run Code Online (Sandbox Code Playgroud)

你也可以使用AddOrUpdate,但你需要告诉EF如何使用第一个参数检查记录是否存在...

protected override void Seed(WebApplication2.Models.ApplicationDbContext context) {

    var persons = new List<Person> { 
        new Person{FirstName = "John", LastName = "Doe", CellNumber = "123-456-789", SecondaryPhoneNumber = "98873213", Address = "1street 2",BirthDate = DateTime.Now.Date, Pesel = "312312312", Notes = "Annoying"},
        new Person{FirstName = "Anna", LastName = "Doe", CellNumber = "113-456-789", SecondaryPhoneNumber = "98873213", Address = "1street 2",BirthDate = DateTime.Now.Date, Pesel = "548555672", Notes = "Less Annoying"}
    };

    persons.ForEach(person => context.Persons.AddOrUpdate(p => new { p.FirstName, p.LastName }, person));
    context.SaveChanges();

    var meetings = new List<Meeting>{
        new Meeting{PersonId = 1, Body = "Body of meeting", Date = DateTime.Now}
    };

    meetings.ForEach(meeting => context.Meetings.AddOrUpdate(m => m.Body, meeting));
    context.SaveChanges();

    var statuses = new List<Status> {
        new Status{Name = "OK"},
        new Status {Name = "NOT_OK"}
    };

    statuses.ForEach(status => context.Statuses.AddOrUpdate(s => s.Name, status));
    context.SaveChanges();

}
Run Code Online (Sandbox Code Playgroud)