使用EF和WebAPI,如何返回ViewModel并支持IQueryable / OData?

时间:2013-02-21 17:20:46

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

我有一个ASP.NET WebAPI项目。我最近为我的所有数据表创建了EntityFramework实体。但我不想暴露我的数据层和架构给我的用户。如何将我的实体映射到ViewModel(automapper?)提供IQueryable返回类型,以便我的API支持OData?

OData支持查询组合和类似SQL的参数。我想我需要为查询组合部分提供某种双向翻译?这是否意味着自定义LINQ提供程序?我希望它比那更容易。

或者我应该放弃IQueryable / OData?

3 个答案:

答案 0 :(得分:10)

我在这里找到答案:Web API Queryable - how to apply AutoMapper?

您可以使用[Queryable]类型的参数来对任何类型或LINQ查询应用OData操作,而不是使用ODataQueryOptions<T>。这是一个很好的例子,甚至不需要使用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);
}

这里是the Microsoft page解释这种用法的具体细节。 (大约一半)

答案 1 :(得分:6)

我能够使用ViewModel类成功测试它。

public class InvoiceViewModel
{
    public int InvoiceID { get; set; }
    public string InvoiceNumber { get; set; }
}
在获取中

,从您的实体中选择您的视图模型:

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行中使用viewmodel

modelBuilder.EntitySet<InvoiceViewModel>("Invoice");

有了这个,你可以使用像

这样的网址

http://website/odata/Invoice?$filter=InvoiceID eq 1

我通过sql profiler确认过滤器正在传递给SQL。

答案 2 :(得分:1)

如果您使用的是Automapper,则可以在其中使用投影。例如:

    public class ProductsController : EntitySetController<Product, int>
    {
         private DbProductsContext _db = new DbProductsContext();

         public override IQueryable<ProductDto> Get()
         {
            return _db.Products.Project().To<ProductDto>();
         }
    ...