zoukankan      html  css  js  c++  java
  • EF Core – QueryFilter & Interception

    主要参考

    Global Query Filters

    Interceptors

    QueryFilter

    QueryFilter 就是默认过滤, 非常适合用来做 Soft Delete

    builder.HasQueryFilter(e => EF.Property<DateTimeOffset?>(e, "DateDeleted") == null);

    设置这个以后, 一般的 query 语句就拿不到 deleted 的 row 了

    如果想获取 deleted row 那么就需要通过 IgnoreQueryFilters 来 by pass 它.

    blogs = db.Blogs
        .Include(b => b.Posts)
        .IgnoreQueryFilters()
        .ToList();

    Interception

    Interception 也适合用来做 Soft Delete 或者简单的 Audit Trail

    但是还有一个更简单的做法是直接 override SaveChangesAsync 方法

    去 DbContext class

    public override Task<int> SaveChangesAsync(CancellationToken cancellationToken = default)
    {
        foreach (var entry in ChangeTracker.Entries())
        {
            if (entry.State == EntityState.Added)
            {
                        
            }
            else if (entry.State == EntityState.Modified)
            {
    
            }
            else if (entry.State == EntityState.Deleted)
            {
    
            }
            var tableName = entry.Metadata.GetTableName();
    
            foreach (var property in entry.Properties)
            {
                var isModified = property.IsModified;
                var originalValue = property.OriginalValue;
                var currentValue = property.CurrentValue;
                var metadata = property.Metadata;
            }
        }
        return base.SaveChangesAsync(cancellationToken);
    }

    获取 Entry 资料, 然后修改 Entry 就可以操控最终 save 的结构了. (比如把 Deleted 换成 Modified)

    创建一个 Interceptor (我这里用 SaveChangesInterceptor 举例)

    public class SoftDeleteInterception : SaveChangesInterceptor
    {
        public override ValueTask<InterceptionResult<int>> SavingChangesAsync(DbContextEventData eventData, InterceptionResult<int> result, CancellationToken cancellationToken = default)
        {
            var entities = eventData.Context!.ChangeTracker.Entries();
            return new ValueTask<InterceptionResult<int>>(result);
        }
    }

    注: SavingChangesAsync 是 before SQL, SavedChangesAsync 是 after success SQL, FailedChangesAsync 是 after fail SQL.

    在 DbContext class register 这个 interceptor

    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder) => optionsBuilder.AddInterceptors(new SoftDeleteInterception());

    Change State in SaveChanges

    看注释, 有些逻辑和平时会不同,比如 set value 时, 不会 update IsModified (但 generate 出来的语句还是有的, 我想可能 EF 最后还会再对比一次吧...懒惰去研究了)

    foreach (var entry in eventData.Context!.ChangeTracker.Entries())
    {
        var entityType = entry.Entity.GetType();
        if (entityType.FullName == "TestEFCore.Product")
        {
            entry.State = EntityState.Unchanged; // if change to modified then all properties will become IsModified 
            typeof(Product).GetProperty("Name")!.SetValue(entry.Entity, "New Value"); // current value 会 update, but IsModified 依然是 false
            entry.Property("DateDeleted").CurrentValue = DateTimeOffset.Now;
            entry.Property("DateDeleted").IsModified = true; // will update entry.State to modified
            foreach (var p in entry.Properties)
            {
                var isModified = p.IsModified;
            }
            var state = entry.State;
        }
    }

    Dependency Injection inside Interceptor

    参考:

    Ability to register IInterceptor without an IDbContextOptionsExtension

    A better way of resolving EF Core interceptors with dependency injection

  • 相关阅读:
    Centos7上安装docker
    docker部署mysql5.6.40
    centos7上部署spring boot并保存日志
    [转载]Ocelot简易教程(一)Ocelot是什么
    浅谈Surging服务引擎中的RabbitMQ组件和容器化部署
    [转载]Surging教学视频资源汇总
    [转载]netcore 使用surging框架发布到docker
    [转载]Surging 分布式微服务框架使用入门
    [转载]Surging Demo 项目之一
    [转载]剥析surging的架构思想
  • 原文地址:https://www.cnblogs.com/keatkeat/p/15427088.html
Copyright © 2011-2022 走看看