[英]Entity Framework Core: How to IgnoreQueryFilters for DbSet Find method
I am using Global Query Filters but do not want to apply it on DbSet .Find
method.我正在使用全局查询过滤器,但不想将其应用于 DbSet
.Find
方法。 I can not use .IgnoreQueryFilters
because it returns IQueryable
.我不能使用
.IgnoreQueryFilters
因为它返回IQueryable
。 Also I do not want use .FirstOrDefault
due to performance reasons.由于性能原因,我也不想使用
.FirstOrDefault
。
Help is appreciated.帮助表示赞赏。
You can create 'Find' extension method for IDbSet<T>
where you can "simulate" original Find
method lookup flow.您可以为
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);
}
I didn't test it, but might work just fine.我没有测试它,但可能工作得很好。
In case you have some common table key convention you can even go for more generic extension method.如果您有一些通用的表键约定,您甚至可以使用更通用的扩展方法。
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);
}
Hope it helps.希望能帮助到你。
I created more generic approach based on dropoutcoder solution.我基于dropoutcoder解决方案创建了更通用的方法。 It does not require that DbSet has primary key with strict
Id
name.它不要求 DbSet 具有带有严格
Id
名称的主键。 It still has only one key restriction but it suits me well.它仍然只有一个键限制,但它很适合我。
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.