Entity Framework 多对多 - Code First - 迁移
Entity Framework many to many - Code First - Migrations
我有产品 class:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Language> Languages { get; set; }
}
语言class:
public class Language
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Product> Products { 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");
}
}
这按预期创建了第三个 table,但是当我使用以下种子执行我的更新数据库时:
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();
}
它像这样更新关系 table ProducLanguages:
正在插入一种不存在的语言(数字4),我期望的结果是:
我做错了什么?
提前致谢。
您需要指定每个实体的 Id
,即使 PK 是身份。指定将在数据库中使用的 Id
至关重要,否则每个 Update-Database
都会创建新记录。
您还应该使用在 migrations.In 期间为播种数据创建的 AddOrUpdate
扩展方法,您可以指定一个表达式来了解应该使用什么 属性 来检查是否有必要执行 Add
或 Update
操作,但如果您未在实体中指定 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();
}
我有产品 class:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Language> Languages { get; set; }
}
语言class:
public class Language
{
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<Product> Products { 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");
}
}
这按预期创建了第三个 table,但是当我使用以下种子执行我的更新数据库时:
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();
}
它像这样更新关系 table ProducLanguages:
正在插入一种不存在的语言(数字4),我期望的结果是:
我做错了什么?
提前致谢。
您需要指定每个实体的 Id
,即使 PK 是身份。指定将在数据库中使用的 Id
至关重要,否则每个 Update-Database
都会创建新记录。
您还应该使用在 migrations.In 期间为播种数据创建的 AddOrUpdate
扩展方法,您可以指定一个表达式来了解应该使用什么 属性 来检查是否有必要执行 Add
或 Update
操作,但如果您未在实体中指定 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();
}