Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Entity framework 使用EF和WebAPI,如何返回ViewModel并支持IQueryable/OData?_Entity Framework_Asp.net Web Api_Odata_Iqueryable - Fatal编程技术网

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

Entity framework 使用EF和WebAPI,如何返回ViewModel并支持IQueryable/OData?,entity-framework,asp.net-web-api,odata,iqueryable,Entity Framework,Asp.net Web Api,Odata,Iqueryable,我有一个ASP.NETWebAPI项目。我最近为所有数据表创建了EntityFramework实体。但我不想向我的用户公开我的数据层和模式。如何将实体映射到ViewModel自动映射器?并提供IQueryable返回类型,以便我的API支持OData OData支持查询组合和类似SQL的参数。我想我需要为查询组合部分提供某种双向翻译?这是否意味着自定义LINQ提供程序?我希望这比那容易 或者我应该放弃IQueryable/OData吗?如果您使用的是Automapper,您可以在其中使用投影。例

我有一个ASP.NETWebAPI项目。我最近为所有数据表创建了EntityFramework实体。但我不想向我的用户公开我的数据层和模式。如何将实体映射到ViewModel自动映射器?并提供IQueryable返回类型,以便我的API支持OData

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


或者我应该放弃IQueryable/OData吗?

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

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

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

我能够使用ViewModel类成功地测试这一点

public class InvoiceViewModel
{
    public int InvoiceID { get; set; }
    public string InvoiceNumber { get; set; }
}
在Get中,选择从实体到viewmodel:

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");
有了这个,您可以使用如下url

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

我通过sql探查器确认过滤器正在传递给sql

我在这里找到了答案:

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

下面解释一下这种用法的细节。大约在一半的时候

它实际上与使用AutoMapper无关。这是EntityFramework LINQ提供程序至少与DbContext,有人说ObjectContext不支持这样一个事实,即您可以在投影选择上查询结果,它将识别并将其转换为对原始数据源的查询。LINQ如何允许对viewmodel的查询转换为对原始数据源的查询?我不明白。我假设如果我们必须使用typeconverter自定义方法来映射类,那么它肯定不起作用?我知道IQueryable将允许对已翻译的类执行OData查询,但如果不检索所有可能的产品并在过滤之前将其转换为ProductDto实例,我看不出这如何起作用。如何将OData查询转换为正确的SQL?Eric,在get的某个时候,您必须提供从DTO/ViewModel到EntityFramework类的一些转换,无论是通过直接映射(如我的示例中所示),还是通过自动映射器或类似的方式。OData库可以使用它来确定如何将过滤器传递到实体框架,以便将您的选择转换为正确的SQL。我认为这种方法不再有效。除非将参数更改为ODataQueryOptions,否则不会调用该方法。如果将参数更改为该值,则会调用该方法,但odataQuery.ApplyTo会抛出一个异常,表示该查询应用于PersonDto类型,而不是Person。@sheamus,您将需要应用于Dto类型。比如:odataQuery.applytoconverttosoow.Person。GetAll@EricFalsken这不会导致所有人员都被拉入内存,以便ConvertToTos可以对其进行操作吗?将ConvertToToTos替换为Automapper.ConvertTo或odataQuery.ApplyTodb.Person.GetAll.to,您将返回一个LINQ查询,该查询只会转换必要的对象,而不会只要使用双向对象绑定语法,就可以从数据库中返回所有内容。@EricFalsken但如果在执行查询之前将其转换为DTO,您将如何处理关系?例如,我在尝试展开时遇到此错误:在实体集“Persons”上,从实体类型“PersonDto”中找不到导航属性“Address”的NavigationLink工厂