如何解决如何在.NET Core 3.1中结合OData 4和Automapper
我尝试在.NET Core 3.1中结合使用Automapper和OData,但现在已经有一段时间了。我的OData控制器通过这种方式像超级按钮一样工作:
[ODataRoute]
[EnableQuery]
public IQueryable<Unit> Get()
{
return _context.Units;
}
_context
是我的EF DbContext
。
但是,我需要公开UnitDto
而不是Unit
。
到目前为止,我尝试过的是:
[ODataRoute]
[EnableQuery]
public IQueryable<UnitDto> Get()
{
var units = _context.Units;
return units.ProjectTo<UnitDto>(_mapper.ConfigurationProvider);
}
但这导致空引用异常:
System.NullReferenceException:对象引用未设置为对象的实例。
在lambda_method处(Closure,QueryContext,DbDataReader,ResultContext,Int32 [],ResultCoordinator)
在Microsoft.EntityFrameworkCore.Query.Internal.QueryingEnumerable1.AsyncEnumerator.MoveNextAsync() at Microsoft.AspNetCore.Mvc.Infrastructure.AsyncEnumerableReader.ReadInternal[T](Object value) at Microsoft.AspNetCore.Mvc.Infrastructure.AsyncEnumerableReader.ReadInternal[T](Object value) at Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor.ExecuteAsyncEnumerable(ActionContext context,ObjectResult result,Object asyncEnumerable,Func
2阅读器处)
等
使用GetQueryAsync
中的Automapper.Aspnetcore.Odata.EFCore
会导致相同的异常:
[HttpGet]
public async Task<IActionResult> GetAll(ODataQueryOptions<UnitDto> options)
{
return Ok(await _context.Units.GetQueryAsync(_mapper,options));
}
关于如何实现这一目标的任何想法?这是要走的路,我做错什么了吗?还是应该朝另一个方向走?
解决方法
最后,我找到了解决方法。因此,假设有更多的人遇到这个问题,这就是我要做的事情。
第一件事是对数据库对象执行查询。然后获取它们的结果(使用JSON(反)序列化,不知道一种更好的方法)并将它们映射到DTO对象。
[ODataRoute]
[EnableCustomQuery]
public IEnumerable<UnitDto> Get(ODataQueryOptions<Unit> opts)
{
var queryResult = opts.ApplyTo(_context.Units);
var units = _mapper.Map<List<Unit>>(JsonConvert.DeserializeObject<List<UnitOData>>(JsonConvert.SerializeObject(queryResult)));
return _mapper.Map<List<UnitDto>>(units);
}
我想使用所有查询选项,包括$expand
,$filter
,$skip
,$top
和$count
。但是查询应该在数据库对象上,而在DTO对象上查询。因此,我将其链接到我的EDM模型中,如下所示:
var unitsConfig = builder.EntitySet<Unit>("UnitsWithoutDto");
unitsConfig.EntityType.Property(p => p.InternalReference).Name = "ExternalReference";
反序列化的结果现在将是具有特定属性的数据库对象,当该特定对象被过滤时,该属性被更改。因此,我创建了一个新的UnitOData
。
public class UnitOData : Unit
{
public string DisplayName { get; set; }
}
根据特定属性是否存在将其映射到原始对象。
CreateMap<UnitOData,Unit>()
.ForMember(a => a.InternalReference,opt => opt.MapFrom(src => src.ExternalReference ?? src.InternalReference));
然后一切正常,请期待分页。因此,创建了一个自定义过滤器,该过滤器将忽略$skip
和$top
查询选项。
public class EnableCustomQueryAttribute : EnableQueryAttribute
{
public override IQueryable ApplyQuery(IQueryable queryable,ODataQueryOptions queryOptions)
{
var ignoreQueryOptions = AllowedQueryOptions.Skip | AllowedQueryOptions.Top;
return queryOptions.ApplyTo(queryable,ignoreQueryOptions);
}
}
如果有真正的解决方案,请分享。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。