我有一个 ASP.NET WebAPI 项目。我最近为我的所有数据表创建了 EntityFramework 实体。但我不想将我的数据层和架构暴露给我的用户。如何将我的实体映射到 ViewModel(自动映射器?)并提供 IQueryable 返回类型,以便我的 API 支持 OData?
OData 支持查询组合和类似 SQL 的参数。我想我需要为查询组合部分提供某种双向翻译?这是否意味着自定义 LINQ 提供程序?我希望它比那更容易。
还是我应该放弃 IQueryable/OData?
我有一个 ASP.NET WebAPI 项目。我最近为我的所有数据表创建了 EntityFramework 实体。但我不想将我的数据层和架构暴露给我的用户。如何将我的实体映射到 ViewModel(自动映射器?)并提供 IQueryable 返回类型,以便我的 API 支持 OData?
OData 支持查询组合和类似 SQL 的参数。我想我需要为查询组合部分提供某种双向翻译?这是否意味着自定义 LINQ 提供程序?我希望它比那更容易。
还是我应该放弃 IQueryable/OData?
我在这里找到了答案:Web API Queryable - 如何应用 AutoMapper?
[Queryable]
您可以使用类型参数代替使用,ODataQueryOptions<T>
以针对您希望的任何类型或 LINQ 查询应用 OData 操作。这是一个很好的例子,它甚至不需要使用 AutoMapper:
public virtual IQueryable<PersonDto> Get(ODataQueryOptions<Person> odataQuery){
odataQuery.Validate(new ODataValidationSettings(){
AllowedFunctions = AllowedFunctions.AllMathFunctions
});
var people = odataQuery.ApplyTo(uow.Person().GetAll());
return ConvertToDtos(people);
}
这是解释此用法细节的 Microsoft 页面。(大约下降一半)
我能够使用 ViewModel 类成功地对此进行测试。
public class InvoiceViewModel
{
public int InvoiceID { get; set; }
public string InvoiceNumber { get; set; }
}
在 Get 中,从您的实体中选择到您的视图模型中:
public override IQueryable<InvoiceViewModel> Get()
{
var ctx = new CreditPointEntities();
return ctx.Invoices.Select(i => new InvoiceViewModel
{
InvoiceID = i.InvoiceID,
InvoiceNumber = i.InvoiceNumber
}).AsQueryable();
}
确保在 webapiconfig.cs 的模型构建器行中使用视图模型
modelBuilder.EntitySet<InvoiceViewModel>("Invoice");
有了这个,你可以使用一个像
http://website/odata/Invoice?$filter=InvoiceID eq 1
我通过 sql profiler 确认过滤器正在传递给 SQL。
如果您使用的是 Automapper,则可以在其中使用投影。例子:
public class ProductsController : EntitySetController<Product, int>
{
private DbProductsContext _db = new DbProductsContext();
public override IQueryable<ProductDto> Get()
{
return _db.Products.Project().To<ProductDto>();
}
...