当前位置:首页 > 科技  > 软件

如何校验内存数据的一致性,DynamicExpresso 算是帮上大忙了

来源: 责编: 时间:2023-10-10 18:31:44 364观看
导读一:背景1. 讲故事记的在上一家公司做全内存项目的时候,因为一些关键表会在程序 startup 的时候全量灌入到内存中,但随着时间的推移,内存和数据库的同步偶尔会出现数据差异的情况,伴随着就是运营那边报过来的 bug,检查数据库

一:背景

1. 讲故事

记的在上一家公司做全内存项目的时候,因为一些关键表会在程序 startup 的时候全量灌入到内存中,但随着时间的推移,内存和数据库的同步偶尔会出现数据差异的情况,伴随着就是运营那边报过来的 bug,检查数据库的数据完整性很简单,直接写一些 sql 验证一下就好了,但校验内存中的数据就非常麻烦了,因为你不能像写 sql 一样直接去查生产中的内存集合,那怎么办呢?为了方便演示问题,先上一段演示代码:LLN28资讯网——每日最新资讯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 一致。LLN28资讯网——每日最新资讯28at.com

用 sql 验证太简单了,直接在查询分析器里面写一下sql 搞定,如下图:LLN28资讯网——每日最新资讯28at.com

图片图片LLN28资讯网——每日最新资讯28at.com

那在 UI 上 怎么验证呢?LLN28资讯网——每日最新资讯28at.com

二:寻找解决方法

1. 在UI上自定义高级查询

这个也是大家最容易想到的,使用多个 if 叠加查询条件,如下代码所示:LLN28资讯网——每日最新资讯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();        }

图片图片LLN28资讯网——每日最新资讯28at.com

问题貌似是可以解决,但是这种用 if 叠加的方式不觉得太不灵活了吗?如果客户心情不好,又来了一个 TradeID between 1 and 10 的筛选条件,那上面的代码是不是还得加一个 TradeID 的判断 ?太麻烦了,还得继续寻找更灵活的姿势。LLN28资讯网——每日最新资讯28at.com

2. 使用DataTable

哈哈,大家看到 DataTable 是不是有一点懵逼,可不要小瞧这玩意,人家可是直接支持 sql 查询的哦,这灵活性不容小觑哈,上一段代码说话:LLN28资讯网——每日最新资讯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;        }

图片图片LLN28资讯网——每日最新资讯28at.com

是不是很强大,直接将文本化的 sql 塞入到 DataTable 中,你想什么样的查询你就写什么样的 sql 就 ok 啦,当然,理论归理论,在我的场景中肯定是不会这么玩的,毕竟内存中的 trade 有上千万行,转成 DataTable 不是给自己挖坑嘛,那有没有其他的方式呢?LLN28资讯网——每日最新资讯28at.com

3. 使用 表达式树 (ExpressionTree)

我想很多人看到 表达式树 都会退避三舍,虽然这玩意很强大,但是太复杂了,它会将你的查询语句拆解成树中的节点从而构建一棵非常复杂的树结构,其实 DataTable 对 sql语句的解析也是在内存中构建了一棵解析树,所以这玩意太反人类了,比如你要构建 i > 5 的查询,你需要下面这样的硬编码,这还是非常简单的哈,复杂的会让你吐血。LLN28资讯网——每日最新资讯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));

图片图片LLN28资讯网——每日最新资讯28at.com

从图中可以看到,5>5 = False 是没有问题的,既然表达式树是可以解决类似这样的场景,聪明的你应该会想到,开源社区是否又类似封装好的 ExpressionTree 开发包呢?说实话,还真有。。。LLN28资讯网——每日最新资讯28at.com

4. DynamicExpresso 开发工具包

开源大法好,github地址:https://github.com/davideicardi/DynamicExpresso , 这玩意实现了 将文本化的 C# 语句 动态转换成 delegate,这句话是什么意思呢?大家可以看一下这张图:LLN28资讯网——每日最新资讯28at.com

