Why only one EF Core Global Query Filter work but others are not
Hi, I'm working with
EF Core 6
, recently I want to use the Global Query Filters
.
So in OnModelCreating
inside my DbContext
I applied the two Gobal Query Filters
shown bellow:
The Problem:
The problem is only the first query filter
who applied, but the IAuditable
one not applied, please how do I fix this issue ?
Massive thanks in advance
@Database6 Replies
My query filters:
foreach ( var entityType in modelBuilder.Model.GetEntityTypes() )
{
if ( typeof( IArchivable ).IsAssignableFrom( entityType.ClrType ) )
{
var parameter = Expression.Parameter( entityType.ClrType , "p" );
var isArchivedProperty = MemberExpression.Property(parameter, "IsArchived");
// check isArchived == null
var isArchivedNullCheck = Expression.Equal( isArchivedProperty , Expression.Constant( null , typeof( bool ? ) ) );
var isArchivedNullFunc = Expression.Lambda( isArchivedNullCheck , parameter );
// check isArchived == false
var isArchivedFalseCheck = Expression.Equal( isArchivedProperty , Expression.Constant( false , typeof( bool ? ) ) );
var isArchivedFalseFunc = Expression.Lambda( isArchivedFalseCheck , parameter );
// Combine the two expressions using OR
var isArchivedCExpression = Expression.OrElse( isArchivedNullCheck , isArchivedFalseCheck );
// Create the lambda expression
var isArchivedFunc = Expression.Lambda( isArchivedCExpression , parameter );
modelBuilder.Entity( entityType.ClrType ).HasQueryFilter( isArchivedFunc );
}
foreach ( var entityType in modelBuilder.Model.GetEntityTypes() )
{
if ( typeof( IArchivable ).IsAssignableFrom( entityType.ClrType ) )
{
var parameter = Expression.Parameter( entityType.ClrType , "p" );
var isArchivedProperty = MemberExpression.Property(parameter, "IsArchived");
// check isArchived == null
var isArchivedNullCheck = Expression.Equal( isArchivedProperty , Expression.Constant( null , typeof( bool ? ) ) );
var isArchivedNullFunc = Expression.Lambda( isArchivedNullCheck , parameter );
// check isArchived == false
var isArchivedFalseCheck = Expression.Equal( isArchivedProperty , Expression.Constant( false , typeof( bool ? ) ) );
var isArchivedFalseFunc = Expression.Lambda( isArchivedFalseCheck , parameter );
// Combine the two expressions using OR
var isArchivedCExpression = Expression.OrElse( isArchivedNullCheck , isArchivedFalseCheck );
// Create the lambda expression
var isArchivedFunc = Expression.Lambda( isArchivedCExpression , parameter );
modelBuilder.Entity( entityType.ClrType ).HasQueryFilter( isArchivedFunc );
}
else if ( typeof( IAuditable ).IsAssignableFrom( entityType.ClrType ) )
{
var parameter = Expression.Parameter( entityType.ClrType , "p" );
var isDeletedProperty = MemberExpression.Property(parameter, "IsDeleted");
// check isDeleted == null
var isDeletedNullCheck = Expression.Equal( isDeletedProperty , Expression.Constant( null , typeof( bool ? ) ) );
var isDeletedNullFunc = Expression.Lambda( isDeletedNullCheck , parameter );
// check isDeleted == false
var isDeletedFalseCheck = Expression.Equal( isDeletedProperty , Expression.Constant( false , typeof( bool ? ) ) );
var isDeletedFalseFunc = Expression.Lambda( isDeletedFalseCheck , parameter );
// Combine the two expressions using OR
var isDeletedCExpression = Expression.OrElse( isDeletedNullCheck , isDeletedFalseCheck ); // IsDeleted == null || IsDeleted == false
// Create the lambda expression
var isDeletedFunc = Expression.Lambda( isDeletedCExpression , parameter ); // p => p.IsDeleted == null || p.IsDeleted == false
modelBuilder.Entity( entityType.ClrType ).HasQueryFilter( isDeletedFunc );
}
}
else if ( typeof( IAuditable ).IsAssignableFrom( entityType.ClrType ) )
{
var parameter = Expression.Parameter( entityType.ClrType , "p" );
var isDeletedProperty = MemberExpression.Property(parameter, "IsDeleted");
// check isDeleted == null
var isDeletedNullCheck = Expression.Equal( isDeletedProperty , Expression.Constant( null , typeof( bool ? ) ) );
var isDeletedNullFunc = Expression.Lambda( isDeletedNullCheck , parameter );
// check isDeleted == false
var isDeletedFalseCheck = Expression.Equal( isDeletedProperty , Expression.Constant( false , typeof( bool ? ) ) );
var isDeletedFalseFunc = Expression.Lambda( isDeletedFalseCheck , parameter );
// Combine the two expressions using OR
var isDeletedCExpression = Expression.OrElse( isDeletedNullCheck , isDeletedFalseCheck ); // IsDeleted == null || IsDeleted == false
// Create the lambda expression
var isDeletedFunc = Expression.Lambda( isDeletedCExpression , parameter ); // p => p.IsDeleted == null || p.IsDeleted == false
modelBuilder.Entity( entityType.ClrType ).HasQueryFilter( isDeletedFunc );
}
}
Because you can only have one global filter, if set the filter with
HasQueryFilter
and try to add another one with HasQueryFilter
, it'll actually replace the old filter.
You might want to combine the two expressions with Expression.AndAlso
Unknown User•3y ago
Message Not Public
Sign In & Join Server To View
But the problem is the
Entities types
will be differents because one filter should be applied on IAuditable
entities and another filter should be applied on IArchivable
entties.
Is I miss something ?
I'm gonna crazy with this issue
hmmmmm, omg maybe I should write query filter
for every entity
manuallyThat shouldn't be an issue, the parameter in the filter is the entity itself:
which can both implement
var parameter = Expression.Parameter( entityType.ClrType , "p" );
var parameter = Expression.Parameter( entityType.ClrType , "p" );
IAuditable
and IArchivable
. So instead of doing an "else-if", you change it to an if-statement that combines the expression.
Example:
foreach ( var entityType in modelBuilder.Model.GetEntityTypes() )
{
var parameter = Expression.Parameter( entityType.ClrType , "p" );
Expression condition? = null;
if ( typeof( IArchivable ).IsAssignableFrom( entityType.ClrType ) )
{
var isArchivedProperty = MemberExpression.Property(parameter, "IsArchived");
// check isArchived == null
var isArchivedNullCheck = Expression.Equal( isArchivedProperty , Expression.Constant( null , typeof( bool ? ) ) );
var isArchivedNullFunc = Expression.Lambda( isArchivedNullCheck , parameter );
// check isArchived == false
var isArchivedFalseCheck = Expression.Equal( isArchivedProperty , Expression.Constant( false , typeof( bool ? ) ) );
var isArchivedFalseFunc = Expression.Lambda( isArchivedFalseCheck , parameter );
// Combine the two expressions using OR
condition = Expression.OrElse( isArchivedNullCheck , isArchivedFalseCheck );
}
if ( typeof( IAuditable ).IsAssignableFrom( entityType.ClrType ) )
{
var isDeletedProperty = MemberExpression.Property(parameter, "IsDeleted");
// check isDeleted == null
var isDeletedNullCheck = Expression.Equal( isDeletedProperty , Expression.Constant( null , typeof( bool ? ) ) );
var isDeletedNullFunc = Expression.Lambda( isDeletedNullCheck , parameter );
// check isDeleted == false
var isDeletedFalseCheck = Expression.Equal( isDeletedProperty , Expression.Constant( false , typeof( bool ? ) ) );
var isDeletedFalseFunc = Expression.Lambda( isDeletedFalseCheck , parameter );
// Combine the two expressions using OR
var isDeletedCExpression = Expression.OrElse( isDeletedNullCheck , isDeletedFalseCheck ); // IsDeleted == null || IsDeleted == false
condition = condition == null ? isDeletedCExpression : Expression.AndAlso( condition , isDeletedCExpression );
}
if ( condition != null )
{
var filter = Expression.Lambda( condition , parameter );
modelBuilder.Entity( entityType.ClrType ).HasQueryFilter( filter );
}
}
foreach ( var entityType in modelBuilder.Model.GetEntityTypes() )
{
var parameter = Expression.Parameter( entityType.ClrType , "p" );
Expression condition? = null;
if ( typeof( IArchivable ).IsAssignableFrom( entityType.ClrType ) )
{
var isArchivedProperty = MemberExpression.Property(parameter, "IsArchived");
// check isArchived == null
var isArchivedNullCheck = Expression.Equal( isArchivedProperty , Expression.Constant( null , typeof( bool ? ) ) );
var isArchivedNullFunc = Expression.Lambda( isArchivedNullCheck , parameter );
// check isArchived == false
var isArchivedFalseCheck = Expression.Equal( isArchivedProperty , Expression.Constant( false , typeof( bool ? ) ) );
var isArchivedFalseFunc = Expression.Lambda( isArchivedFalseCheck , parameter );
// Combine the two expressions using OR
condition = Expression.OrElse( isArchivedNullCheck , isArchivedFalseCheck );
}
if ( typeof( IAuditable ).IsAssignableFrom( entityType.ClrType ) )
{
var isDeletedProperty = MemberExpression.Property(parameter, "IsDeleted");
// check isDeleted == null
var isDeletedNullCheck = Expression.Equal( isDeletedProperty , Expression.Constant( null , typeof( bool ? ) ) );
var isDeletedNullFunc = Expression.Lambda( isDeletedNullCheck , parameter );
// check isDeleted == false
var isDeletedFalseCheck = Expression.Equal( isDeletedProperty , Expression.Constant( false , typeof( bool ? ) ) );
var isDeletedFalseFunc = Expression.Lambda( isDeletedFalseCheck , parameter );
// Combine the two expressions using OR
var isDeletedCExpression = Expression.OrElse( isDeletedNullCheck , isDeletedFalseCheck ); // IsDeleted == null || IsDeleted == false
condition = condition == null ? isDeletedCExpression : Expression.AndAlso( condition , isDeletedCExpression );
}
if ( condition != null )
{
var filter = Expression.Lambda( condition , parameter );
modelBuilder.Entity( entityType.ClrType ).HasQueryFilter( filter );
}
}
@gerard sorry for annoying mate, I want to thanking you about your help and time
I almost used your provided solution
the problem is when I start my
I hope if you have any idea about how do I can fix this issue ?
and massive thanks in advance
ooooh my gosh I just did a mistake instead of
I have to
Massive thanks bro I really appreciate your help and effort
all love <3
foreach ( var entityType in modelBuilder.Model.GetEntityTypes() )
{
var parameter = Expression.Parameter( entityType.ClrType , "p" );
Expression ? conditions = null;
if ( typeof( IArchivable ).IsAssignableFrom( entityType.ClrType ) )
{
var isArchivedProperty = MemberExpression.Property( parameter , "IsArchived" );
// check isArchived == null
var isArchivedNullCheck = Expression.Equal( isArchivedProperty , Expression.Constant( null , typeof( bool ? ) ) );
var isArchivedNullFunc = Expression.Lambda( isArchivedNullCheck , parameter );
// check isArchived == false
var isArchivedFalseCheck = Expression.Equal( isArchivedProperty , Expression.Constant( false , typeof( bool ? ) ) );
var isArchivedFalseFunc = Expression.Lambda( isArchivedFalseCheck , parameter );
// Combine the two expressions using OR
conditions = Expression.OrElse( isArchivedNullFunc , isArchivedFalseFunc );
}
foreach ( var entityType in modelBuilder.Model.GetEntityTypes() )
{
var parameter = Expression.Parameter( entityType.ClrType , "p" );
Expression ? conditions = null;
if ( typeof( IArchivable ).IsAssignableFrom( entityType.ClrType ) )
{
var isArchivedProperty = MemberExpression.Property( parameter , "IsArchived" );
// check isArchived == null
var isArchivedNullCheck = Expression.Equal( isArchivedProperty , Expression.Constant( null , typeof( bool ? ) ) );
var isArchivedNullFunc = Expression.Lambda( isArchivedNullCheck , parameter );
// check isArchived == false
var isArchivedFalseCheck = Expression.Equal( isArchivedProperty , Expression.Constant( false , typeof( bool ? ) ) );
var isArchivedFalseFunc = Expression.Lambda( isArchivedFalseCheck , parameter );
// Combine the two expressions using OR
conditions = Expression.OrElse( isArchivedNullFunc , isArchivedFalseFunc );
}
if ( typeof( IAuditable ).IsAssignableFrom( entityType.ClrType ) )
{
var isDeletedProperty = MemberExpression.Property(parameter, "IsDeleted");
// check isDeleted == null
var isDeletedNullCheck = Expression.Equal( isDeletedProperty , Expression.Constant( null , typeof( bool ? ) ) );
var isDeletedNullFunc = Expression.Lambda( isDeletedNullCheck , parameter );
// check isDeleted == false
var isDeletedFalseCheck = Expression.Equal( isDeletedProperty , Expression.Constant( false , typeof( bool ? ) ) );
var isDeletedFalseFunc = Expression.Lambda( isDeletedFalseCheck , parameter );
// Combine the two expressions using OR
var isDeletedCExpression = Expression.OrElse( isDeletedNullCheck , isDeletedFalseCheck );
// Add the Expression to the Conditions
conditions = conditions == null ? isDeletedCExpression : Expression.AndAlso( conditions , isDeletedCExpression );
}
if ( conditions != null )
{
var filter = Expression.Lambda( conditions , parameter );
modelBuilder.Entity( entityType.ClrType ).HasQueryFilter( filter );
}
}
if ( typeof( IAuditable ).IsAssignableFrom( entityType.ClrType ) )
{
var isDeletedProperty = MemberExpression.Property(parameter, "IsDeleted");
// check isDeleted == null
var isDeletedNullCheck = Expression.Equal( isDeletedProperty , Expression.Constant( null , typeof( bool ? ) ) );
var isDeletedNullFunc = Expression.Lambda( isDeletedNullCheck , parameter );
// check isDeleted == false
var isDeletedFalseCheck = Expression.Equal( isDeletedProperty , Expression.Constant( false , typeof( bool ? ) ) );
var isDeletedFalseFunc = Expression.Lambda( isDeletedFalseCheck , parameter );
// Combine the two expressions using OR
var isDeletedCExpression = Expression.OrElse( isDeletedNullCheck , isDeletedFalseCheck );
// Add the Expression to the Conditions
conditions = conditions == null ? isDeletedCExpression : Expression.AndAlso( conditions , isDeletedCExpression );
}
if ( conditions != null )
{
var filter = Expression.Lambda( conditions , parameter );
modelBuilder.Entity( entityType.ClrType ).HasQueryFilter( filter );
}
}
ASP.net core 6
app I get this exception
InvalidOperationException: The binary operator OrElse is not defined for the types 'System.Func2[MBSM.Core.Entities.ContinuousFormation,System.Boolean]' and 'System.Func
2[MBSM.Core.Entities.ContinuousFormation,System.Boolean]'.
which my ContinuousFormation
is :
public class ContinuousFormation : IAuditable, IArchivable
{
// Other properties removed for clarity
public string CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }
public bool IsEdited { get; set; }
public string LastEditor { get; set; }
public DateTime LastEditDate { get; set; }
public bool? IsDeleted { get; set; }
public string? DeletedBy { get; set; }
public DateTime? DeletedOn { get; set; }
public bool ? IsArchived { get; set; }
public string ArchivedBy { get; set; }
public DateTime ? ArchivedOn { get; set; }
}
public class ContinuousFormation : IAuditable, IArchivable
{
// Other properties removed for clarity
public string CreatedBy { get; set; }
public DateTime CreatedOn { get; set; }
public bool IsEdited { get; set; }
public string LastEditor { get; set; }
public DateTime LastEditDate { get; set; }
public bool? IsDeleted { get; set; }
public string? DeletedBy { get; set; }
public DateTime? DeletedOn { get; set; }
public bool ? IsArchived { get; set; }
public string ArchivedBy { get; set; }
public DateTime ? ArchivedOn { get; set; }
}
conditions = Expression.OrElse( isArchivedNullFunc , isArchivedFalseFunc );
conditions = Expression.OrElse( isArchivedNullFunc , isArchivedFalseFunc );
conditions = Expression.OrElse( isArchivedNullCheck , isArchivedFalseCheck );
conditions = Expression.OrElse( isArchivedNullCheck , isArchivedFalseCheck );