2013-09-05 23 views
1

什么是在ASP.NET Web Api中服务OData可查询GET请求的正确方法?这可能听起来像一个“什么更好”的问题,但它应该是一个“什么是工作”的问题。ASP.NET Web Api:正确的方式来服务OData可查询的GET请求

一些假设:

  • 要启用的OData-查询,你必须把Queryable属性返回IQueryable<Model>的操作方法。因此,你必须公开领域模型?
  • 域模型使用实体框架5并具有导航属性。 XML和Json序列化程序不喜欢EF代理,因此您必须为OData查询禁用它们。
  • 序列化器获取导航属性并将其提供给用户。

因此,如果我有一个Category类型的父类和子类的导航属性,序列化器抱怨我有循环引用,我不能摆脱这个错误。

我读过,我应该使用DTO,但如何?我如何向用户提供IQueryable<DTOModel>,以便为数据库创建适当的SQL?记住,我想用$filter之类的。

我只是想给用户一个没有序列化导航属性的模型对象可过滤列表....但是如何?

回答

3

您不必公开IQueryable<> - 您可以创建一个方法来接受ODataQueryOptions的实例并自行处理它。这里有一个代码示例,可以完成你所需要的大部分功能。对您来说,制定出最适合您的解决方案应该已经足够了。这个方法也允许你保留你的EF代理类。

using System.Web.Http.OData; 
using System.Web.Http.OData.Builder; 
using System.Web.Http.OData.Query; 
[ActionName("Dto")] 
public IList<DtoModel> GetDto(ODataQueryOptions<DtoModel> queryOptions) 
{ 
    var data2 = DatabaseData(); 

    //Create a set of ODataQueryOptions for the internal class 
    ODataModelBuilder modelBuilder = new ODataConventionModelBuilder(); 
    modelBuilder.EntitySet<Model>("Model"); 
    var queryContext = new ODataQueryContext(
     modelBuilder.GetEdmModel(), typeof(Model)); 
    var newQueryOptions = new ODataQueryOptions<Model>(queryContext, Request); 

    var t = new ODataValidationSettings() { MaxTop = 25 }; 
    var s = new ODataQuerySettings() { PageSize = 25 }; 
    newQueryOptions.Validate(t); 
    IEnumerable<Model> results = 
     (IEnumerable<Model>)newQueryOptions.ApplyTo(data2, s); 

    int skip = newQueryOptions.Skip == null ? 0 : newQueryOptions.Skip.Value; 
    int take = newQueryOptions.Top == null ? 25 : newQueryOptions.Top.Value; 

    IList<Model> internalResults = results.Skip(skip).Take(take).ToList(); 

    // map from Model to Dto here using AutoMapper 
    AutoMapper.Mapper.CreateMap<Model, DtoModel>(); 
    IList<DtoModel> webResults = 
     AutoMapper.Mapper.Map<IList<Model>, IList<DtoModel>>(internalResults); 

    return webResults; 
} 

在这个例子中使用的数据是一个简单的Queryable组数据:

private IQueryable<Model> DatabaseData() 
{ 
    return (
     new Model[] { 
     new Model() { id = 1, name = "one", type = "a" }, 
     new Model() { id = 2, name = "two", type = "b" }, 
     new Model() { id = 3, name = "three", type = "c" }, 
     new Model() { id = 4, name = "four", type = "d" }, 
     new Model() { id = 5, name = "five", type = "e" }, 
     new Model() { id = 6, name = "six", type = "f" }, 
     new Model() { id = 7, name = "seven", type = "g" }, 
     new Model() { id = 8, name = "eight", type = "h" }, 
     new Model() { id = 9, name = "nine", type = "i" } 
    }) 
    .AsQueryable(); 
} 

这些测试类:

public class Poco 
{ 
    public int id { get; set; } 
    public string name { get; set; } 
    public string type { get; set; } 
} 
public class DtoModel 
{ 
    public int id { get; set; } 
    public string name { get; set; } 
    public string type { get; set; } 
} 
public class Model 
{ 
    public int id { get; set; } 
    public string name { get; set; } 
    public string type { get; set; } 
    public virtual ICollection<Poco> Pocos { get; set; } 
} 
+1

我怎样才能让这个与扩大工作? –

相关问题