【问题标题】:Attach entities with tree to EF将带有树的实体附加到 EF
【发布时间】:2018-03-14 22:51:43
【问题描述】:

我有一个包含许多子实体的巨大表单,因此,我使用 Automapper 用树填充 EF 对象。然后我想更新数据库中的类似实体。有什么方法可以将其附加到上下文中?

我尝试这样做:

        // 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 的情况下解决此问题?

【问题讨论】:

  • @IvanStoev。非常奇怪的错误:将 datetime2 数据类型转换为 datetime 数据类型导致值超出范围。\r\n语句已终止
  • 这似乎与原始问题无关。你解决了吗?

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


【解决方案1】:

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

    // 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();

【讨论】:

    【解决方案2】:

    我找到了一篇文章:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-01-18
      • 2020-05-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-08
      相关资源
      最近更新 更多