构建表达式以过滤数据 EF Core
Build Expression to filter data EF Core
我需要重用可用的表达式:
Expression<Func<Picture, int>> selector = o => o.EntityId;
并为 Where 构建表达式:
Expression<Func<Picture, bool>> filter = w => w.EntityId > 5;
如何构建这样的表达式?
下一个操作不会在客户端执行,对吧?
var collection = _dbContext.Pictures.Where(filter).ToList();
配置您的 DbContext 以禁止客户端求值和测试。
例如
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFQuerying;Trusted_Connection=True;")
.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
}
见https://docs.microsoft.com/en-us/ef/core/querying/client-eval#previous-versions
或者开始迁移到 EF Core 3.1,它增强了查询翻译功能,并删除了客户端评估 "feature"。
我终于弄明白了如何动态构建表达式:
Expression<Func<Picture, int>> selector = o => o.EntityId;
var parameter = Expression.Parameter(typeof(Picture));
// get property name
if (!(selector.Body is MemberExpression memberExpression))
{
memberExpression = ((UnaryExpression)selector.Body).Operand as MemberExpression;
}
var propertyName = memberExpression.ToString().Substring(2);
var expressionParameter = Expression.Property(parameter, propertyName);
var expressionBody = Expression.GreaterThan(expressionParameter, Expression.Constant(5, typeof(int)));
var filter = Expression.Lambda<Func<Picture, bool>>(expressionBody, parameter);
var collection = _dbContext.Pictures.Where(filter).ToList();
一般示例:
var filter = CreateFilter<Picture, int>(o => o.EntityId, 5);
var collection = _dbContext.Pictures.Where(filter).ToList();
private Expression<Func<TData, bool>> CreateFilter<TData, TKey>(Expression<Func<TData, TKey>> selector, TKey valueToCompare)
{
var parameter = Expression.Parameter(typeof(TData));
var expressionParameter = Expression.Property(parameter, GetParameterName(selector));
var body = Expression.GreaterThan(expressionParameter, Expression.Constant(valueToCompare, typeof(TKey)));
return Expression.Lambda<Func<TData, bool>>(body, parameter);
}
private string GetParameterName<TData, TKey>(Expression<Func<TData, TKey>> expression)
{
if (!(expression.Body is MemberExpression memberExpression))
{
memberExpression = ((UnaryExpression)expression.Body).Operand as MemberExpression;
}
return memberExpression.ToString().Substring(2);
}
感谢 David 关于 的回复,我能够验证过滤没有在客户端执行
我需要重用可用的表达式:
Expression<Func<Picture, int>> selector = o => o.EntityId;
并为 Where 构建表达式:
Expression<Func<Picture, bool>> filter = w => w.EntityId > 5;
如何构建这样的表达式?
下一个操作不会在客户端执行,对吧?
var collection = _dbContext.Pictures.Where(filter).ToList();
配置您的 DbContext 以禁止客户端求值和测试。
例如
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder
.UseSqlServer(@"Server=(localdb)\mssqllocaldb;Database=EFQuerying;Trusted_Connection=True;")
.ConfigureWarnings(warnings => warnings.Throw(RelationalEventId.QueryClientEvaluationWarning));
}
见https://docs.microsoft.com/en-us/ef/core/querying/client-eval#previous-versions
或者开始迁移到 EF Core 3.1,它增强了查询翻译功能,并删除了客户端评估 "feature"。
我终于弄明白了如何动态构建表达式:
Expression<Func<Picture, int>> selector = o => o.EntityId;
var parameter = Expression.Parameter(typeof(Picture));
// get property name
if (!(selector.Body is MemberExpression memberExpression))
{
memberExpression = ((UnaryExpression)selector.Body).Operand as MemberExpression;
}
var propertyName = memberExpression.ToString().Substring(2);
var expressionParameter = Expression.Property(parameter, propertyName);
var expressionBody = Expression.GreaterThan(expressionParameter, Expression.Constant(5, typeof(int)));
var filter = Expression.Lambda<Func<Picture, bool>>(expressionBody, parameter);
var collection = _dbContext.Pictures.Where(filter).ToList();
一般示例:
var filter = CreateFilter<Picture, int>(o => o.EntityId, 5);
var collection = _dbContext.Pictures.Where(filter).ToList();
private Expression<Func<TData, bool>> CreateFilter<TData, TKey>(Expression<Func<TData, TKey>> selector, TKey valueToCompare)
{
var parameter = Expression.Parameter(typeof(TData));
var expressionParameter = Expression.Property(parameter, GetParameterName(selector));
var body = Expression.GreaterThan(expressionParameter, Expression.Constant(valueToCompare, typeof(TKey)));
return Expression.Lambda<Func<TData, bool>>(body, parameter);
}
private string GetParameterName<TData, TKey>(Expression<Func<TData, TKey>> expression)
{
if (!(expression.Body is MemberExpression memberExpression))
{
memberExpression = ((UnaryExpression)expression.Body).Operand as MemberExpression;
}
return memberExpression.ToString().Substring(2);
}
感谢 David 关于