【问题标题】:AutoMapper confuses ChangeTrackerAutoMapper 混淆了 ChangeTracker
【发布时间】:2017-08-09 12:07:59
【问题描述】:

我有一个Project 对象,它由许多嵌套对象组成。

将此对象保存到数据库:

  • 我只更改项目中的一个属性(作为测试),然后将其传递给我的 DAL。
  • 我使用 EF 从数据库加载现有项目。
  • 我将更改后的项目映射到现有项目。
var existingProject = 
    db.Project.Single(p => p.ID == changedProject.ID).Include(p => p.Something);

existingProject = Mapper.Map(changedProject, existingProject);

db.SaveChanges();

由于外键为空而失败,这并不奇怪,因为当我深入到更改跟踪器时,我可以看到它非常困惑:

var added = db.ChangeTracker.Entries().Where(e => e.State == EntityState.Added);

映射发生后,项目中的大量对象被标记为已添加(即使项目中没有添加或删除任何内容,我只更改了一个属性)。

这是因为 AutoMapper 会创建嵌套对象的新实例,而 EF 无法将这些实例与数据库中的现有对象相关联吗?

我在很多地方都看到过这种方法,AutoMapper 有没有办法与 ChangeTracker 一起工作,以便理解上述内容 - 还是手动映射所有内容更好? (就我而言,需要做很多工作)

【问题讨论】:

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


    【解决方案1】:

    首先清除目标集合。如果要映射到现有的 EF 集合,则需要 AutoMapper.Collection。

    【讨论】:

    • 这看起来很有希望,谢谢,虽然我使用的是 AutoMapper 3.3.1.0,所以可能需要更新。
    • 所以这有所不同,但现在 ChangeTracker 中的众多整体被标记为“修改”,而不是像以前那样“添加”。它们应该被标记为未更改,也许 EF 仍然会因为映射而识别到对象的更改?
    • 我会说检查SQL,如果那里有问题,请在github上报告,否则应该没问题。
    • 我的业务逻辑中有一个作为 null 的对象,而数据库填充了它(因此它将所有实体标记为不同)。重新填充这个解决了这个问题。很棒的工具 - 这种方法比我遇到的数百个可怕的实现要顺畅得多!
    【解决方案2】:

    这是因为当您进行映射时,会创建新实体,而 EF 上下文没有关于它的任何信息。 您可以将数据从 db 映射到您的“changedProject”,然后进行所有必要的更改,然后再次映射到“existingProject”,并为此实体调用“Update”方法,如下例所示(使用 System.Data.EntityState.Modified) Updating records using a Repository Pattern with Entity Framework 6

    【讨论】:

    • 最后,当您从“changedProject”映射回“existingProject”时,这肯定会导致同样的问题吗? (AutoMapper 将创建新实体)
    • 是的,它正在创建新实例,但随后更新方法将它们重新附加到上下文中作为“修改”而不是“添加”状态
    • 明白了,但这不是设置所有要修改的东西吗?如果 5000 个属性中只有 1 个属性发生了变化,它会去更新它们。
    • 您是对的,它将更新此实体中的所有属性。它不适用于导航属性(如果您添加,那么它也会添加所有导航属性)。可能一个实体没有 5k 列 :) 但我知道你的意思。还有一种方法可以仅将属性标记为已修改,但您需要知道哪个属性已更改,因为 ChangeTracker 不知道。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-25
    • 1970-01-01
    • 2016-06-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多