I try to make a global query. I know that this is possible in EF Core 2.0 however I need to do it using EF 6.
I try to do something like this in EF 6: (IsDeleted is a property in my Class Cliente as boolean)
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
modelBuilder.Entity<Client>().HasQueryFilter(x => x.IsDeleted= false);
}
I will appreciate your help, thank you!
What I believe is that you want to implement soft-delete in your application. To apply a global query filter you can follow this approach too.
first of all, install System.linq.Dynamic
Library using NuGet.
Then create one extension Method like:
public static IQueryable<T> WhereDeleted<T>(this IQueryable<T> source)
{
return source.Where("IsDeleted== false");
}
and then you can call other methods like this:
var client = db.Client.Include("whatever you need")
.WhereDeleted().Where(c => c.Age < 30);
Unfortunately, EF6 doesn't support query filters.
Here is an approach you could use to implement similar behaviour.
Note: This approach doesn't use Dependency injection (DI), however it should be simple enough to modify it to make use of DI.
//Marker interface
public interface IQueryFilter
{
}
public interface IQueryFilter<T> : IQueryFilter
where T : class
{
Expression<Func<T, bool>> Expression { get; }
}
public static class QueryableExtensions
{
private static readonly Lazy<IEnumerable<Type>> _queryFilterTypes = new Lazy<IEnumerable<Type>>(GetQueryFilterTypes);
public static IQueryable<T> Filter<T>(this IQueryable<T> queryable)
where T : class
{
foreach (Type type in _queryFilterTypes.Value)
{
IQueryFilter<T> queryFilter = Create<T>(type);
if (queryFilter?.Expression != null)
{
queryable = queryable.Where(queryFilter.Expression);
}
}
return queryable;
}
private static IEnumerable<Type> GetQueryFilterTypes()
{
return Assembly.GetExecutingAssembly() //the assembly where you will have your query filters
.GetTypes()
.Where(x => typeof(IQueryFilter).IsAssignableFrom(x)
&& !x.IsAbstract)
.ToArray();
}
private static IQueryFilter<T> Create<T>(Type type)
where T : class
{
IQueryFilter<T> filter = null;
if (typeof(IQueryFilter<T>).IsAssignableFrom(type))
{
filter = CreateImpl(type);
}
else if (type.IsGenericType)
{
Type entityType = typeof(T);
TypeInfo typeInfo = type.GetTypeInfo();
Type genericParameter = typeInfo.GenericTypeParameters.SingleOrDefault();
if (genericParameter != null)
{
foreach (var constraint in genericParameter.GetGenericParameterConstraints())
{
if (!constraint.IsAssignableFrom(entityType))
{
return null;
}
}
}
filter = CreateImpl(type.MakeGenericType(entityType));
}
return filter;
IQueryFilter<T> CreateImpl(Type t)
{
IQueryFilter<T> result = null;
ConstructorInfo constructor = t.GetConstructor(Array.Empty<Type>());
if (constructor != null)
{
result = (IQueryFilter<T>)constructor.Invoke(Array.Empty<object>());
}
return result;
}
}
}
Example interface:
public interface ISoftDeletable
{
bool IsDeletable { get; }
}
Example entity:
public class Person : ISoftDeletable
{
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsDeleted { get; set; }
}
Example IQueryFilter<T>
implementation
public class NotDeletedQueryFilter<T> : IQueryFilter<T>
where T : class, ISoftDeletable
{
public Expression<Func<T, bool>> Expression { get; } = x => !x.IsDeleted;
}
Example usage. (The DbContext
has a DbSet<Person>
named People
)
var peoples = await dbContext.People
.Filter()
.ToListAsync();
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.