具有Automapper的EF Core引发异常“无法跟踪实体类型”

杜斯曼

EF Core与自动映射器结合使用时出现问题。

我的解决方案包含以下层次结构:

BLL <=> DAL <=> EF Core <=> Mysql Database

我在BLL中使用自动映射器。

并以该用户类为例:

public class User
{
    public Guid Id { get; set; } = Guid.NewGuid();

    public string FirstName { get; set; }

    public string LastName { get; set; }

    public Guid? CreatedById { get; set; }

    public Guid? ModifiedById { get; set; }

    public virtual User CreatedBy { get; set; }

    public virtual User ModifiedBy { get; set; }
}

和我有相同的类UserDTO(DataTransferObject)。

我已经在数据库中有一个用户创建另一个用户的记录,因为创建或更新用户必须填写createdby和Modifyby。

从数据库获取用户:

UserDTO userDTO = this._UserBLL.GetUser("Unit", "Test");

//BLL
var mapped = new List<UserDTO>();
this._Mapper.Map(dalResult, mapped); //dalResult = List<User> object
return mapped;

这里是一个如何添加用户的示例:

UserDTO testUser2 = new UserDTO
{
    FirstName = "Test 2",
    LastName = "Test 2",
    CreatedBy = userDTO,
    ModifiedBy = userDTO
};

this._UserBLL.Add(testUser2);

//BLL
List<User> mappedUsers = new List<User>();

this._Mapper.Map(users, mappedUsers); //users = List<UserDTO> that contains testUser2

DbContext.Users.AddRange(mappedUsers); //Throws exception
DbContext.SaveChanges();

抛出的异常: The instance of entity type 'User' cannot be tracked because another instance with the same key value for {'Id'} is already being tracked.

但是我不知道如何解决异常。同样的问题是,当我更新现有记录时。

自动映射类为:

this.CreateMap<User, UserDTO>()
    .ReverseMap();

你有一个解决办法吗?希望您了解我的问题,否则请问我。

国王的问候

罗德·拉米雷斯(RodRamírez)

这里有一些误解

  1. 切记DTO是一个愚蠢的类,从某种意义上说,它只是充当信息以强类型传播的容器而已。通常,当前端向您发送一些数据并且后端捕获到控制器参数(我知道这并不完全正确,只是试图在此处提出要点)时,或者在将DTO返回到前端时,您通常会处理DTO。终止于任何需要的理由。那么一般的方法将是:

  2. 前端发送了DTO

  3. 后端控制器捕获

  4. 后端服务将DTO映射到感兴趣的某些域模型(自动映射器)

  5. 后端服务执行业务规则的逻辑步骤,例如将记录保存在数据库中或更新一些我不知道您为它命名的内容

  6. 后端服务将响应(如果有)映射到DTO(自动映射器)

  7. 后端控制器将数据直接发送回前端,以执行所需的任何操作

现在,关于您的错误,这是实体框架入门者的常见错误。让我说明发生了什么:

UserDTO userDTO = this._UserBLL.GetUser("Unit", "Test"); 
//tip: as per the explanation above this should't be a DTO

//EF says "alright!, programmer pull out
//a record from the database and got a object of type UserDTO with Id = "someguid"
//im gonna begin tracking this object to see if it changes in the
//execution of the code.
//In case my fellow programmer wants to modify this object and 
//save it in on the database, as I was tracking it down in 
//the first place, I'm gonna know how to build my
//SQL statements to perform the right update/delete/create sentence in 
//SQL form.

在映射的某处,您正在使用相同的ID创建相同的对象类型,然后实体框架成为主流

//EF says: "mmm, that's weird, im tracking the same object 
//again, im gonna alert the human. *throws exception*

此处的关键是重新阅读实体框架/核心的文档,以完全了解实体框架的想法。现在,关于代码和业务需求,您应该致力于执行以下操作:

//Suppose that the in the controller parameter we receive this DTO
var newUserDto = new UserDto() 
{
    Firstname = "Rodrigo",
    Lastname = "Ramirez",
    CreatedBy = 1, //this can be the user Id of the user that sent this DTO
};

var userToCreate = Mapper.Map<User>(newUserDto);
var userCreator = UserRepository.GetById(newUserDto.CreatedBy);
userToCreate.CreatedBy = userCreator;

关于该主题的最后几句话:

  1. 这是一个偏好问题,但我宁愿阅读
var user = Mapper.Map<User>(newUserDto); //hey mapper, be a pal and transform this newUserDto into a User object.
  1. 不需要时,请检查是否使用List <>进行映射。
  2. 对于此业务逻辑,您无需阻止实体框架开始跟踪给定实体。但是,如果发现这种情况,可以签出执行此操作的方法“ AsNoTracking()”。
  3. 查看通过用户类实例创建新的GUID的必要性。这似乎是有问题的,您需要完全了解EF的工作方式才能成功进行此操作。
  4. 您想要做的事情是常见的审计实践,建议您重写方法OnSaveChanges()来执行此任务。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

EF Core 更新无法跟踪实体类型“广告”的实例

来自分类Dev

EF Core:无法跟踪实体类型的实例,因为另一个具有相同键值的实例

来自分类Dev

无法跟踪实体类型“ TestType”的实例,因为已经跟踪了具有相同键的该类型的另一个实例

来自分类Dev

EF,Automapper异常,“附加类型...的实体失败,因为相同类型的另一个实体已经具有相同的主键值”

