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();
你有一个解决办法吗?希望您了解我的问题,否则请问我。
国王的问候
这里有一些误解
切记DTO是一个愚蠢的类,从某种意义上说,它只是充当信息以强类型传播的容器而已。通常,当前端向您发送一些数据并且后端捕获到控制器参数(我知道这并不完全正确,只是试图在此处提出要点)时,或者在将DTO返回到前端时,您通常会处理DTO。终止于任何需要的理由。那么一般的方法将是:
前端发送了DTO
后端控制器捕获
后端服务将DTO映射到感兴趣的某些域模型(自动映射器)
后端服务执行业务规则的逻辑步骤,例如将记录保存在数据库中或更新一些我不知道您为它命名的内容
后端服务将响应(如果有)映射到DTO(自动映射器)
后端控制器将数据直接发送回前端,以执行所需的任何操作
现在,关于您的错误,这是实体框架入门者的常见错误。让我说明发生了什么:
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;
关于该主题的最后几句话:
var user = Mapper.Map<User>(newUserDto); //hey mapper, be a pal and transform this newUserDto into a User object.
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句