如何使用Entity Framework删除对象及其子对象?

时间:2016-05-18 16:44:03

标签: asp.net entity-framework asp.net-web-api

我正在尝试使用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>();
    }
}

2 个答案:

答案 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();
}