Luk*_*ett 4 entity-framework odata
将我的EF模型暴露给API似乎总是错误的.我希望我的API将自定义实体模型返回给调用者,但在后面使用EF.
所以我可能有PersonRestEntity
一个CRUD操作的控制器和一个Person
后面的EF代码优先实体和映射值.
当我这样做时,我不能再~/people?$top=10
在URL中使用以下内容等
[EnableQuery]
public IQueryable<Person> Get(ODataQueryOptions<Person> query) { ... }
Run Code Online (Sandbox Code Playgroud)
因为那暴露了Person
哪些是私有数据库实现.
我怎么能吃蛋糕吃呢?
我找到了一个方法.诀窍不仅仅是IQueryable
从控制器返回,因为您需要首先实现查询.这并不意味着物化整套到RAM中,查询仍然在数据库中运行,但明确将查询和物化可以此后返回映射实体的结果.
定义此操作,指定DbSet实体类型:
public async Task<HttpResponseMessage> Get(ODataQueryOptions<Person> oDataQuery)
Run Code Online (Sandbox Code Playgroud)
然后手动应用查询,DbSet<Person>
以便:
var queryable = oDataQuery.ApplyTo(queryableDbSet);
Run Code Online (Sandbox Code Playgroud)
然后使用以下命令运行查询并将结果转换为您公开公开的实体集合:
var list = await queryable.ToListAsync(cancellationToken);
return list
.OfType<Person>()
.Select(p => MyEntityMapper.MapToRestEntity(p));
Run Code Online (Sandbox Code Playgroud)
然后您可以HttpResponseMessage
正常返回列表.
就是这样,虽然显然实体之间的属性名称不匹配或在任何一个类上都不存在,但是会出现一些问题,因此最好确保要包含在查询选项中的属性在两个实体.
另外,我猜你可以选择不支持过滤器,只允许$top
并$skip
自己强加默认订单.这可以像这样来实现,确保订购可查询第一,然后跳过,然后顶部.就像是:
IQueryable queryable = people
.GetQueryable(operationContext)
.OrderBy(r => r.Name);
if (oDataQuery.Skip != null)
queryable = oDataQuery.Skip.ApplyTo(queryable, new System.Web.OData.Query.ODataQuerySettings());
if (oDataQuery.Top != null)
queryable = oDataQuery.Top.ApplyTo(queryable, new System.Web.OData.Query.ODataQuerySettings());
var list = await queryable.ToListAsync(operationContext.CreateToken());
return list
.OfType<Person>()
.Select(i => this.BuildPersonEntity(i));
Run Code Online (Sandbox Code Playgroud)
更多信息:
如果单纯使用非泛型ODataQueryOptions
你
无法创建EDM模型,因为控制器上的'Get'操作'People'有一个返回类型'System.Net.Http.HttpResponseMessage',它不实现IEnumerable
并且在不同情况下会发生其他错误.
归档时间: |
|
查看次数: |
1599 次 |
最近记录: |