将带有树的实体附加到EF

时间:2017-10-03 16:55:10

标签: c# entity-framework entity-framework-6 automapper

我有一个包含许多子实体的庞大表单,因此,我使用Automapper将树对象填充为EF对象。然后我想更新DB中的类似实体。任何方式将其附加到上下文?

我试着这样做:

        // ApplicationDriver has many child objects
        Infrastructure.Asset.ApplicationDriver driver = mapper.Map<Infrastructure.Asset.ApplicationDriver>(model);

        // get similar object from DB
        Infrastructure.Asset.ApplicationDriver currentApplication = db.ApplicationDrivers.Where(p => p.ApplicationId == model.ApplicationId).FirstOrDefault();

        if (currentApplication == null)
        {
            db.ApplicationDrivers.Add(driver);
        }
        else
        {
            // try to attach driver to current context. 
            // I want to 'replace' current object with all child objects in DB
            db.ApplicationDrivers.Attach(driver);
            currentApplication = driver;
        }
        await db.SaveChangesAsync();

我收到错误:

  

“附加”Infrastructure.Asset.ApplicationDriver“类型的实体   失败,因为同一类型的另一个实体已经相同   主键值。使用“附加”方法或时,可能会发生这种情况   将实体的状态设置为“未更改”或“已修改”(如果有)   图中的实体具有冲突的键值。这可能是因为   某些实体是新的,尚未收到数据库生成的密钥   值。在这种情况下,使用“添加”方法或“已添加”实体状态   跟踪图形,然后将非新实体的状态设置为   “视情况而定”或“修改”。“

我试试:

        var currentApplication = db.ApplicationDrivers.Where(p => p.ApplicationId == model.ApplicationId).FirstOrDefault();

        if (currentApplication == null)
        {
            db.ApplicationDrivers.Add(driver);
        }
        else
        {
            driver.Id = currentApplication.Id;
            db.ApplicationDrivers.Attach(driver);
        }
        await db.SaveChangesAsync();

并得到同样的错误。什么是不正确的以及如何解决此问题,而无需手动将所有子对象的每个属性从驱动程序复制到currentApplication?

2 个答案:

答案 0 :(得分:0)

如果要更新数据库,则无需附加到实体,并将db替换为当前对象:

    // ApplicationDriver has many child objects
    Infrastructure.Asset.ApplicationDriver driver = mapper.Map<Infrastructure.Asset.ApplicationDriver>(model);

    // get similar object from DB
    Infrastructure.Asset.ApplicationDriver currentApplication = db.ApplicationDrivers.Where(p => p.ApplicationId == model.ApplicationId).FirstOrDefault();

    if (currentApplication == null)
    {
        db.ApplicationDrivers.Add(driver);
    }
    else
    {
        //this will attach, and set state to modified
        //same as previous question, make sure you virtual properties are not populated to avoid unwanted duplicates. 
        db.Entry(driver).State = System.Data.Entity.EntityState.Modified; 
        currentApplication = driver;
    }
    await db.SaveChangesAsync();

答案 1 :(得分:0)

我找到了一篇文章:

https://www.devtrends.co.uk/blog/stop-using-automapper-in-your-data-access-code

似乎,最好不要使用automapper将DTO映射到EF以进行编辑。