【问题标题】:ASP.NET OData - Implementing PATCH with Delta<T> with Data Transfer ObjectsASP.NET OData - 使用带有数据传输对象的 Delta<T> 实现 PATCH
【发布时间】:2013-11-27 12:08:45
【问题描述】:

在我的 OData 控制器中,我将我的 EF 实体转换为 DTO,因为该实体包含许多 UI 不使用的字段。

此问答 (ASP.NET WebApi OData support for DTOs) 展示了如何将 OData URI 中的查询选项应用于 EF 查询并返回 DTO。这太好了,这意味着我得到了查询数据库的好处以及序列化较小实体的好处。

但是,当我需要更新时,如何将带有修补字段的 Delta 应用到我的实体?

实体中的字段名称与 DTO 不匹配。

我可以使用 Delta 中更改的字段集合,但我会映射所有字段名称并使用反射来更新实体中的所有属性。

有没有更好的方法?

我是否应该使用我的实体而不是 DTO 并使用 odata $select 参数来减少线路上数据的大小。

我是否应该只恢复到 WebAPI 并拥有仅采用所需参数的单独更新函数,例如 UpdateStartDate(int id, DateTime newStartDate)

【问题讨论】:

  • 您是否使用自动映射器来定义映射?
  • 是的,我正在使用 AutoMapper 进行映射。

标签: entity-framework asp.net-web-api odata


【解决方案1】:

我刚刚遇到了同样的问题,发现以下链接很有帮助:http://qimata.com/?p=1381

为了繁荣,这里是使用 AutoMapper 将数据库实体映射到 DTO 的代码,然后将 Patching 应用于 DTO 对象,然后在保存之前使用 AutoMapper 映射回数据库实体:

[AcceptVerbs("PATCH", "MERGE")]
public virtual async Task<IHttpActionResult> Patch([FromODataUri] int key, Delta<DtoEntity> delta, CancellationToken cancellationToken)
{
    Validate(delta.GetEntity());

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

    var entity = await _genericRepository.FindAsync(cancellationToken, key);
    var dto = Mapper.Map<DtoEntity>(entity);
    delta.Patch(dto);
    Mapper.Map(dto, entity);
    await _context.SaveChangesAsync(cancellationToken);
    return Updated(dto);
}

另一件值得一提的事情是,在将 AutoMapper 与 EntityFramework 一起使用时,请注意导航属性的自动扩展。 您可以使用ExplicitExpansion 方法禁用扩展:

Mapper.CreateMap<DbEntity, DtoEntity>()
            .ForMember(dest => dest.Example, opt => opt.ExplicitExpansion());

我还必须在我的 DbContext 构造函数中使用 Configuration.LazyLoadingEnabled = false; 禁用延迟加载。

【讨论】:

  • 这最终不会更新模型中的所有属性,而不仅仅是那些改变的属性吗?您生成的 SQL 是否仅包含 PATCH 请求中传递的属性?我的理解是,将dto 映射到entity 最终会设置dto 对象的所有属性,这不是我们想要的PATCH。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-25
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多