AVt天堂网 手机版,亚洲va久久久噜噜噜久久4399,天天综合亚洲色在线精品,亚洲一级Av无码毛片久久精品

當前位置:首頁 > 科技  > 軟件

如何校驗內存數據的一致性,DynamicExpresso 算是幫上大忙了

來源: 責編: 時間:2023-10-10 18:31:44 222觀看
導讀一:背景1. 講故事記的在上一家公司做全內存項目的時候,因為一些關鍵表會在程序 startup 的時候全量灌入到內存中,但隨著時間的推移,內存和數據庫的同步偶爾會出現數據差異的情況,伴隨著就是運營那邊報過來的 bug,檢查數據庫

一:背景

1. 講故事

記的在上一家公司做全內存項目的時候,因為一些關鍵表會在程序 startup 的時候全量灌入到內存中,但隨著時間的推移,內存和數據庫的同步偶爾會出現數據差異的情況,伴隨著就是運營那邊報過來的 bug,檢查數據庫的數據完整性很簡單,直接寫一些 sql 驗證一下就好了,但校驗內存中的數據就非常麻煩了,因為你不能像寫 sql 一樣直接去查生產中的內存集合,那怎么辦呢?為了方便演示問題,先上一段演示代碼:XVz28資訊網——每日最新資訊28at.com

class Program    {        static void Main(string[] args)        {            var tradeList = new List<Trade>()            {                new Trade(){TradeID=1, TradeTitle="交易1", Created=Convert.ToDateTime("2020/8/1"), CustomerID=1},                new Trade(){TradeID=2, TradeTitle="交易2", Created=Convert.ToDateTime("2020/8/5"),CustomerID=2},                new Trade(){TradeID=3, TradeTitle="交易3", Created=Convert.ToDateTime("2020/8/10"), CustomerID=3}            };        }    }    class Trade    {        public int TradeID { get; set; }        public string TradeTitle { get; set; }        public DateTime Created { get; set; }        public int CustomerID { get; set; }    }

上面的 tradeList 就是內存中的集合,現在有一個問題,我想查詢一下 trade 表中 CustomerID in (1,2,10) && Created <= '2020-08-01' 的記錄是否和內存中的 tradelist 一致。XVz28資訊網——每日最新資訊28at.com

用 sql 驗證太簡單了,直接在查詢分析器里面寫一下sql 搞定,如下圖:XVz28資訊網——每日最新資訊28at.com

圖片圖片XVz28資訊網——每日最新資訊28at.com

那在 UI 上 怎么驗證呢?XVz28資訊網——每日最新資訊28at.com

二:尋找解決方法

1. 在UI上自定義高級查詢

這個也是大家最容易想到的,使用多個 if 疊加查詢條件,如下代碼所示:XVz28資訊網——每日最新資訊28at.com

