如何将ODataQueryOptions <t>应用于IQueryable <x>

时间:2016-06-10 08:55:59

标签: c# entity-framework odata

我希望将ODataQueryOptions应用于DbSet。让我快速介绍一下我的应用。我需要创建一个从两个表T1和amp;中读取数据的应用程序。 T2。除了每个表之外,两个表都具有几乎相同的模式。我的实体类设计有点像下面所示:(为了简洁起见,我保持了架构和术语的简单化)

class Base
{
    [Key]
    public int ID;
    public string Name;
    public string Gender;
    public string Comment;
}

[Table("T1")]
class TableOneEntity : Base
{

}

[Table("T2")]
class TableTwoEntity : Base
{
    // extra columns from T2
    public string Country;
    public string City;
}

DbContext类:

class ApplicationDbContext : DbContext
{
    public DbSet<TableOneEntity> TableOneDbSet;
    public DbSet<TableTwoEntity> TableTwoDbSet;
}

我的OData GET API如下所示:

public PageResult<TableTwoEntity> GetTableResult(ODataQueryOptions<TableOneEntity> options)
{
    var result1 = options.ApplyTo(appDbCtx.TableOneDbSet) as IQueryable<TableOneEntity>;

    var result2 = options.ApplyTo(appDbCtx.TableTwoDbSet) as IQueryable<TableTwoEntity>;

    return new PageResult<TableTwoEntity>(output, odataProperties.NextLink, odataProperties.TotalCount);
}

当调用GET API时,我得到以下异常:

  

无法将'TableOneEntity'的ODataQueryOptions应用于IQueryable   'TableTwoEntity'。

如何将相同的'选项'应用于TableTwoDbSet?

2 个答案:

答案 0 :(得分:0)

我通常会包含对OData WebApi nuget package的引用。

然后,对于控制器,添加Queryable属性并将您的集合作为Queryable返回,您就完成了,只需在调用中添加OData查询选项。

很酷的部分是如果您使用EF,那么所有过滤器和约束都会一直传递到数据库查询。

public class MyController : ApiController
{
    // Add the queryable attribute
    [Queryable]
    IQueryable<stuff> Get() {
        ...
        ...
        return myStuff.AsQueryable();
}

然后您可以这样使用它:

http://www.blabla.bla/api/v1/stuff?$top=10&$skip=20&$orderby=name

---为你提供10行的第20页,按名称排序。

请参阅OData conventions以获得一个很好的参考:

答案 1 :(得分:0)

管道将URL转换为恰好在一个EDM实体类上的转换。所以简短的回答是,你不能按照自己的方式去做。但是,您可以做的是创建一个复合类(如果您使用EF,则使用视图):

class Base
{
    [Key]
    public int ID;
    public string Name;
    public string Gender;
    public string Comment;
}

[Table("T1")]
class TableOneEntity : Base
{

}

[Table("T2")]
class TableTwoEntity : Base
{
    // extra columns from T2
    public string Country;
    public string City;
}

[Table("V1")] // which is a view containing columns from Base, T1 and T2.
class CompositeEntity : Base
{
    // extra columns from T1
    .....

    // extra columns from T2
    public string Country;
    public string City;
}

然后你可以这样做:

[EnableQuery(PageSize = 100)] // For server-driven paging -- recommended but not obligatory
public IHttpActionResult GetTableResult()
{
    return appDbCtx.Composite;
}

请记住将复合类添加到EDM(通常在WebApiConfig.cs中)。就是这样。 OData管道将为您完成所有其余的工作。

修改

事实上,事实证明,你可以通过使用开放类型来做你想做的事情。见http://www.asp.net/web-api/overview/odata-support-in-aspnet-web-api/odata-v4/use-open-types-in-odata-v4。但是,我怀疑复合类/视图在您的情况下将是更简单的选项。