Using EF and WebAPI, how can I return a ViewModel AND support IQueryable/OData? [duplicate]

给你一囗甜甜゛ 提交于 2019-12-23 07:38:57

问题


I've got an ASP.NET WebAPI project. I've recently created EntityFramework entities for all my data tables. But I don't want to expose my data layer & schema to my users. How can I map my entities to a ViewModel (automapper?) and provide IQueryable return type so that my API supports OData?

OData supports query composition and SQL-like parameters. I guess I'd need to provide some kind of 2-way translation for the query-composition part? Does that mean a custom LINQ provider? I hope it's easier than that.

Or should I give up on IQueryable/OData?


回答1:


I found the answer here: Web API Queryable - how to apply AutoMapper?

Instead of using [Queryable] you can use a parameter of type ODataQueryOptions<T> to apply OData operations against any type or LINQ query you wish. Here's a great example that doesn't even need to use 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);
}

Here's the Microsoft page explaining the specifics of this usage. (about half way down)




回答2:


I was able to successfully test this using a ViewModel class.

public class InvoiceViewModel
{
    public int InvoiceID { get; set; }
    public string InvoiceNumber { get; set; }
}

in the Get, select from your entity into your viewmodel:

public override IQueryable<InvoiceViewModel> Get()
    {
        var ctx = new CreditPointEntities();
        return ctx.Invoices.Select(i => new InvoiceViewModel
            {
                InvoiceID = i.InvoiceID,
                InvoiceNumber = i.InvoiceNumber
            }).AsQueryable();
    }

Make sure you use the viewmodel in your modelbuilder line in webapiconfig.cs

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

with this, you can use a url like

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

I confirmed through sql profiler that the filter was being passed through to SQL.




回答3:


if you are using Automapper, you could use projections in it. Example:

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

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


来源:https://stackoverflow.com/questions/15008450/using-ef-and-webapi-how-can-i-return-a-viewmodel-and-support-iqueryable-odata

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!