1. 程式人生 > 其它 >EF Core 5.0 使用過濾器進行查詢攔截的方法和示例,以及一些備忘

EF Core 5.0 使用過濾器進行查詢攔截的方法和示例,以及一些備忘

1、查詢攔截和結果替換(取消執行)的示例:

    /// <summary>
    /// 查詢攔截器
    /// </summary>
    public class ShardingDbCommandInterceptor : Microsoft.EntityFrameworkCore.Diagnostics.DbCommandInterceptor
    {
        /// <summary>
        /// 在這裡做攔截、判斷、取消查詢、賦值操作
        /// </summary>
        /// <param name="command"></param>
        /// <param name="eventData"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public override InterceptionResult<DbDataReader> ReaderExecuting(DbCommand command, CommandEventData eventData, InterceptionResult<DbDataReader> result)
        {
            Console.WriteLine(command.CommandText);

            //取引數列表
            foreach (System.Data.Common.DbParameter p in command.Parameters)
            {
                Console.WriteLine($"    引數名:{p.ParameterName},引數值:{p.Value},引數方向:{p.Direction}");
            }

            Console.WriteLine($"當前資料庫名稱:{command.Connection.Database},資料來源為:{command.Connection.DataSource},伺服器版本:{command.Connection.ServerVersion}");


            //定義一個Table,如果執行下面的程式碼,即攔截成功,自動被取消執行
            var dt = new System.Data.DataTable();
            dt.Columns.Add("Id", typeof(string));
            dt.Columns.Add("AccountId", typeof(Int64));
            var rs = dt.NewRow();
            rs["Id"] = Guid.NewGuid().ToString();
            rs["AccountId"] = 1234;
            dt.Rows.Add(rs);
            result = InterceptionResult<DbDataReader>.SuppressWithResult(dt.CreateDataReader());

            return result;
        }

        /// <summary>
        /// 執行完畢後會返回
        /// </summary>
        /// <param name="command"></param>
        /// <param name="eventData"></param>
        /// <param name="result"></param>
        /// <returns></returns>
        public override DbDataReader ReaderExecuted(DbCommand command, CommandExecutedEventData eventData, DbDataReader result)
        {
            return base.ReaderExecuted(command, eventData, result);
        }
    }

  2、註冊過濾器的程式碼:

    /// <summary>
    /// 多庫、分庫、分表、Redis自動化 上下文物件
    /// </summary>
    public class DataContexts:DbContext
    {

        public DataContexts() : base()
        {
            
        }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.UseSqlServer("Data Source=192.168.3.162;Initial Catalog=hmt_report;Persist Security Info=True;User ID=sa;Password=123").AddInterceptors(new ShardingDbCommandInterceptor());
        }

        /// <summary>
        /// 重寫該方法,用於實現批量生成SQL進行批量操作,例如批量插入,以及做Redis的更新
        /// </summary>
        /// <returns></returns>
        public override int SaveChanges()
        {
            return base.SaveChanges();
        }

        /// <summary>
        /// 聲明當前資料庫上下文使用的全部模型和反射欄位列表
        /// </summary>
        public static Dictionary<string, System.Reflection.PropertyInfo[]> modelProperties { get; set; } = new Dictionary<string, System.Reflection.PropertyInfo[]>();


        /// <summary>
        /// 表 AudienceAccountReport_DataOnDay
        /// </summary>
        public DbSet<ShardingEntityFramework.DataModels.AudienceAccountReport_DataOnDay> AudienceAccountReport_DataOnDay { get; set; }

    }

  EF Framework也是一樣,有了該攔截器後,可以擴充套件為Redis自動化,只要識別出來查詢語句中的目標表,以及鍵欄位有具體值,就可以直接從redis裡取,然後,讀寫分離也是基於攔截器來改變資料庫連線字串,就可以實現讀寫的分離,另外,要自動更新redis或者讀寫分離,則通過覆蓋重寫

SaveChanges 函式來實現,同時,分庫分表也涉及到這個地方,實際上,特別是分表稍為麻煩一些,分表因為有多種不同規則,分表方法,核心難點是解析SQL裡的條件,得出表名和對不同表的where欄位及值,進行做實際表的替換,來實現自動化分表哦。

僅僅是思路。