图片图片LLN28资讯网——每日最新资讯28at.com

从上图可以看到,你可以 写一些文本化的 C# 语句,然后经过 DynamicExpresso 处理后转换成了可执行 delegate,如果你没看懂,我用代码表示一下,如下图:LLN28资讯网——每日最新资讯28at.com

图片LLN28资讯网——每日最新资讯28at.com

其中: 30 = 5 * 8 / 2 + 10 ,重点在于这里的 数学表达式 是文本的,有了这个思路,那我是不是也可以将 tradeList 的查询条件文本化表示,如下代码:LLN28资讯网——每日最新资讯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);

图片图片LLN28资讯网——每日最新资讯28at.com

问题搞定,还是比较完美的

本文链接:http://www.28at.com/showinfo-26-12730-0.html如何校验内存数据的一致性,DynamicExpresso 算是帮上大忙了

声明:本网页内容旨在传播知识,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。邮件:2376512515@qq.com

上一篇: 构建第一个GraalVM应用镜像,体验毫秒级极速启动!

下一篇: 使用Python分析时序数据集中的缺失数据

标签:
  • 热门焦点
  • K60 Pro官方停产 第三方瞬间涨价

    虽然没有官方宣布,但Redmi的一些高管也已经透露了,Redmi K60 Pro已经停产且不会补货,这一切都是为了即将到来的K60 Ultra铺路,属于厂家的正常操作。但有意思的是该机在停产之后
  • 7月安卓手机性价比榜:努比亚+红魔两款新机入榜

    7月登场的新机有努比亚Z50S Pro和红魔8S Pro,除了三星之外目前唯二的两款搭载超频版骁龙8Gen2处理器的产品,而且努比亚和红魔也一贯有着不错的性价比,所以在本次的性价比榜单
  • 5月iOS设备好评榜:iPhone 14仅排第43?

    来到新的一月,安兔兔的各个榜单又重新汇总了数据,像安卓阵营的榜单都有着比较大的变动,不过iOS由于设备的更新换代并没有那么快,所以相对来说变化并不大,特别是iOS好评榜,老款设
  • JavaScript学习 -AES加密算法

    引言在当今数字化时代,前端应用程序扮演着重要角色,用户的敏感数据经常在前端进行加密和解密操作。然而,这样的操作在网络传输和存储中可能会受到恶意攻击的威胁。为了确保数据
  • ESG的面子与里子

    来源 | 光子星球撰文 | 吴坤谚编辑 | 吴先之三伏大幕拉起,各地高温预警不绝,但处于厄尔尼诺大&ldquo;烤&rdquo;之下的除了众生,还有各大企业发布的ESG报告。ESG是&ldquo;环境保
  • 三星显示已开始为AR设备研发硅基LED微显示屏

    7月18日消息,据外媒报道,随着苹果首款头显产品Vision Pro在6月份正式推出,AR/VR/MR等头显产品也就将成为各大公司下一个重要的竞争领域,对显示屏这一关
  • iQOO 11S评测:行业唯一的200W标准版旗舰

    【Techweb评测】去年底,iQOO推出了“电竞旗舰”iQOO 11系列,作为一款性能强机,该机不仅全球首发2K 144Hz E6全感屏,搭载了第二代骁龙8平台及144Hz电竞
  • 英特尔Xe HPG游戏显卡:拥有512EU,单风扇版本

    据10 月 30 日外媒 TheVerge 消息报道,英特尔 Xe HPG Arc Alchemist 的正面实被曝光,不仅拥有 512 EU 版显卡,还拥有 128EU 的单风扇版本。另外,这款显卡 PCB
  • 荣耀Magic4 至臻版 首创智慧隐私通话 强劲影音系统

    2022年第一季度临近尾声,在该季度内,许多品牌陆续发布自己的最新产品,让大家从全新的角度来了解当今的手机技术。手机是电子设备中,更新迭代十分迅速的一款产品,基
Top