簡體   English   中英

Automapper DTO 到實體框架核心 model

[英]Automapper DTO to Entity Framework Core model

I'm building my first .NET Core 3.1 API, I have problem with properly map DTO to model, I'm sending JSON with userId of existing user:

{
   "userId": 0,
   "storageName": "string"
}

它拋出一個錯誤,看起來它正在嘗試從數據庫中為現有用戶創建新的而不是 map

后端_API_DEV | 失敗:Microsoft.EntityFrameworkCore.Database.Command[20102] Backend_API_DEV |
執行 DbCommand (43ms) 失敗 [Parameters=[@p0='?' (DbType = Int32), @p1='?' (大小 = 4000),@p2='?' (大小 = 4000),@p3='?' (大小 = 4000)],CommandType='Text',CommandTimeout='30']
后端_API_DEV | 設置無計數;
后端_API_DEV | 插入 [Users]([UserId]、[UserEmail]、[UserName]、[UserPassword])
后端_API_DEV | 值(@p0、@p1、@p2、@p3);
后端_API_DEV | 失敗:Microsoft.EntityFrameworkCore.Update[10000]
后端_API_DEV | 保存上下文類型“Backend.Data.BackendContext”的更改時,數據庫中發生異常。

我使用的其他 DTO/模型沒有外鍵,它們 map 正確,所以我可以在數據庫中創建和更新對象。 我認為我的問題是 map 配置,但我不知道如何正確地做到這一點。

namespace Backend.Profiles
{
    public class StorageProfile : Profile
    {
        public StorageProfile()
        {
            CreateMap<StorageCreateDto, Storage>()
                .ForPath(dest => dest.IdUser.UserId, opt => opt.MapFrom(src => src.UserId));
        }
    }
}

Model:

namespace Backend.Models
{
    public class Storage
    {
        [Key]
        public int StorageId { get; set; }
        [ForeignKey("UserId")]
        public virtual User IdUser { get; set; }
        [Required]
        public string StorageName { get; set; }
    }
}

Controller:

namespace Backend.Controllers
{
    [ApiController]
    [Route("api/[controller]")]
    public class StorageController : ControllerBase
    {
        private readonly IBackendRepo _repository;
        private readonly IMapper _mapper;

        public StorageController(IBackendRepo repository, IMapper mapper)
        {
            _repository = repository;
            _mapper = mapper;
        }

        [HttpPost]
        public ActionResult<StorageReadDto> CreateStorage(StorageCreateDto storageCreateDto)
        {
            var model = _mapper.Map<Storage>(storageCreateDto);
            _repository.CreateStorage(model);
            _repository.SaveChanges();

            var readDto = _mapper.Map<StorageReadDto>(model);

            return CreatedAtRoute(nameof(GetStorageById), new { Id = readDto.StorageId }, readDto);
        }
    }
}

將更改保存到數據庫的存儲庫:

    public bool SaveChanges()
    {
        return (_context.SaveChanges() >= 0);
    }

    public void CreateStorage(Storage storage)
    {
        if (storage == null)
        {
            throw new ArgumentNullException(nameof(storage));
        }

        _context.Storages.Add(storage);
    }

如果storage.User是非空引用,則將storage添加到上下文:

_context.Storages.Add(storage);

還添加了引用的User 這就是DbSet<T>.Add的工作原理——它添加了整個 object 圖。

有兩種選擇:

  1. 重新設計Storage以添加外鍵屬性UserId 將 DTO 映射到存儲時,初始化外鍵屬性而不是引用屬性。 也就是初始化用戶id而不是user。 (另外,最好重命名IdUser屬性,這樣的名稱會混淆,因為這不是標識符,而是引用)。

  2. 添加storage后,將引用用戶的 state 顯式設置為Unchanged

_context.Entry(storage.IdUser).State = EntityState.Unchanged;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM