Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
885 views
in Technique[技术] by (71.8m points)

c# - Using Global Query Filters for all entities

I have recently found global filters, which is great because I have been tasked with implementing soft deletes in my applicaiton. Currently I have done this:

// Query filters https://docs.microsoft.com/en-us/ef/core/querying/filters
modelBuilder.Entity<Address>().HasQueryFilter(m => !m.Deleted);
modelBuilder.Entity<Attribute>().HasQueryFilter(m => !m.Deleted);
modelBuilder.Entity<Brand>().HasQueryFilter(m => !m.Deleted);
modelBuilder.Entity<BrandAddress>().HasQueryFilter(m => !m.Deleted);
modelBuilder.Entity<BrandCategory>().HasQueryFilter(m => !m.Deleted);
modelBuilder.Entity<Category>().HasQueryFilter(m => !m.Deleted);
// many more entity types....

All the entities inherit a BaseModel which looks like this:

public class BaseModel
{
    public Guid CreatedBy { get; set; }
    public Guid UpdatedBy { get; set; }
    public DateTime DateCreated { get; set; }
    public DateTime DateUpdated { get; set; }
    public bool Deleted { get; set; }
}

Is it possible to add the query filter for any class that inherits the BaseModel? Something like:

modelBuilder.Entity<BaseModel>().HasQueryFilter(m => !m.Deleted);

So I don't forget (at a later date) to add the query filter for models I add?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

For the latest EF Core version (should work for 3.0 also, for earlier versions expression replacement should be handled manually, see ReplacingExpressionVisitor call) you can automate it using some reflection (minimal amount of it), expression trees and IMutableModel.GetEntityTypes in your OnModelCreating method. Something like this should work:

// define your filter expression tree
Expression<Func<BaseModel, bool>> filterExpr = bm => !bm.Deleted;
foreach (var mutableEntityType in modelBuilder.Model.GetEntityTypes())
{
    // check if current entity type is child of BaseModel
    if (mutableEntityType.ClrType.IsAssignableTo(typeof(BaseModel)))
    {
        // modify expression to handle correct child type
        var parameter = Expression.Parameter(mutableEntityType.ClrType);
        var body = ReplacingExpressionVisitor.Replace(filterExpr.Parameters.First(), parameter, filterExpr.Body);
        var lambdaExpression = Expression.Lambda(body, parameter);

        // set filter
        mutableEntityType.SetQueryFilter(lambdaExpression);
    }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

57.0k users

...