[英]Entity Framework Core: How to IgnoreQueryFilters for DbSet Find method
我正在使用全局查询过滤器,但不想将其应用于 DbSet .Find
方法。 我不能使用.IgnoreQueryFilters
因为它返回IQueryable
。 由于性能原因,我也不想使用.FirstOrDefault
。
帮助表示赞赏。
您可以为IDbSet<T>
创建“Find”扩展方法,您可以在其中“模拟”原始Find
方法查找流程。
public static async Task<T> FindAsync<T>(this IDbSet<T> source, Expression<Func<TSource,bool>> predicate)
where T : class, new()
{
// parameters validation if needed
return
source.Local.SingleOrDefault(predicate)
?? await source.IgnoreQueryFilters().SingleOrDefaultAsync(predicate);//.ConfigureAwait(false);
}
我没有测试它,但可能工作得很好。
如果您有一些通用的表键约定,您甚至可以使用更通用的扩展方法。
public static async Task<T> FindAsync<T, TKey>(this IDbSet<T> source, TKey id)
where T : class, new()
where TKey : IEquatable<TKey>
{
// parameters validation if needed
return
source.Local.SingleOrDefault(e => e.Id == id)
?? await source.IgnoreQueryFilters().SingleOrDefaultAsync(e => e.Id == id);//.ConfigureAwait(false);
}
希望能帮助到你。
我基于dropoutcoder解决方案创建了更通用的方法。 它不要求 DbSet 具有带有严格Id
名称的主键。 它仍然只有一个键限制,但它很适合我。
public static class DataContextProviderExtensions
{
public static T FindWithIgnoreQueryFilters<T, TValue>(this DataContextProvider context, TValue id) where T : class, new()
{
var expr = GetByIdExpression<T, TValue>(context, id);
return context.Set<T>().Local.SingleOrDefault(expr.Compile())
?? context.Set<T>().IgnoreQueryFilters().SingleOrDefault(expr);
}
private static Expression<Func<T, bool>> GetByIdExpression<T, TValue>(DataContextProvider context, TValue id) where T : class, new()
{
var keys = context.GetEntityKeys<T>().ToArray();
if (keys.Length != 1)
throw new Exception("GetByIdExpression works only with Entity which has one primary key column.");
var param = Expression.Parameter(typeof(T), "p");
var exp = Expression.Lambda<Func<T, bool>>(
Expression.Equal(
Expression.Property(param, keys[0]),
ExpressionClosureFactory.GetField(id)
),
param
);
return exp;
}
}
internal class ExpressionClosureFactory
{
public static MemberExpression GetField<TValue>(TValue value)
{
var closure = new ExpressionClosureField<TValue>
{
ValueProperty = value
};
return Expression.Field(Expression.Constant(closure), "ValueProperty");
}
class ExpressionClosureField<T>
{
public T ValueProperty;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.