来自分类Dev

无法跟踪实体类型“ x”的实例,因为已经跟踪了具有相同的{'a','b'}键值的另一个实例

来自分类Dev

无法跟踪实体类型 <T> 的实例,因为已跟踪另一个具有相同 {'Id'} 键值的实例

来自分类Dev

“如何修复“实体类型的实例”无法跟踪,因为另一个具有键值“{TypeId: 1}”的实例已被跟踪。

来自分类Dev

ASP.NET Core - 无法跟踪实体类型的实例

来自分类Dev

EF代码优先:具有多个多对一关系的实体类型

来自分类Dev

具有TPH继承的实体类型到多个表的EF映射属性

来自分类Dev

具有TPH继承的实体类型到多个表的EF映射属性

来自分类Dev

EF代码优先:具有多个多对一关系的实体类型

来自分类Dev

在EF 6中更新现有数据会引发异常-“ ...相同类型的实体已经具有相同的主键值。”

来自分类Dev

EF Core 3:无法将CLR属性“ Number”添加到实体类型“ CHSIMTBase”,因为它是在CLR类型“合同”上声明的

来自分类Dev

实体类型没有定义键EF6

来自分类Dev

具有可选关系的EF Core 3.1 DeleteBehavior.SetNull引发约束异常

来自分类Dev

进行EF Core迁移(SmartEnum)时,“找不到适合实体类型的构造函数”

来自分类Dev

Ef Core 3实体类型XOrder不能映射到表,因为它是从Order派生的。只能将基本实体类型映射到表

来自分类Dev

带有AutoMapper的通用工作单元和存储库模式引发异常“相同类型的另一个实体已经具有相同的主键值”

来自分类Dev

具有预先创建的映射的AutoMapper子实体

来自分类Dev

具有预先创建的映射的AutoMapper子实体

来自分类Dev

具有不同属性类型的AutoMapper对象

来自分类Dev

AutoMapper-具有非常长的属性名称的拼合类型

来自分类Dev

具有继承的Automapper 5.2无法正常工作

来自分类Dev

具有相同标签的L1实体类型和L3实体类型

来自分类Dev

实体框架与相同实体类型但具有不同关系类型的多对多关系

来自分类Dev

当外键实体类型相同时,AutoMapper 忽略 MaxDepth

来自分类Dev

找不到具有MappingExeption实体类的portlet时发生Liferay异常

来自分类Dev

找不到具有MappingExeption实体类的portlet时发生Liferay异常

Related 相关文章

  1. 1

    EF Core 更新无法跟踪实体类型“广告”的实例

  2. 2

    EF Core:无法跟踪实体类型的实例,因为另一个具有相同键值的实例

  3. 3

    无法跟踪实体类型“ TestType”的实例,因为已经跟踪了具有相同键的该类型的另一个实例

  4. 4

    EF,Automapper异常,“附加类型...的实体失败,因为相同类型的另一个实体已经具有相同的主键值”

  5. 5

    无法跟踪实体类型“ x”的实例,因为已经跟踪了具有相同的{'a','b'}键值的另一个实例

  6. 6

    无法跟踪实体类型 <T> 的实例,因为已跟踪另一个具有相同 {'Id'} 键值的实例

  7. 7

    “如何修复“实体类型的实例”无法跟踪,因为另一个具有键值“{TypeId: 1}”的实例已被跟踪。

  8. 8

    ASP.NET Core - 无法跟踪实体类型的实例

  9. 9

    EF代码优先:具有多个多对一关系的实体类型

  10. 10

    具有TPH继承的实体类型到多个表的EF映射属性

  11. 11

    具有TPH继承的实体类型到多个表的EF映射属性

  12. 12

    EF代码优先:具有多个多对一关系的实体类型

  13. 13

    在EF 6中更新现有数据会引发异常-“ ...相同类型的实体已经具有相同的主键值。”

  14. 14

    EF Core 3:无法将CLR属性“ Number”添加到实体类型“ CHSIMTBase”,因为它是在CLR类型“合同”上声明的

  15. 15

    实体类型没有定义键EF6

  16. 16

    具有可选关系的EF Core 3.1 DeleteBehavior.SetNull引发约束异常

  17. 17

    进行EF Core迁移(SmartEnum)时,“找不到适合实体类型的构造函数”

  18. 18

    Ef Core 3实体类型XOrder不能映射到表,因为它是从Order派生的。只能将基本实体类型映射到表

  19. 19

    带有AutoMapper的通用工作单元和存储库模式引发异常“相同类型的另一个实体已经具有相同的主键值”

  20. 20

    具有预先创建的映射的AutoMapper子实体

  21. 21

    具有预先创建的映射的AutoMapper子实体

  22. 22

    具有不同属性类型的AutoMapper对象

  23. 23

    AutoMapper-具有非常长的属性名称的拼合类型

  24. 24

    具有继承的Automapper 5.2无法正常工作

  25. 25

    具有相同标签的L1实体类型和L3实体类型

  26. 26

    实体框架与相同实体类型但具有不同关系类型的多对多关系

  27. 27

    当外键实体类型相同时,AutoMapper 忽略 MaxDepth

  28. 28

    找不到具有MappingExeption实体类的portlet时发生Liferay异常

  29. 29

    找不到具有MappingExeption实体类的portlet时发生Liferay异常

热门标签

归档