我有一个控制器,其参数为
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
属性:
这是我的 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
在控制器内不起作用。仅在结果返回后。
您可以检查下面的代码:
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);
}
}
}