static void Main(string[] args)        {            var tradeList = new List<Trade>()            {                new Trade(){TradeID=1, TradeTitle="交易1", Created=Convert.ToDateTime("2020/8/1"), CustomerID=1},                new Trade(){TradeID=2, TradeTitle="交易2", Created=Convert.ToDateTime("2020/8/5"),CustomerID=2},                new Trade(){TradeID=3, TradeTitle="交易3", Created=Convert.ToDateTime("2020/8/10"), CustomerID=3}            };            IEnumerable<Trade> query = tradeList;            //UI            var queryCustomerIDList = new List<int>() { 1, 2, 10};            var queryCreated = "2020-08-01";            if (queryCustomerIDList.Count > 0)            {                query = query.Where(m => queryCustomerIDList.Contains(m.CustomerID));            }            if (string.IsNullOrEmpty(queryCreated))            {                query = query.Where(m => m.Created <= Convert.ToDateTime(queryCreated));            }            //最后的結果            var list = query.ToList();        }

圖片圖片XVz28資訊網——每日最新資訊28at.com

問題貌似是可以解決,但是這種用 if 疊加的方式不覺得太不靈活了嗎?如果客戶心情不好,又來了一個 TradeID between 1 and 10 的篩選條件,那上面的代碼是不是還得加一個 TradeID 的判斷 ?太麻煩了,還得繼續尋找更靈活的姿勢。XVz28資訊網——每日最新資訊28at.com

2. 使用DataTable

哈哈,大家看到 DataTable 是不是有一點懵逼,可不要小瞧這玩意,人家可是直接支持 sql 查詢的哦,這靈活性不容小覷哈,上一段代碼說話:XVz28資訊網——每日最新資訊28at.com

static void Main(string[] args)        {            var tradeList = new List<Trade>()            {                new Trade(){TradeID=1, TradeTitle="交易1", Created=Convert.ToDateTime("2020/8/1"), CustomerID=1},                new Trade(){TradeID=2, TradeTitle="交易2", Created=Convert.ToDateTime("2020/8/5"),CustomerID=1},                new Trade(){TradeID=3, TradeTitle="交易3", Created=Convert.ToDateTime("2020/8/10"), CustomerID=3}            };            var table = CopyToDataTable(tradeList);            var query = table.Select("CustomerID in (1,2,10) and Created <= '2020-08-01' and TradeID >= 1 and TradeID <= 10")                            .Select(m => new Trade()                            {                                TradeID = Convert.ToInt32(m[0]),                                TradeTitle = Convert.ToString(m[1]),                                Created = Convert.ToDateTime(m[2]),                                CustomerID = Convert.ToInt32(3)                            }).ToList();        }        public static DataTable CopyToDataTable<T>(IEnumerable<T> array)        {            var ret = new DataTable();            foreach (PropertyDescriptor dp in TypeDescriptor.GetProperties(typeof(T)))                ret.Columns.Add(dp.Name);            foreach (T item in array)            {                var Row = ret.NewRow();                foreach (PropertyDescriptor dp in TypeDescriptor.GetProperties(typeof(T)))                    Row[dp.Name] = dp.GetValue(item);                ret.Rows.Add(Row);            }            return ret;        }

圖片圖片XVz28資訊網——每日最新資訊28at.com

是不是很強大,直接將文本化的 sql 塞入到 DataTable 中,你想什么樣的查詢你就寫什么樣的 sql 就 ok 啦,當然,理論歸理論,在我的場景中肯定是不會這么玩的,畢竟內存中的 trade 有上千萬行,轉成 DataTable 不是給自己挖坑嘛,那有沒有其他的方式呢?XVz28資訊網——每日最新資訊28at.com

3. 使用 表達式樹 (ExpressionTree)

我想很多人看到 表達式樹 都會退避三舍,雖然這玩意很強大,但是太復雜了,它會將你的查詢語句拆解成樹中的節點從而構建一棵非常復雜的樹結構,其實 DataTable 對 sql語句的解析也是在內存中構建了一棵解析樹,所以這玩意太反人類了,比如你要構建 i > 5 的查詢,你需要下面這樣的硬編碼,這還是非常簡單的哈,復雜的會讓你吐血。XVz28資訊網——每日最新資訊28at.com

ParameterExpression param = Expression.Parameter(typeof(int), "i");            ConstantExpression constExp = Expression.Constant(5, typeof(int));            BinaryExpression greaterThan = Expression.GreaterThan(param, constExp);            Expression<Func<int, bool>> f = Expression.Lambda<Func<int, bool>>(greaterThan, param);            Func<int, bool> mydelegate = f.Compile();            Console.WriteLine(mydelegate(5));

圖片圖片XVz28資訊網——每日最新資訊28at.com

從圖中可以看到,5>5 = False 是沒有問題的,既然表達式樹是可以解決類似這樣的場景,聰明的你應該會想到,開源社區是否又類似封裝好的 ExpressionTree 開發包呢?說實話,還真有。。。XVz28資訊網——每日最新資訊28at.com

4. DynamicExpresso 開發工具包

開源大法好,github地址:https://github.com/davideicardi/DynamicExpresso , 這玩意實現了 將文本化的 C# 語句 動態轉換成 delegate,這句話是什么意思呢?大家可以看一下這張圖:XVz28資訊網——每日最新資訊28at.com

圖片圖片XVz28資訊網——每日最新資訊28at.com

從上圖可以看到,你可以 寫一些文本化的 C# 語句,然后經過 DynamicExpresso 處理后轉換成了可執行 delegate,如果你沒看懂,我用代碼表示一下,如下圖:XVz28資訊網——每日最新資訊28at.com

圖片XVz28資訊網——每日最新資訊28at.com

其中: 30 = 5 * 8 / 2 + 10 ,重點在于這里的 數學表達式 是文本的,有了這個思路,那我是不是也可以將 tradeList 的查詢條件文本化表示,如下代碼:XVz28資訊網——每日最新資訊28at.com

var interpreter = new Interpreter();            interpreter.Reference(typeof(System.Linq.Enumerable));            interpreter.SetVariable("arr", new int[] { 1, 2, 10 });            string whereExpression = "(trade.CustomerID == 1 || trade.CustomerID==2 || trade.CustomerID==10) && " +                                     "trade.Created <= Convert.ToDateTime(/"2020-08-01/") &&" +                                     "trade.TradeID >= 1 && " +                                     "trade.TradeID <=10";            Func<Trade, bool> queryFunc = interpreter.ParseAsDelegate<Func<Trade, bool>>(whereExpression, "trade");            var list = tradeList.Where(queryFunc).ToList();            var i = Enumerable.Contains(new int[] { 1, 2, 3 }, 3);

圖片圖片XVz28資訊網——每日最新資訊28at.com

問題搞定,還是比較完美的

本文鏈接:http://www.tebozhan.com/showinfo-26-12730-0.html如何校驗內存數據的一致性,DynamicExpresso 算是幫上大忙了

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 構建第一個GraalVM應用鏡像,體驗毫秒級極速啟動!

下一篇: 使用Python分析時序數據集中的缺失數據

標簽:
  • 熱門焦點
Top