如何将DTO的ODataQueryOptions应用于基础EntitySet?

clt*_*ang 6 c# entity-framework odata asp.net-web-api

有2类,Foo和Bar。Foo对象中嵌套了一个Bar对象。

public class Foo {
    public Guid FooId { get; set; }
    public string FooName { get; set; }
    [ForeignKey("Bar")]
    public Guid BarId { get; set; }

    public virtual Bar Bar { get; set; }
}

public class Bar {
    public Guid BarId { get; set; }
    public string BarName { get; set; }
}

public class FooBarContext : DbContext {
    public DbSet<Foo> Foos { get; set; }
    public DbSet<Bar> Bars { get; set; }
}

public class FooDTO {
    public Guid FooId { get; set; }
    public string FooName { get; set; }
    public Guid BarId { get; set; }
    public string BarName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

我的问题是:我可以以某种方式将FooDTO的OData查询转换为Foo的OData查询,以便可以将其应用于Foos DbSet吗?

例如,我想通过BarName进行查询,该名称最终来自嵌套的Bar对象。

GET /Foos?$filter=BarName eq 'Bar2'
Run Code Online (Sandbox Code Playgroud)

这是处理查询的控制器和操作

public class FoosController {
    public async Task<IHttpActionResult> GetFoos(ODataQueryOptions<FooDTO> queryOptions) {
        // translate filter FooDTO.BarName to filter Foo.Bar.Name
        // ODataQueryOptions<Foo> fooQueryOptions = ....
        using (var context = new FooBarContext()) {
            return fooQueryOptions.ApplyTo(context.Foos);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

谢谢。

Ela*_*ode 3

首先将 OData 包安装到您的 Web API 项目

Install-Package Microsoft.AspNet.OData -Version 7.1.0
Run Code Online (Sandbox Code Playgroud)

WebApiConfig.cs通过添加以下using语句来配置 OData 端点

using System.Web.OData.Builder;
using System.Web.OData.Extensions;
Run Code Online (Sandbox Code Playgroud)

并在该Register方法中添加以下代码

public static void Register(HttpConfiguration config)
{
    config.MapHttpAttributeRoutes();

    // New code start
    ODataModelBuilder builder = new ODataConventionModelBuilder();
    builder.EntitySet<Foo>("Foos");
    builder.EntitySet<Bar>("Bars");
    config.MapODataServiceRoute(
        routeName: "ODataRoute",
        routePrefix: null,
        model: builder.GetEdmModel());

    config.Count().Filter().OrderBy().Expand().Select().MaxTop(null);

    config.EnableDependencyInjection();
    // New code end

    config.Routes.MapHttpRoute(
        name: "DefaultApi",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional }
    );
}
Run Code Online (Sandbox Code Playgroud)

更新映射:在您的控制器中

[EnableQuery()] // Enables clients to modify the query, by using query options such as $filter, $sort, and $page
public async Task<IHttpActionResult> GetFoos(ODataQueryOptions<FooDTO> queryOptions)
{
    using (var context = new FooBarContext())
    {
        return queryOptions.ApplyTo(context.Foos.AsQueryable().Select(f => new FooDTO
        {
            BarId = f.BarId,
            BarName = f.Bar.BarName,
            FooId = f.FooId,
            FooName = f.FooName
        }));
    }
}
Run Code Online (Sandbox Code Playgroud)

有关更多信息,请查看使用 ASP.NET Web API 创建 OData v4 端点

还可以使用 OData 和 ASP.NET Core 增强您的 Web API(对于 .Net core,但它可能会有所帮助)