我正在尝试使用EF删除对象和其他一些子对象。这是我正在使用的方法:
public async Task<IHttpActionResult> Delete([FromBody]WordForm wordForm)
{
var olddObj = db.WordDefinitions
.Where(w => w.WordFormId == wordForm.WordFormId)
.AsNoTracking()
.ToList();
foreach (var wordDefinition in olddObj)
{
db.WordDefinitions.Attach(wordDefinition);
db.WordDefinitions.Remove(wordDefinition);
}
db.WordForms.Attach(wordForm);
db.WordForms.Remove(wordForm);
await db.SaveChangesAsync();
return Ok();
}
任何人都可以向我解释为什么我会收到这条消息:
附加“Entities.Models.Core.WordDefinition”类型的实体 失败,因为同一类型的另一个实体已经相同 主键值。使用“附加”方法或时,可能会发生这种情况 将实体的状态设置为“未更改”或“已修改”(如果有) 图中的实体具有冲突的键值。这可能是因为 某些实体是新的,尚未收到数据库生成的密钥 值。在这种情况下,使用“添加”方法或“已添加”实体状态 跟踪图形,然后将非新实体的状态设置为 “视情况而定”或“修改”。
这是对象定义:
public class WordForm
{
public string WordFormId { get; set; } // WordFormId (Primary key) (length: 20)
public int WordFormIdentity { get; set; } // WordFormIdentity
// Reverse navigation
public virtual System.Collections.Generic.ICollection<WordDefinition> WordDefinitions { get; set; } // WordDefinition.FK_WordDefinitionWordForm
public WordForm()
{
WordDefinitions = new System.Collections.Generic.List<WordDefinition>();
}
}
答案 0 :(得分:2)
我知道这可能不是您想要的解决方案,但您可以将数据库中的“删除规则”设置为“级联”,每当您删除某个对象时,其所有子项都将被删除。
答案 1 :(得分:2)
从查询返回时,方法的第一部分已经将对象加载到图形中,因此无需附加它们。只需删除已加载的对象。第二个附加应该可以正常工作,但也可以使用其主键将其加载到图形中,然后将其删除。
以下是您的方法的重构版本......
public async Task<IHttpActionResult> Delete([FromBody]WordForm wordForm) {
if(wordForm == null) return BadRequest();
var toRemove = db.WordForms.FirstOrDefault(w => w.WordFormId == wordForm.WordFormId);
if(toRemove != null) {
var olddObj = db.WordDefinitions
.Where(w => w.WordFormId == wordForm.WordFormId)
.ToList();
//removing children
foreach (var wordDefinition in olddObj) {
db.WordDefinitions.Remove(wordDefinition);
}
//remove parent object
db.WordForms.Remove(toRemove);
await db.SaveChangesAsync();
return Ok();
}
return NotFound();
}