.NET Core OData - $expand 无法在后端使用 ODataQueryOptions

问题描述 投票:0回答:1

我有一个控制器,其参数为

OdataQueryOptions
,如下:

[EnableQuery]
public async Task<ActionResult<IEnumerable<SecuredEmployee>>> Get([FromQuery] int? managerLevel,
                                                                  [FromQuery] string? managerEmployeeNumber,
                                                                  [FromQuery] bool isSearch = false,
                                                                  ODataQueryOptions<SecuredEmployee>? options = null)
{
    var userId = "[email protected]";
    isSearch = true;

    var employees = await mediator.Send(new ListEmployeesQuery(managerLevel, managerEmployeeNumber, userId, isSearch: isSearch), CancellationToken.None);

    var filteredResults = options?.Filter.ApplyTo(employees.AsQueryable(), new ODataQuerySettings()) as IQueryable<SecuredEmployee>;

    var expandedResults = options?.SelectExpand.ApplyTo(filteredResults, new ODataQuerySettings()) as IQueryable<SecuredEmployee>;

    return Ok(employees);
}

这是电话:

https://localhost:7145/odata/ExportSearchResults/
        ?$filter=((contains(forename, 'dange')) or (contains(surname, 'dange')) or (contains(employeeNumber, 'dange'))) and (status eq true)
        &$expand=PerformanceReviews,EngagementScores,TalentAssessments,SecuredEmployeeDetails
        &isSearch=true&$top=5&$skip=0&$count=true

return Ok(employees)
之后,正确应用了过滤和扩展。

此外,应用

filteredResults
后,
$filter
会返回正确的结果。
expandedResults
返回 null。

这是

SelectExpand
属性:

enter image description here

这是我的 OData 配置:

public static ODataConventionModelBuilder AddODataEntities(this ODataConventionModelBuilder modelBuilder)
{
    modelBuilder.EntitySet<SecuredEmployee>("Employee").EntityType.HasKey(entity => entity.EmployeeId);
    modelBuilder.EntitySet<SecuredPerformanceReview>("PerformanceReview").EntityType.HasKey(entity => entity.Id);
    modelBuilder.EntitySet<SecuredEngagementScore>("EngagementScores").EntityType.HasKey(entity => entity.Id);
    modelBuilder.EntitySet<SecuredTalentAssessment>("TalentAssessments").EntityType.HasKey(entity => new { entity.EmployeeId, entity.Year });
    modelBuilder.EntitySet<TalentAssessmentAuditLog>("TalentAssessmentAuditLogs").EntityType.HasKey(entity => new { entity.EmployeeId, entity.Year, entity.IdentityId, entity.EffectiveDate });
    modelBuilder.EntitySet<SecuredEmployeeDetails>("EmployeeDetails").EntityType.HasKey(entity => new { entity.EmployeeId });
    modelBuilder.EntitySet<SecuredMobilityConsideration>("MobilityConsiderations").EntityType.HasKey(entity => entity.Id);
    modelBuilder.EntitySet<SecuredEmployee>("ExportSearchResults").EntityType.HasKey(entity => entity.EmployeeId);

    return modelBuilder;
}

还有 AddOData 语句:

services.AddControllers().AddOData(opt => opt.Count().Filter().Expand().Select().OrderBy().SetMaxTop(100)
    .AddRouteComponents("odata", builder.GetEdmModel()));

有什么问题吗?

提前致谢。

我尝试使用前端应用的相同过滤器将完全相同的结果导出到 Excel 文件,因此我需要

$expand
$filter
才能正常工作。在这种情况下,
$expand
在控制器内不起作用。仅在结果返回后。

c# .net asp.net-mvc asp.net-core odata
1个回答
0
投票

您可以检查下面的代码:

public class SecuredEmployee
{
    [Key]
    public int EmployeeId { get; set; }
    public string Forename { get; set; }
    public string Surname { get; set; }
    public string EmployeeNumber { get; set; }
    public bool Status { get; set; }

    public virtual ICollection<SecuredPerformanceReview> PerformanceReviews { get; set; }
    public virtual ICollection<SecuredEngagementScore> EngagementScores { get; set; }
    public virtual ICollection<SecuredTalentAssessment> TalentAssessments { get; set; }
    public virtual ICollection<SecuredEmployeeDetails> EmployeeDetails { get; set; }
}

ApplicationDbContext.cs:

using Microsoft.EntityFrameworkCore;
using ODataExample.Models;

namespace ODataExample.Data
{
    public class ApplicationDbContext : DbContext
    {
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
            : base(options) { }

        public DbSet<SecuredEmployee> SecuredEmployees { get; set; }
        public DbSet<SecuredPerformanceReview> PerformanceReviews { get; set; }
        public DbSet<SecuredEngagementScore> EngagementScores { get; set; }
        public DbSet<SecuredTalentAssessment> TalentAssessments { get; set; }
        public DbSet<SecuredEmployeeDetails> EmployeeDetails { get; set; }

        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            base.OnModelCreating(modelBuilder);

            modelBuilder.Entity<SecuredEmployee>().HasKey(e => e.EmployeeId);
            modelBuilder.Entity<SecuredPerformanceReview>().HasKey(e => e.Id);
            modelBuilder.Entity<SecuredEngagementScore>().HasKey(e => e.Id);
            modelBuilder.Entity<SecuredTalentAssessment>().HasKey(e => new { e.EmployeeId, e.Year });
            modelBuilder.Entity<SecuredEmployeeDetails>().HasKey(e => e.EmployeeId);
        }
    }
}

EmployeesController.cs:

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.OData.Query;
using Microsoft.AspNetCore.OData.Routing.Controllers;
using Microsoft.EntityFrameworkCore;
using ODataExample.Data;
using ODataExample.Models;

namespace ODataExample.Controllers
{
    public class EmployeesController : ODataController
    {
        private readonly ApplicationDbContext _context;

        public EmployeesController(ApplicationDbContext context)
        {
            _context = context;
        }

        [EnableQuery]
        public async Task<ActionResult<IEnumerable<SecuredEmployee>>> Get(ODataQueryOptions<SecuredEmployee> options)
        {
            var employees = await _context.SecuredEmployees
                .Include(e => e.PerformanceReviews)
                .Include(e => e.EngagementScores)
                .Include(e => e.TalentAssessments)
                .Include(e => e.EmployeeDetails)
                .ToListAsync();

            var employeesQuery = employees.AsQueryable();
            var filteredResults = options?.Filter?.ApplyTo(employeesQuery, new ODataQuerySettings()) as IQueryable<SecuredEmployee>;

            if (filteredResults == null)
            {
                return BadRequest("Filtered results are null");
            }

            var expandedResults = options?.SelectExpand?.ApplyTo(filteredResults, new ODataQuerySettings()) as IQueryable<SecuredEmployee>;

            if (expandedResults == null)
            {
                return BadRequest("Expanded results are null");
            }

            return Ok(expandedResults);
        }
    }

}
© www.soinside.com 2019 - 2024. All rights reserved.