使用 AutoMapper 映射两个模型
Mapping two models with AutoMapper
我有一个 Customer 模型,它与 Address 模型具有一对一的关系。我正在使用 AutoMapper 来映射这些值。我想使用我的 API 在数据库中创建一个新的客户,理想情况下会根据提供给客户模型的信息插入一个新的地址行。
这是 Entity framework 核心收到的 SQL 异常:
---> Microsoft.Data.SqlClient.SqlException (0x80131904): Cannot insert the value NULL into column 'AddressId', table 'dbo.Customers'; column does not allow nulls. INSERT fails.
注意 - BaseEntity 仅包括常见属性,如 ID、并发检查等
客户型号:
public class Customer : BaseEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string UpdatedBy { get; set; }
public DateTime? LastContact { get; set; }
#region Navigation Properties
public int? AddressId { get; set; }
public string UserId { get; set; }
public User User { get; set; }
public virtual Address Address { get; set; }
public virtual ICollection<Invoice> Invoices { get; set; }
#endregion
}
我的地址模型:
public class Address : BaseEntity
{
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
#region Navigation Properties
public virtual Customer Customer { get; set; }
#endregion
}
我正在为请求使用DTO class,如下:
public class CustomerCreateDto
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string UserId { get; set; }
}
AddressDto:
public class AddressDto : BaseEntity
{
[Required]
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
[Required]
public string City { get; set; }
public string State { get; set; }
[Required]
[DataType(DataType.PostalCode)]
public string PostalCode { get; set; }
}
CustomerDto
public class CustomerDto : BaseEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string UserId { get; set; }
public int AddressId { get; set; }
public string UpdatedBy { get; set; }
public DateTime? LastContact { get; set; }
public virtual UserDto User { get; set; }
public virtual AddressDto Address { get; set; }
public virtual ICollection<InvoiceDto> Invoices { get; set; }
}
这是 AutoMapper 配置
public class MappingConfiguration : Profile
{
public MappingConfiguration()
{
CreateMap<AddressDto, Address>().ReverseMap();
CreateMap<CustomerDto, Customer>().ForMember(dst => dst.UserId,
opt => opt.MapFrom(src => src.User.Id)).ForMember(dst =>
dst.Address,
opt => opt.MapFrom(src => src.Address)).ReverseMap();
CreateMap<CustomerCreateDto, Customer>().ReverseMap();
}
}
这里是控制器方法。我知道我可以通过像 customer.Address = address
这样的 addressDto
对象手动设置值来做到这一点,但我想看看是否有更好的方法
[HttpPost]
public async Task < IActionResult > Create([FromBody] CustomerCreateDto customerDto)
{
if (customerDto == null || !ModelState.IsValid) {
return BadRequest(ModelState);
}
var addressDto = new AddressDto {
AddressLine1 = customerDto.AddressLine1,
AddressLine2 = customerDto.AddressLine2,
City = customerDto.City,
State = customerDto.State,
PostalCode = customerDto.PostalCode,
CreatedDate = DateTime.Now,
};
var user = await _userManager.FindByIdAsync(customerDto.UserId);
var address = _mapper.Map<Address>(addressDto);
var customer = _mapper.Map<Customer>(customerDto);
customer.CreatedDate = DateTime.Now;
var result = await _customerRepository.CreateAsync(customer);
if (result) return Created("Created", new { customer });
// if we got this far it means the request failed
return new
StatusCodeResult(StatusCodes.Status500InternalServerError);
}
我正在寻找的功能是通过将 CustomerCreateDto 更改为:
public class CustomerCreateDto
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string UserId { get; set; }
public virtual AddressDto Address { get; set; }
}
映射配置:
public class MappingConfiguration : Profile
{
public MappingConfiguration()
{
CreateMap<AddressDto, Address>().ReverseMap();
CreateMap<CustomerDto, Customer>().ForMember(dst => dst.UserId,
opt => opt.MapFrom(src => src.User.Id));
CreateMap<CustomerCreateDto, Customer>().ForMember(dst => dst.Address,
opt => opt.MapFrom(src => src.Address)).ReverseMap().ReverseMap();
}
}
我的控制器:
[HttpPost]
public async Task<IActionResult> Create([FromBody] CustomerCreateDto customerDto)
{
if (customerDto == null || !ModelState.IsValid) {
return BadRequest(ModelState);
}
var customer = _mapper.Map<Customer>(customerDto);
customer.CreatedDate = DateTime.Now;
var result = await _customerRepository.CreateAsync(customer);
if (result) return Created("Created", new { customer });
return new StatusCodeResult(StatusCodes.Status500InternalServerError);
}
我有一个 Customer 模型,它与 Address 模型具有一对一的关系。我正在使用 AutoMapper 来映射这些值。我想使用我的 API 在数据库中创建一个新的客户,理想情况下会根据提供给客户模型的信息插入一个新的地址行。
这是 Entity framework 核心收到的 SQL 异常:
---> Microsoft.Data.SqlClient.SqlException (0x80131904): Cannot insert the value NULL into column 'AddressId', table 'dbo.Customers'; column does not allow nulls. INSERT fails.
注意 - BaseEntity 仅包括常见属性,如 ID、并发检查等
客户型号:
public class Customer : BaseEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string UpdatedBy { get; set; }
public DateTime? LastContact { get; set; }
#region Navigation Properties
public int? AddressId { get; set; }
public string UserId { get; set; }
public User User { get; set; }
public virtual Address Address { get; set; }
public virtual ICollection<Invoice> Invoices { get; set; }
#endregion
}
我的地址模型:
public class Address : BaseEntity
{
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
#region Navigation Properties
public virtual Customer Customer { get; set; }
#endregion
}
我正在为请求使用DTO class,如下:
public class CustomerCreateDto
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
public string City { get; set; }
public string State { get; set; }
public string PostalCode { get; set; }
public string UserId { get; set; }
}
AddressDto:
public class AddressDto : BaseEntity
{
[Required]
public string AddressLine1 { get; set; }
public string AddressLine2 { get; set; }
[Required]
public string City { get; set; }
public string State { get; set; }
[Required]
[DataType(DataType.PostalCode)]
public string PostalCode { get; set; }
}
CustomerDto
public class CustomerDto : BaseEntity
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string UserId { get; set; }
public int AddressId { get; set; }
public string UpdatedBy { get; set; }
public DateTime? LastContact { get; set; }
public virtual UserDto User { get; set; }
public virtual AddressDto Address { get; set; }
public virtual ICollection<InvoiceDto> Invoices { get; set; }
}
这是 AutoMapper 配置
public class MappingConfiguration : Profile
{
public MappingConfiguration()
{
CreateMap<AddressDto, Address>().ReverseMap();
CreateMap<CustomerDto, Customer>().ForMember(dst => dst.UserId,
opt => opt.MapFrom(src => src.User.Id)).ForMember(dst =>
dst.Address,
opt => opt.MapFrom(src => src.Address)).ReverseMap();
CreateMap<CustomerCreateDto, Customer>().ReverseMap();
}
}
这里是控制器方法。我知道我可以通过像 customer.Address = address
这样的 addressDto
对象手动设置值来做到这一点,但我想看看是否有更好的方法
[HttpPost]
public async Task < IActionResult > Create([FromBody] CustomerCreateDto customerDto)
{
if (customerDto == null || !ModelState.IsValid) {
return BadRequest(ModelState);
}
var addressDto = new AddressDto {
AddressLine1 = customerDto.AddressLine1,
AddressLine2 = customerDto.AddressLine2,
City = customerDto.City,
State = customerDto.State,
PostalCode = customerDto.PostalCode,
CreatedDate = DateTime.Now,
};
var user = await _userManager.FindByIdAsync(customerDto.UserId);
var address = _mapper.Map<Address>(addressDto);
var customer = _mapper.Map<Customer>(customerDto);
customer.CreatedDate = DateTime.Now;
var result = await _customerRepository.CreateAsync(customer);
if (result) return Created("Created", new { customer });
// if we got this far it means the request failed
return new
StatusCodeResult(StatusCodes.Status500InternalServerError);
}
我正在寻找的功能是通过将 CustomerCreateDto 更改为:
public class CustomerCreateDto
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string UserId { get; set; }
public virtual AddressDto Address { get; set; }
}
映射配置:
public class MappingConfiguration : Profile
{
public MappingConfiguration()
{
CreateMap<AddressDto, Address>().ReverseMap();
CreateMap<CustomerDto, Customer>().ForMember(dst => dst.UserId,
opt => opt.MapFrom(src => src.User.Id));
CreateMap<CustomerCreateDto, Customer>().ForMember(dst => dst.Address,
opt => opt.MapFrom(src => src.Address)).ReverseMap().ReverseMap();
}
}
我的控制器:
[HttpPost]
public async Task<IActionResult> Create([FromBody] CustomerCreateDto customerDto)
{
if (customerDto == null || !ModelState.IsValid) {
return BadRequest(ModelState);
}
var customer = _mapper.Map<Customer>(customerDto);
customer.CreatedDate = DateTime.Now;
var result = await _customerRepository.CreateAsync(customer);
if (result) return Created("Created", new { customer });
return new StatusCodeResult(StatusCodes.Status500InternalServerError);
}