entity-framework - 实体框架 LinqKit 动态 where 相关数据的谓词
问题描述
该代码是 Alpha 版本,没有验证或错误管理......稍后会包含它。
我有一个非常简单的模型,其中包含两个相关实体:Location
和Country
:
public class UNCountry
{
public int UNCountryId { get; set; }
[Required]
[MaxLength(2, ErrorMessage = "The field {0} only can contains a maximum of {1} characters lenght.")]
[RegularExpression("[A-Z][A-Z]", ErrorMessage = "The field {0}, This code is formed by Two(2) capital letters")]
public string Code { get; set; }
[Required]
[MaxLength(255, ErrorMessage = "The field {0} only can contains a maximum of {1} characters lenght.")]
public string Name { get; set; }
}
public class UNLocation
{
public int UNLocationId { get; set; }
[MaxLength(1, ErrorMessage = "The field {0} only can contains a maximum of {1} characters lenght.")]
public string UNChangeType { get; set; }
[Required]
[MaxLength(5, ErrorMessage = "The field {0} only can contains a maximum of {1} characters lenght.")]
[RegularExpression("[A-Z]{5}", ErrorMessage = "The field {0}, This code is formed by 5 capital letters")]
public string Code { get; set; }
[Required]
[MaxLength(255, ErrorMessage = "The field {0} only can contains a maximum of {1} characters lenght.")]
public string Name { get; set; }
public int UNCountryId { get; set; }
public UNCountry UNCountry { get; set; }
}
我有一个列出所有位置的应用程序,用户可以按任何列进行过滤,这是 Angular 中的通用组件视图,我希望所有列过滤器都是动态的。过滤器作为数组传入 JsonFilters 参数
[{name:"nameOfField1", value:"valueOfField1"},...],
然后我用 LinqKit 和 PredicateBuilder 构造一个谓词,并在查询中使用谓词 .Where(predicate)。它完美地工作。
这是控制器中的初始代码
var validFilter = new PaginationFilter(
pF.PageNumber, pF.PageSize, pF.JsonFilters
);
var p = validFilter.CreateDynamicSearch<UNLocation>();
//var b = PredicateBuilder.New<UNLocation>(true);
//b = b.And(c => c.UNCountry.Name.Contains("Col"));
var pagedData = await _context.UNLocations
.Include(c => c.UNCountry)
.Where(p)
//.Where(d => d.UNCountry.Name.Contains("Col"))
.OrderBy(x => x.UNLocationId)
.Skip((validFilter.PageNumber - 1) * validFilter.PageSize)
.Take(validFilter.PageSize)
.ToListAsync();
var totalRecords = await _context.UNLocations.CountAsync();
return Ok(new PagedResponse<List<UNLocation>>(pagedData, validFilter.PageNumber, validFilter.PageSize,totalRecords));
我在过滤器参数中传递了字段名和值,一切正常,但是当我对国家/地区名称进行过滤时(字段名称是 UNCountry.Name),谓词在 UNLocations 上使用此字段名称失败,它在构造谓词的函数中失败,但是如果我直接在 Where 中使用(前面代码中的注释行 //.Where(d => d.UNCountry.Name.Contains("Col")) )它可以工作,我可以像这样解决问题,但是对于查询中具有更多相关数据字段的其他视图来说,它不会是动态的。
这是谓词生成函数:
public Expression<Func<T, bool>> CreateDynamicSearch<T>()
{
var predicate = PredicateBuilder.New<T>(true);
foreach (ReqFilter filter in this.Filters)
{
var columnFilter = PredicateBuilder.New<T>(false);
var param = Expression.Parameter(typeof(T), "a");
string[] filterParts = filter.Name.Split(".");
string filterName = filterParts[0];
if (filterParts.Length == 1)
{
var prop = Expression.Property(param, filterName);
var call = Expression.Call(prop, "Contains", new Type[0], Expression.Constant(filter.Value));
columnFilter = columnFilter.Or(Expression.Lambda<Func<T, bool>>(call, param));
predicate = predicate.And(columnFilter);
}
else
{
var prop = Expression.Property(param, filter.Name);
var call = Expression.Call(prop, "Contains", new Type[0], Expression.Constant(filter.Value));
columnFilter = columnFilter.Or(Expression.Lambda<Func<T, bool>>(call, param));
predicate = predicate.And(columnFilter);
}
}
return predicate;
}
如果我使用 UNLocation 的普通字段(如代码或名称 byExample [{code:"MIA"},name:"MI"])传递过滤器,则此代码运行良好,但如果我发送列名,谓词构造函数将失败相关的 UNCountry Name byExample [{UNCountry.Name:"United States"}],我重复如果我在设计时代码中编写 Where 代码,它可以工作,但我需要具有 mor 灵活性,并在谓词中生成。有可能或如何做到这一点?提前谢谢,原谅我的英语。
解决方案
推荐阅读
- python - 从电子邮件中提取文本后,空格替换为 =20
- gnuplot - 我正在尝试使用 multiplot 来结合 plot 和 splot 但 x,y 标签似乎被转移了
- c# - C# 中的 Api GetAccessToken 不返回
- javascript - React suspense 有什么好处?
- python - 从元组列表中获取每个元组的最大值列表
- ruby-on-rails - 启动 ruby 服务器时出错,特别是 SystemStackError
- angular - 角度 appBootstrap 方法
- git - 如何为 pack.windowMemory 设置值?
- c - C中的结构数组大小
- postgresql - 在 Mac 上安装 PostGIS for PostgreSQL 时出错