Entity Framework 在 Seeding 数据库中插入重复项

Entity Framework inserting duplicates on Seeding database

编辑----

here 开始,我尝试在播种方法中分配 ID,这 语言没问题 但当我向客户添加地址并将 ID 分配给这些地址,而不是它再次制造了骗局...

地址和语言在我的上下文中都声明为 DbSet<...>

我尝试了什么:

我的 Customer 上有一个 Override ToString() 方法,return 它的名称,我可以观察到当我在调试时查看副本时 1 是名称,另一个是名称空间客户 class 居住在,这似乎是 loguc,因为在 Dupes 案例中 Name 为 NULL 但我想无论如何都要提到它......

----编辑

我正在用一些元数据为我的数据库播种,我发现它有一个我以前从未见过的非常奇怪的行为。我正在插入一个实体 "Customer" 并且它插入该实体 2 次,第一次插入是正确的并且具有它应该具有的所有内容,另一个具有 NULL 属性(字符串值)但一些(如日期时间)具有值。

我完全不知道为什么会这样,它是在我调用 base.Seed(ctx) 时发生的;方法,我敢肯定,因为我在此之后停止了 Webapp,然后才到达其他任何地方。

这个实体客户有一个相关的实体语言以及一个地址集合。

我有 (还没有建议)发生同样的问题,而且是突然发生的,我自己没有对我的模型或播种方法进行任何更改...

基础实体:

public class BaseEntity
{
    public int ID { get; set; }
}

客户:

public class Customer:BaseEntity
{
    public string Name { get; set; }
    public Language Language { get; set; }
    public ICollection<Address> Addresses { get; set; }
}

语言:

public class Language : BaseEntity

{
    public string Name { get; set; }
    public string LanguageCode { get; set; }

    [Required]
    public ICollection<Customer> Customers { get; set; }
}

地址:

public class Address : BaseEntity
{
    public Customer Customer { get; set; }
}

播种方式:

  Language newLanguageNL = new Language("Dutch");
  newLanguageNL.ID = 1;

  Language newLanguageFR = new Language("French");
  newLanguageFR.ID = 2;

  Language newLanguageEN = new Language("English");
  newLanguageEN.ID = 3;

  ctx.Languages.Add(newLanguageNL); 
  ctx.Languages.Add(newLanguageEN); 
  ctx.Languages.Add(newLanguageFR);

  Address addressBE = new Address("informatica laan", "10", "bus nr 1", "8900", "België");
  addressBE.ID = 1;

  Address addressBE2 = new Address("rue de l'informatique", "20", "boite nr 2", "7780", "Belgique");
  addressBE2.ID = 2;

  Address addressEN = new Address("techstreet", "30", "box nr 1", "4000", "Bulgaria");
  addressEN.ID = 3;

  ctx.Addresses.Add(addressEN);
  ctx.Addresses.Add(addressBE);
  ctx.Addresses.Add(addressBE2);

  Customer newCustomer = new Customer("Customer name", newLanguageNL, addressBE);
  // ctx.Customers.AddOrUpdate(c => c.Name, newCustomer);
  ctx.Customers.Add(newCustomer);

  base.Seed(ctx);

OnModelCreating:

     protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        base.OnModelCreating(modelBuilder);      

        // setting the Product FK relation required + related entity
        modelBuilder.Entity<Entity.ProductSupplierForContract>().HasRequired(psfc => psfc.Product)
                                                            .WithMany(p => p.ProductSupplierForContracts)
                                                            .HasForeignKey(psfc => psfc.Product_Id);

        // setting the Supplier FK relation required + related entity
        modelBuilder.Entity<Entity.ProductSupplierForContract>().HasRequired(psfc => psfc.Supplier)
                                                           .WithMany(s => s.ProductSupplierForContracts)
                                                           .HasForeignKey(psfc => psfc.Supplier_Id);

        // setting the Contract FK relation required + related entity
        modelBuilder.Entity<Entity.ProductSupplierForContract>().HasOptional(psfc => psfc.Contract)
                                                          .WithMany(c => c.ProductSupplierForContracts)
                                                          .HasForeignKey(psfc => psfc.Contract_Id);


        modelBuilder.Entity<Entity.PurchasePrice>()
     .ToTable("PurchasePrices");

        modelBuilder.Entity<Entity.SalesPrice>()
    .ToTable("SalesPrices");

        // Bundle in Bundle
        modelBuilder.Entity<Entity.Bundle>().HasMany(b => b.ChildBundles);                      
    }

任何人都可以帮助我解决这个问题,提前感谢您的任何反馈。 我试过使用 AddOrUpdate() 但没有成功。

您向客户建议的地址和语言会保留下来。我认为在您的构造函数中,您向客户建议了集合,不是吗? 这不是必需的。您可以在没有明确的集合建议的情况下保留客户。 EF 将自行映射集合。

我发现您的代码存在一些问题。按照惯例,一个名为 ID 的 int 列将成为一个标识列,因此您不能在不发出 SET IDENTITY_INSERT Language ON 的情况下显式设置它的 ID(除非您有流畅的代码覆盖它)。

AddOrUpdate 适用于这些情况。您没有显示该代码。另一种方式如下所示:

...
if (!ctx.Languages.Any(l => l.ID == 1))  // Check if already on file
{
    ctx.Database.ExecuteSqlCommand("SET IDENTITY_INSERT Language ON");  // Omit if not identity column
    var dutch = new Language {
        ID = 1,
        Name = "Dutch",
        Code = "NL"
    };
    ctx.Languages.Add(dutch);
    ctx.SaveChanges();
    ctx.Database.ExecuteSqlCommand("SET IDENTITY_INSERT Language OFF"); // Omit if not identity column
}
... repeat for other languages
... similar code for other seeded tables

因此,将实体 CustomerAddress Class 中的关系更改为 ICollection 而不是 1 个 Single Customer 不会'创建一个骗子(并创建一个我真正想要的 CustomerAddress table)。

从数据库日志 (log4net) 看来,由于关系,EF 首先为客户的地址引用插入客户 (NULL),然后插入客户 (NOT NULL) 及其引用 ... 当我比较了 Address & Language 我看到 Language 也有一个客户集合(哪个 Address 没有),这解释了为什么 Address 创建了重复的客户条目。 (如果有人需要对此进行任何澄清,请告诉我我会尽力而为)

这个post

我要感谢所有以任何方式做出贡献的人!