EF Core 5.x + OData 7.5.6 - $Top 不会在 EF 查询中插入 TOP

时间:2021-03-18 22:49:30

标签: entity-framework-core odata

我想我错过了一些很简单的事情,但这就是我想要做的。我有一个带有 EF Core 5 + OData 7.5.6 的 .NET Core 5 项目。除了在生成的 SQL 查询中插入 TOP 命令之外,一切似乎都在工作。这是我的控制器。很简单。

[EnableQuery]
[ApiController]
[Route("odata/[controller]")]
public class ConferenceHistoryController : ControllerBase
{
    private readonly cdr_database_2Context _db;

    public ConferenceHistoryController(cdr_database_2Context db)
    {
        _db = db;
    }

    [HttpGet]
    public IEnumerable<_000701CallDataRecord> GetConferenceList()
    {
        // Return Full List
        var query = _db._000701CallDataRecords;
        var qs = query.ToQueryString();
        return query.ToList();
    }
}

当我将请求发送至:

https://localhost:44355/odata/ConferenceHistory/?$select=RecordId,version&$top=5

生成的 SQL 查询是:

SELECT [0].[endDateTime], [0].[id], [0].[organizer], [0].[ParticipantCount], [0].[participants], [0].[PoorCall], [0].[type], [0].[version]

从 [000701_CallDataRecord] AS [0]

如您所见,它缺少 TOP 和 SELECT 命令。我的 Startup.cs 中有以下内容

public void ConfigureServices(IServiceCollection services)
    {
        // Add CORS to Project
        services.AddCors(options =>
        {
            options.AddDefaultPolicy(builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader());
        });

        // Add OData
        services.AddOData();
        services.AddControllers();
        services.AddDbContext<cdr_database_2Context>(options =>
                options.UseSqlServer(Configuration.GetConnectionString("CDRConnection"))
            );

        // Add Swagger Support
        services.AddSwaggerGen(c =>
        {
            c.SwaggerDoc("v1", new OpenApiInfo { Title = "ODataAPI", Version = "v1" });
        });
        SetOutputFormatters(services);
    }

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        // Use HTTPS & Routing
        app.UseHttpsRedirection();
        app.UseRouting();

        // Auth???
        app.UseAuthorization();

        // Swagger Configure
        app.UseSwagger();
        app.UseSwaggerUI((config) =>
        {
            config.SwaggerEndpoint("/swagger/v1/swagger.json", "Swagger Odata Demo Api");
        });

        // Setup Endpoint for EDM
        app.UseEndpoints(endpoints =>
        {
            endpoints.MapControllers();
            endpoints.EnableDependencyInjection();
            endpoints.Select().Expand().Filter().OrderBy().MaxTop(50).Count();
            endpoints.MapODataRoute("odata", "odata", GetEdmModel());
        });
    }

private IEdmModel GetEdmModel()
    {
        // Add OData - EDM Definitions Below
        var odataBuilder = new ODataConventionModelBuilder();
        odataBuilder.EntitySet<WeatherForecast>("WeatherForecast");
        odataBuilder.EntitySet<_000701CallDataRecord>("ConferenceHistory");

        return odataBuilder.GetEdmModel();
    }

只是在寻找可能出错的方向。其他一切似乎都运行良好。

2 个答案:

答案 0 :(得分:0)

  1. 您的控制器需要派生自 ODataController 而不是 ControllerBase
  2. 你需要用 [Queryable] 装饰 GetConferenceList()

答案 1 :(得分:0)

好的,我找到了上面的问题所在。这是使用 .ToList 和 IEumerable。所以如果我改变了这个:

[HttpGet]
public IEnumerable<_000701CallDataRecord> GetConferenceList()
{
    // Return Full List
    var query = _db._000701CallDataRecords;
    var qs = query.ToQueryString();
    return query.ToList();
}

致:

[HttpGet]
public IEnumerable<_000701CallDataRecord> GetConferenceList()
{
    // Return Full List
    var query = _db._000701CallDataRecords;
    var qs = query.ToQueryString();
    return query;
}

它有效。还值得注意的是 .ToQueryString() 不显示 TOP 命令的 OData/EF 插入。但是,如果我在 Startup.cs 文件中启用 .EnableSensitiveDataLogging(),那么我会清楚地看到它被插入其中。

显然,调用 .ToList() 将导致它处理并忽略任何花哨的 OData 命令。这是唯一的变化,当时一切都很好。

相关问题