C# 实体框架多对多-代码优先-迁移
我有产品类别:C# 实体框架多对多-代码优先-迁移,c#,.net,entity-framework,ef-code-first,migration,C#,.net,Entity Framework,Ef Code First,Migration,我有产品类别: public class Product { public int Id { get; set; } public string Name { get; set; } public virtual ICollection<Language> Languages { get; set; } } 公共类产品 { 公共int Id{get;set;} 公共字符串名称{get;set;} 公共虚拟ICollection语言{get;set;} } 语言班: public
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Language> Languages { get; set; }
}
公共类产品
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共虚拟ICollection语言{get;set;}
}
语言班:
public class Language
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Product> Products { get; set; }
}
公共类语言
{
公共int Id{get;set;}
公共字符串名称{get;set;}
公共虚拟ICollection产品{get;set;}
}
在我的EntityTypeConfiguration中:
public class ProductMap : EntityTypeConfiguration<Product>
{
public ProductMap()
{
HasKey(m => m.Id);
Property(p => p.Name).IsRequired();
HasMany(p => p.Languages)
.WithMany(l => l.Products)
.Map(x => x.ToTable("ProducLanguages")
.MapLeftKey("ProductId")
.MapRightKey("LanguageId"));
//Table
ToTable("Products");
}
}
公共类ProductMap:EntityTypeConfiguration
{
公共产品地图()
{
HasKey(m=>m.Id);
属性(p=>p.Name).IsRequired();
有许多(p=>p.Languages)
.有许多(l=>l.产品)
.Map(x=>x.ToTable(“产品语言”)
.MapLeftKey(“产品ID”)
.MapRightKey(“LanguageId”);
//桌子
ToTable(“产品”);
}
}
这将按预期创建第三个表,但当我使用以下种子执行更新数据库时:
protected override void Seed(EcoomerceContext context)
{
var languages = new List<Language>
{
new Language {Name = "Portuguese"},
new Language {Name = "English"},
new Language {Name = "Spanish"}
};
var languagePt = new List<Language>
{
new Language {Name = "Portuguese"},
};
//languages.ForEach(a => context.Languages.Add(a));
new List<Product>
{
new Product {Name = "NameProduct1", Languages = languages},
new Product {Name = NameProduct2 , Languages = languagePt},
}.ForEach(a => context.Products.Add(a));
context.SaveChanges();
}
protected override void Seed(ecoomercontext上下文)
{
var语言=新列表
{
新语言{Name=“葡萄牙语”},
新语言{Name=“English”},
新语言{Name=“西班牙语”}
};
var languagePt=新列表
{
新语言{Name=“葡萄牙语”},
};
//languages.ForEach(a=>context.languages.Add(a));
新名单
{
新产品{Name=“NameProduct1”,Languages=Languages},
新产品{Name=NameProduct2,Languages=languagePt},
}.ForEach(a=>context.Products.Add(a));
SaveChanges();
}
它更新关系表ProducLanguages,如下所示:
它插入了一种不存在的语言(数字4),我期望的结果是:
我做错了什么
提前感谢。您需要指定每个实体的
Id
,即使PK是Identity。指定将在数据库中使用的Id
是至关重要的,否则每个更新数据库将创建新记录
此外,您还应该使用在迁移期间为种子数据创建的扩展方法。在此方法中,您可以指定一个表达式,以了解应该使用什么属性来检查是否需要执行添加
或更新
操作,但如果您没有在实体中指定Id
,将添加新行,旧行也将保留。因此,最后,您的Seed
方法可以是这样的:
protected override void Seed(ConsoleApplication3.YourContext context)
{
var languages = new[]
{
new Language {Id = 1, Name = "Portuguese"},
new Language {Id = 2, Name = "English"},
new Language {Id = 3, Name = "Spanish"},
new Language {Id = 4, Name = "French"},
};
// This way you can add all the languages even when there is not associated to a product
// The first parameter is an expression to know what properties should be used when determining whether an Add or Update operation should be performed
context.Languages.AddOrUpdate(l => l.Name, languages);
var products = new[]
{
new Product {Id = 1, Name = "NameProduct1", Languages = new List<Language> {languages[0],languages[1],languages[3]}},
new Product {Id = 2, Name = "NameProduct2", Languages = new List<Language> {languages[0]}},
};
context.Products.AddOrUpdate(p=>p.Name,products);
context.SaveChanges();
}
受保护的覆盖无效种子(ConsoleApplication3.YourContext)
{
var languages=new[]
{
新语言{Id=1,Name=“葡萄牙语”},
新语言{Id=2,Name=“English”},
新语言{Id=3,Name=“西班牙语”},
新语言{Id=4,Name=“French”},
};
//这样,即使没有与产品关联的语言,也可以添加所有语言
//第一个参数是一个表达式,用于知道在确定是否应执行添加或更新操作时应使用哪些属性
context.Languages.AddOrUpdate(l=>l.Name,Languages);
var产品=新[]
{
新产品{Id=1,Name=“NameProduct1”,Languages=new List{Languages[0],Languages[1],Languages[3]},
新产品{Id=2,Name=“NameProduct2”,语言=新列表{Languages[0]},
};
context.Products.AddOrUpdate(p=>p.Name,Products);
SaveChanges();
}
我做了您的更改,得到了相同的结果。