用表达式创建EF查询扩展



我想写一个IQueryable扩展方法来过滤掉一些实体。这个方法应该有一个类型为expression_func_lt;T, int_gt;>的形参。用于过滤实体。

这是我的尝试,我不知道为什么这不起作用。什么好主意吗?

public static IQueryable<T> AddDefaultQuery<T>(this IQueryable<T> query, Expression<Func<T, int>> countryId, ApplicationDbContext db, ClaimsPrincipal claimsPrincipal)
{
if (claimsPrincipal.IsEppRole()) {
var userCountryIds = db.UserCountry.Where(uc => uc.UserId == LoginUser.GetUserID(claimsPrincipal)).Select(uc => uc.CountryId);
query = query.Where(q => userCountryIds.Contains(countryId.Compile()(q)));
}
return query;
}

错误是:

异常发生:CLR/System。InvalidOperationException抛出异常:'System. 'Microsoft.EntityFrameworkCore.dll中的InvalidOperationException: ' LINQ表达式'其中(=比;a.删除== False)其中(=比;__userCountryIds_0.Contains(__Compile_1.Invoke(a)))'无法翻译。要么以可翻译的形式重写查询,要么通过插入对'AsEnumerable', 'AsAsyncEnumerable', 'ToList'或'ToListAsync'的调用显式切换到客户端计算。更多信息请参见https://go.microsoft.com/fwlink/?linkid=2101038

最近遇到了同样的问题。问题在这里:

Where(q => userCountryIds.Contains(countryId.Compile()(q))).

我了解到Func里面的Contains里面的Where不是LINQ到SQL转换器可以处理的东西。正如我注意到的,编译的表达式也不会被翻译成SQL,它们将在查询SQL后执行,这可能会导致性能下降。

我猜你的表达式是这样的

Expression<Func<T, int>> expression = foo => foo.Id

现在如果我们创建一个这样的表达式:

//don't forget to put a constraint on T like 
//"where T : IHasId" or something like that
public static Expression<Func<T, bool>> BuildExpression<T>(ApplicationDbContext db, ClaimsPrincipal claimsPrincipal)
{
var userCountryIds = db.UserCountry
//this one might also not be translated to SQL
//because it uses function that is not supported by SQL
.Where(uc => uc.UserId == LoginUser.GetUserID(claimsPrincipal))
.Select(uc => uc.CountryId)
.ToList();
var isEppRole = claimsPrincipal.IsEppRole();
return foo => !isEppRole || userCountryIds.Contains(foo.Id);
}

然后在扩展方法

public IQueryable<T> AddDefaultQuery<T>(this IQueryable<T> query, ApplicationDbContext db, ClaimsPrincipal claimsPrincipal)
{
var exp = BuildExpression<T>(db, claimsPrincipal);
//no lambdas, nothing else except the expression itself
return query.Where(exp);
}

这个方法帮助了我,希望它也能帮助你,或者至少能给你指明正确的方向

最新更新