【问题标题】:Ef core 3.0 gives error when inserting record 'The property 'Id' on entity type 'ChannelTypeT' could not be found'Ef core 3.0 在插入记录'找不到实体类型'ChannelTypeT'上的属性'Id'时出错'
【发布时间】:2019-12-12 12:51:18
【问题描述】:

我有带有自动映射器的 .net core 3.0 api。

我的映射遇到了一个问题。下面我列出了我的实体。

[Table(name: "ChannelType")]
public class ChannelType : FullAuditedEntity<string>
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    [Required]
    [StringLength(06)]
    public override string Id { get; set; }

    public string Text { get; set; }

    public virtual ChannelTypeT ChannelTypeT { get; set; }
}

ChannelTypeT 实体会是这样的。

[Table(name: "ChannelTypeT")]
public class ChannelTypeT
{
    [StringLength(02)]
    public string Lang { get; set; }
    public string Text { get; set; }

    #region Primary Key derived from Foreign key for Config tabels        
    [Required]
    [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
    [ForeignKey(name: "ChannelTypeId")]
    public string ChannelTypeId { get; set; }
    public virtual ChannelType ChannelType { get; set; }
    #endregion
}

现在,这意味着当我插入一个 ChannelType 时,代码也应该在 ChannelTypeT 中插入一条新记录,其 Id 与 ChannelTypeId 相同。这是快照。

这是我的 Dto 类。

public class ChannelTypeDtoIncluding
{
    public string Id { get; set; }
    public string Text { get; set; }

    public virtual ChannelTypeTDto ChannelTypeT { get; set; }
}

public class ChannelTypeTDto
{
    public string ChannelTypeId { get; set; }
    public string Lang { get; set; }
    public string Text { get; set; }
}

我的自动映射器映射。

CreateMap<ChannelTypeT, ChannelTypeTDto>().ReverseMap();
        CreateMap<ChannelType, ChannelTypeDtoIncluding>()
            .ForMember(d => d.Id, opt => opt.MapFrom(s => s.ChannelTypeT.ChannelTypeId))
            .ForMember(d => d.Id, opt => opt.MapFrom(s => s.ChannelTypeT.Id))
            .ReverseMap();

最后这是我的 post 方法。

 [HttpPost("InsertIncluding")]
    public IActionResult PostIncluding([FromBody]ChannelTypeDtoIncluding model)
    {
        if (string.IsNullOrEmpty(model.Id))
            return new NotFoundResult();

        if (!ModelState.IsValid)
            return BadRequest(ModelState);

        Response<ChannelType> itemToReturn = _service.Insert(_mapper.Map<ChannelTypeDtoIncluding, ChannelType>(source: model));
        if (itemToReturn.IsSuccess == true)
            return new OkObjectResult(_mapper.Map<ChannelType, ChannelTypeDtoIncluding>(source: itemToReturn.Data));
        else
            return new ObjectResult(itemToReturn.ErrorMessage) { StatusCode = 500 };
    }

但是在这种方法中,当我尝试映射我的模型时,它给了我错误。以下是错误描述。

找不到实体类型“ChannelTypeT”的属性“Id”。确保该属性存在并且已包含在模型中。

我的映射器会将 ChannelType -> Id 更新为 ChannelTypeT -> ChannelTypeId。 我认为问题出在映射器配置上,但不确定我在哪里做错了。

对此的任何想法都会有很大帮助。

【问题讨论】:

  • 请在您使用自动映射器映射实体的位置添加代码
  • 我也用过 Dto。所以它会给这里的读者带来更多的困惑。所以我选择不添加它们。
  • 抱歉,我不明白您想将哪 2 个实体映射到需要将 ChannelType.Id 映射到 ChannelTypeT.ChannelTypeId 的位置。你在mapper.Map&lt;ChannelType, ChannelTypeT&gt;()吗?
  • 是的。我需要的结果是ChannelType.IdChannelTypeT.ChannelTypeId 的映射。正如你所说,我也在为此做一个映射。

标签: c# asp.net-core automapper ef-core-3.0


【解决方案1】:

创建ChannelTypeChannelTypeT 的映射并使用ForMember 指定所需的连接

CreateMap<ChannelType, ChannelTypeT>()
    .ForMember(c => c.ChannelTypeId, m => m.MapFrom(ct => ct.Id));

【讨论】:

  • 我想我必须将 Dto 添加到我的问题中。尽管您的答案似乎正确,但没有按预期工作。
  • 你能快速检查一下吗,我又更新了我的问题。
【解决方案2】:

这是一个工作演示,你可以参考

  1. 对于ChannelTypeT模型中的ForeignKey ChannelTypeId,你应该如下修改,参考ForeignKey Attribute

    [Table(name: "ChannelTypeT")]
    public class ChannelTypeT
    {
        [StringLength(02)]
        public string Lang { get; set; }
        public string Text { get; set; }
    
        #region Primary Key derived from Foreign key for Config tabels        
        [Required]
        [Key, DatabaseGenerated(DatabaseGeneratedOption.None)]
        [ForeignKey(name: "ChannelType")]
        public string ChannelTypeId { get; set; }
        public virtual ChannelType ChannelType { get; set; }
        #endregion
    }
    
  2. 映射文件

    public class MapperProfile: Profile
    {
       public MapperProfile()
      {
        CreateMap<ChannelTypeT, ChannelTypeTDto>().ReverseMap();
        CreateMap<ChannelType, ChannelTypeDtoIncluding>()
            .ForMember(d => d.Text, opt => opt.MapFrom(s => s.ChannelTypeT.Text))
            .ReverseMap();
      }
    }
    
  3. 发布方法

    [HttpPost]
    [Route("/InsertIncluding")]
    public IActionResult PostIncluding([FromBody]ChannelTypeDtoIncluding model)
    {
        if (string.IsNullOrEmpty(model.Id))
            return new NotFoundResult();
    
        if (!ModelState.IsValid)
            return BadRequest(ModelState);
    
        ChannelType data = _mapper.Map<ChannelTypeDtoIncluding, ChannelType>(source: model);
        _context.ChannelType.Add(data);
        _context.SaveChanges();
        return new OkObjectResult(_mapper.Map<ChannelType, ChannelTypeDtoIncluding>(source: data));
    }
    

4.结果:

【讨论】:

  • 感谢您的解释,我的映射开始正常工作。我仍然收到这个 ID 错误。 .net core 似乎有问题。
  • 如果我在 ChannelTypeT 中添加一个属性 Id 作为主键和 fk ChannelTypeId,它可以正常工作。但是如果尝试将 ChannelTypeId 保持为 pk 和 fk,则会出错。
  • 你的_service.Insert()FullAuditedEntity&lt;string&gt; 是什么?
  • _service.Insert() 具有存储库模式的代码。那里没什么好看的。就像您在答案中所做的那样,它很简单。 FullAuditedEntity 是基类,具有创建日期、编辑日期、删除标志等属性。它还具有主键,因此当您传递string 时,id 的数据类型将为字符串。
  • 这是我的demo,你可以检查一下区别。如果您仍然有问题,您可以分享一个可以重现问题的完整演示吗?
猜你喜欢
  • 1970-01-01
  • 2021-11-06
  • 1970-01-01
  • 2020-02-28
  • 2021-02-16
  • 2019-11-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多