这个问题在这里已有答案:
7870
2018-02-21 17:20
起源
答案:
我在这里找到了答案: 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);
}
这里的 微软页面 解释这种用法的具体细节。 (大约一半)
10
2018-03-05 17:53
我认为这种方法不再适用。除非将参数更改为ODataQueryOptions <PersonDto>,否则不会调用该方法。如果将参数更改为该参数,则会调用该方法,但odataQuery.ApplyTo()会抛出异常,表示该查询适用于PersonDto类型,而不是Person。 - sheamus
@sheamus,你需要申请到Dto类型。喜欢: odataQuery.ApplyTo(ConvertToDtos(uow.Person().GetAll())) - Eric Falsken
@EricFalsken不会导致所有人被拉入内存,所以ConvertToDtos可以对它们进行操作吗? - sheamus
更换 ConvertToDtos 同 Automapper.ConvertTo<PersonDto>() 要么 odataQuery.ApplyTo(db.Person().GetAll().To<PersonDto>()) 并且你会得到一个只会转换必要对象的LINQ查询,并且不会从数据库中获取所有内容,只要你使用双向对象绑定语法。 - Eric Falsken
@EricFalsken但如果在执行查询之前将其转换为DTO,您将如何进行关系?例如,我在尝试扩展时遇到此错误:在实体集“人员”上的实体类型“PersonDto”中找不到导航属性“地址”的NavigationLink工厂 - YesMan85
答案:
我在这里找到了答案: 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);
}
这里的 微软页面 解释这种用法的具体细节。 (大约一半)
10
2018-03-05 17:53
我认为这种方法不再适用。除非将参数更改为ODataQueryOptions <PersonDto>,否则不会调用该方法。如果将参数更改为该参数,则会调用该方法,但odataQuery.ApplyTo()会抛出异常,表示该查询适用于PersonDto类型,而不是Person。 - sheamus
@sheamus,你需要申请到Dto类型。喜欢: odataQuery.ApplyTo(ConvertToDtos(uow.Person().GetAll())) - Eric Falsken
@EricFalsken不会导致所有人被拉入内存,所以ConvertToDtos可以对它们进行操作吗? - sheamus
更换 ConvertToDtos 同 Automapper.ConvertTo<PersonDto>() 要么 odataQuery.ApplyTo(db.Person().GetAll().To<PersonDto>()) 并且你会得到一个只会转换必要对象的LINQ查询,并且不会从数据库中获取所有内容,只要你使用双向对象绑定语法。 - Eric Falsken
@EricFalsken但如果在执行查询之前将其转换为DTO,您将如何进行关系?例如,我在尝试扩展时遇到此错误:在实体集“人员”上的实体类型“PersonDto”中找不到导航属性“地址”的NavigationLink工厂 - YesMan85
我能够使用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");
有了这个,你可以使用像这样的网址
http://website/odata/Invoice?$filter=InvoiceID eq 1
我通过sql profiler确认过滤器正在传递给SQL。
5
2018-03-01 09:29
如果您使用的是Automapper,则可以在其中使用投影。例:
public class ProductsController : EntitySetController<Product, int>
{
private DbProductsContext _db = new DbProductsContext();
public override IQueryable<ProductDto> Get()
{
return _db.Products.Project().To<ProductDto>();
}
...
1
2018-02-21 17:34
它实际上与使用AutoMapper无关。这是EntityFramework LINQ提供程序(至少使用DbContext,有人说ObjectContext不起作用)支持这样一个事实,即你可以在投影上查询结果(选择),它会识别并将其转换为查询原始数据源。 - Rich
LINQ如何允许针对viewmodel的查询转换为原始数据源上的查询?我不明白。我假设如果我们必须使用typeconverter(自定义方法)来映射类,它肯定不会起作用? - Eric Falsken
我明白IQueryable会允许OData查询针对翻译的类执行,但我不知道如果不检索所有可能的话这是如何工作的 Products 并将它们转换为 ProductDto 过滤前的实例。如何将OData查询转换为正确的SQL? - Eric Falsken
Eric,在你的Get中的某个时刻,你必须提供从DTO / ViewModel到EntityFramework类的一些翻译,无论是通过直接映射,如我的例子,还是通过自动映射器或类似的东西。 OData库可以使用它来确定如何将过滤器传递给实体框架,以便将Select转换为适当的SQL。 - Gareth Suarez