ASP.NET OData - 使用带有数据传输对象的Delta <t>实现PATCH </t>

时间:2013-11-14 13:04:29

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

在我的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)

1 个答案:

答案 0 :(得分:4)

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

为了繁荣,下面是使用AutoMapper将数据库实体映射到DTO的代码,然后将修补程序应用于DTO对象,然后使用AutoMapper在保存之前映射回数据库实体: / p>

[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;禁用延迟加载。