如何避免向由 Seed 引起的 Entity Framework 管理的数据库添加重复项?

How avoid adding duplicates to database managed by Entity Framework caused by Seed?

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

我的Configuration.cs:

namespace SklepInternetowy1.Migrations
{
    using SklepInternetowy1.DAL;
    using System;
    using System.Data.Entity;
    using System.Data.Entity.Migrations;
    using System.Linq;

    public sealed class Configuration : DbMigrationsConfiguration<SklepInternetowy1.DAL.KursyContext>
    {
        public Configuration()
        {
            AutomaticMigrationsEnabled = false;
            ContextKey = "SklepInternetowy1.DAL.KursyContext";
        }

        protected override void Seed(SklepInternetowy1.DAL.KursyContext context)
        {
            KursyInitializer.SeedKursyData(context);
            //  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" }
            //    );
            //
        }
    }
}

我的KursyInitializer.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Data.Entity;
using SklepInternetowy1.Models;
using SklepInternetowy1.DAL;
using SklepInternetowy1.Migrations;
using System.Data.Entity.Migrations;

namespace SklepInternetowy1.DAL
{
    public class KursyInitializer : MigrateDatabaseToLatestVersion<KursyContext, Configuration>
    {
        public static void SeedKursyData(KursyContext context)
        {
            var kategorie = new List<Kategoria>
            {
                new Kategoria() {KategoriaID=1, NazwaKategorii="Asp123",NazwaPlikuIkony="asp.png", OpisKategorii="opis asp net mvc" },
                new Kategoria() {KategoriaID=2, NazwaKategorii="Java",NazwaPlikuIkony="java.png", OpisKategorii="opis java" },
                new Kategoria() {KategoriaID=3, NazwaKategorii="Php",NazwaPlikuIkony="php.png", OpisKategorii="opis php" },
                new Kategoria() {KategoriaID=4, NazwaKategorii="Html",NazwaPlikuIkony="html.png", OpisKategorii="opis html" },
                new Kategoria() {KategoriaID=5, NazwaKategorii="Css",NazwaPlikuIkony="css.png", OpisKategorii="opis css" },
                new Kategoria() {KategoriaID=6, NazwaKategorii="Xml",NazwaPlikuIkony="xml.png", OpisKategorii="opis xml" },
                new Kategoria() {KategoriaID=7, NazwaKategorii="C#",NazwaPlikuIkony="c#.png", OpisKategorii="opis c#" }
             };

            kategorie.ForEach(k => context.Kategorie.AddOrUpdate(k));
            context.SaveChanges();

            var kursy = new List<Kurs>
            {
                new Kurs() {AutorKursu="Tomek", TytulKursu="asp.net mvc1", KategoriaID=1, CenaKursu=100, Bestseller=true, NazwaPlikuObrazka="asd.png", DataDodania=DateTime.Now, OpisKursu="opis1" },
                new Kurs() {AutorKursu="Jacek", TytulKursu="asp.net mvc2", KategoriaID=2, CenaKursu=101, Bestseller=true, NazwaPlikuObrazka="asd1.png", DataDodania=DateTime.Now, OpisKursu="opis2" },
                new Kurs() {AutorKursu="Jarek", TytulKursu="asp.net mvc3", KategoriaID=3, CenaKursu=102, Bestseller=true, NazwaPlikuObrazka="asd2.png", DataDodania=DateTime.Now, OpisKursu="opis3" },
                new Kurs() {AutorKursu="Romek", TytulKursu="asp.net mvc4", KategoriaID=4, CenaKursu=103, Bestseller=true, NazwaPlikuObrazka="asd3.png", DataDodania=DateTime.Now, OpisKursu="opis4" }
            };

             kursy.ForEach(k => context.Kursy.AddOrUpdate(k));
             context.SaveChanges();
        }
    }
}

我的Kurs.cs:

namespace SklepInternetowy1.Models
{
    public class Kurs
    {
        public int KursID { get; set; }
        public int KategoriaID { get; set; }
        [Required(ErrorMessage = "Wprowadz nazwę kursu")]
        [StringLength(100)]
        public string TytulKursu { get; set; }
        [Required(ErrorMessage = "Wprowadz nazwę autora")]
        [StringLength(100)]
        public string AutorKursu { get; set; }
        public DateTime DataDodania { get; set; }
        [StringLength(100)]
        public string NazwaPlikuObrazka { get; set; }
        public string OpisKursu { get; set; }
        public decimal CenaKursu { get; set; }
        public bool Bestseller { get; set; }
        public bool Ukryty { get; set; }
        public string OpisSkrocony { get; set; }

        public virtual Kategoria Kategoria { get; set; }

    }
}

每次我 运行 应用程序,Seed 添加重复记录:

duplicates

问题:我必须更改什么才能避免 table Kurs 中出现重复?

您忘记绑定种子方法将检查其是添加还是更新的密钥。

只需更改以下行......

kursy.ForEach(k => context.Kursy.AddOrUpdate(x => x.AutorKursu, k));

我假设 "AutorKursu" 是您的主键。您可以根据需要设置此条件,这取决于 lamda 函数种子方法将确定需要的操作。

来自 Entity Framework 文档:

 identifierExpression:
        //     An expression specifying the properties that should be used when determining
        //     whether an Add or Update operation should be performed.

MSDN:https://msdn.microsoft.com/en-us/library/hh846514(v=vs.103).aspx

AddOrUpdate MSDN 文章中所述,此方法使用密钥 属性 来检查实体是否存在。在您的例子中,整数 属性 的默认值为 0。因此 EF 检查是否存在具有此类键的记录,并决定它应该为该实体创建一个新记录。 因此,您需要在每个记录的种子方法中显式定义 KursID 属性,以便 Entity Framework 知道相关项已经存在于数据中执行 AddOrUpdate 时的基数。