应该不是这么难!我即将放弃EF ......
我的模特有每周报纸版。每个版本都可以有很多分类。每个分类可以出现在一个或多个版本中。我的模特:
public class Classifieds
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int ClassifiedId { get; set; }
...
public virtual ICollection<EditionModel> Editions { get; set; }
}
public class EditionModel
{
[Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
public int EditionId { get; set; } // This is YYYYWW, WW = week number
public Date PublicationDate { get; set; }
public virtual ICollection<Classifieds> Classifieds { get; set; }
}
OnModelCreating覆盖:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Entity<EditionModel>()
.Property(z => z.EditionId)
.HasDatabaseGeneratedOption(DatabaseGeneratedOption.None);
modelBuilder.Entity<EditionModel>()
.HasMany(c => c.Classifieds)
.WithMany(d => d.Editions)
.Map(x =>
{
x.MapLeftKey("EditionId");
x.MapRightKey("ClassifiedId");
x.ToTable("EditionModelClassifieds");
});
base.OnModelCreating(modelBuilder);
}
创建分类广告操作代码(HTTP put):
public async Task<ActionResult> Create(Classifieds classifieds, int[] EditionList)
{
var allPubs = PopulateEditionList(); // Current and next 12 editions
db.Set<Classifieds>().Attach(classifieds);
db.Entry(classifieds).Collection(x => x.Editions).Load();
foreach (var p in EditionList)
{
var anEd = (from x in allPubs where x.EditionId == p select x).Single();
classifieds.Editions.Add(anEd);
}
...
if (ModelState.IsValid)
{
var ads = db.Classifieds.Add(classifieds);
await db.SaveChangesAsync().ConfigureAwait(false);
return View("Receipt", classifieds);
}
...
}
在提交新的分类广告时,我得到了
Violation of PRIMARY KEY constraint 'PK_dbo.EditionModels'.
Cannot insert duplicate key in object 'dbo.EditionModels'.
为什么EF坚持要在EditionModels中插入重复行而不是仅仅将连接表行链接到其中的现有行?我该如何解决这个问题?
答案 0 :(得分:3)
显然PopulateEditionList()
没有将版本附加到上下文中。在foreach
循环中添加此行:
db.Set<EditionModel>().Attach(anEd);
可能你可以简化整个程序。我不确定为什么要将版本加载到内存中。您可以根据足以创建关系的键创建“存根实体”。将classifieds
附加到上下文似乎是多余的,因为您要将其作为新实体添加到数据库中。尝试从数据库中为DB中尚不存在的父实体加载相关版本似乎也是多余的。结果只能是一个空集合。
因此,以下更简单的版本也可以起作用:
public async Task<ActionResult> Create(Classifieds classifieds, int[] EditionList)
{
classifieds.Editions = new List<EditionModel>();
foreach (var p in EditionList)
{
var anEd = new EditionModel { EditionId = p };
db.Set<EditionModel>().Attach(anEd);
classifieds.Editions.Add(anEd);
}
//...
if (ModelState.IsValid)
{
var ads = db.Classifieds.Add(classifieds);
await db.SaveChangesAsync().ConfigureAwait(false);
return View("Receipt", classifieds);
}
//...
}
答案 1 :(得分:0)
问题是EditionModel不是上下文的一部分。谢谢你,Slauma指出我正确的方向。更正的创建操作是:
...
classifieds.Editions = new List<EditionModel>();
foreach (var p in EditionList)
{
var ed = await db.EditionModel.FindAsync(p);
if (ed == null)
ed = new EditionModel { EditionId = p, PublicationDate = (from q in allPubs where q.EditionId == p select q).Single().PublicationDate };
InsertOrUpdate<EditionModel>(ed);
classifieds.Editions.Add(ed);
}
...
其余代码如上所述。