为C#的PetaPoco组件增加一个批量更新功能(临时表模式)
总有一些数据是需要批量更新的,并且更新的字段,每个数据都不一样。
为了实现这样一个功能,写了这样一个方法:
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using NetRube.Data;
using PetaPoco;namespace NetRube.Utils
{/// <summary>/// 临时表工具类/// </summary>public class TempTableUtil{/// <summary>/// 获取字段名/// </summary>/// <typeparam name="T">数据表类</typeparam>/// <param name="colExp">表字段</param>/// <returns></returns>private static string GetColName<T>(Expression<Func<T, dynamic>> colExp) where T : IModel{var colName = "";if (colExp.Body is MemberExpression memberExpression)colName = memberExpression.Member.Name;else if (colExp.Body is UnaryExpression unaryExpression && unaryExpression.Operand is MemberExpression operandMemberExpression)colName = operandMemberExpression.Member.Name;return colName;}/// <summary>/// 获取表名与主键字段名/// </summary>/// <typeparam name="T">数据表类</typeparam>/// <param name="priColExpression">获取主键的Lambda表达式</param>/// <returns></returns>/// <exception cref="ArgumentException"></exception>private static (string, string) GetTableAndPrimaryColName<T>(Expression<Func<T, dynamic>> priColExpression) where T : IModel{T table = Activator.CreateInstance<T>();var type = table.GetType();var tableAttr = (TableNameAttribute)Attribute.GetCustomAttribute(type, typeof(TableNameAttribute));if (tableAttr == null)throw new ArgumentException("无效对象");string tableName = tableAttr.Value; //得到表名var priColName = GetColName(priColExpression); //得到主键PropertyInfo[] proInfos = table.GetType().GetProperties(); //获取所有字段foreach (var pro in proInfos){if (pro.Name.ToLower() == priColName.ToLower())priColName = pro.Name;if (!string.IsNullOrEmpty(priColName))break; //已经拿到,跳出}if (string.IsNullOrEmpty(priColName))throw new ArgumentException("无效主键字段名");return (tableName, priColName);}/// <summary>/// 获取表名与字段名/// </summary>/// <typeparam name="T">数据表类</typeparam>/// <param name="modCols">获取待修改字段的Lambda表达式,可多个</param>/// <returns></returns>/// <exception cref="ArgumentException"></exception>private static Dictionary<string, string> GetModifyColNames<T>(Dictionary<Expression<Func<T, dynamic>>, string> modCols) where T : IModel{T table = Activator.CreateInstance<T>();var type = table.GetType();var tableAttr = (TableNameAttribute)Attribute.GetCustomAttribute(type, typeof(TableNameAttribute));if (tableAttr == null)throw new ArgumentException("无效对象");string tableName = tableAttr.Value; //得到表名PropertyInfo[] proInfos = table.GetType().GetProperties(); //获取所有字段var result = new Dictionary<string, string>();foreach (var col in modCols){var modColName = GetColName(col.Key);var modColType = col.Value;foreach (var pro in proInfos){if (pro.Name.ToLower() == modColName.ToLower()){modColName = pro.Name;result.Add(modColName, modColType);break; //已经拿到,跳出}}if (string.IsNullOrEmpty(modColName))throw new ArgumentException("无效的修改字段名");}return result;}/// <summary>/// 批量更新多列字段(临时表模式)/// </summary>/// <typeparam name="T">数据表类</typeparam>/// <param name="priColExpression">主键的Lambda表达式</param>/// <param name="priColType">主键在数据表的数据类型</param>/// <param name="modColExpressions">待修改字段的Lambda表达式,可多个</param>/// <param name="db">数据库对象</param>/// <param name="dataList">用于修改的数据,必须有主键数据和待修改字段的数据</param>/// <returns></returns>public static bool BatchUpdateMutiColData<T>(Expression<Func<T, dynamic>> priColExpression, string priColType,Dictionary<Expression<Func<T, dynamic>>, string> modColExpressions,Database db, List<T> dataList) where T : IModel{//如果字典为空则直接返回if (dataList == null || dataList.Count == 0)return false;//获取表名与字段名var (tableName, priColName) = GetTableAndPrimaryColName(priColExpression);var modColNames = GetModifyColNames(modColExpressions);//创建临时表sqlvar tmpTableName = $"TempUpdateTable_{DateTime.Now.ToString("yyyyMMddHHmmss")}";var modNameTypeSql = string.Join(", ", modColNames.Select(m => m.Key + " " + m.Value));var createTempTableSql = @$"CREATE TEMPORARY TABLE {tmpTableName} ({priColName} {priColType}, {modNameTypeSql} );";//数据插入到临时表sqlvar insertTempTableSql = new StringBuilder();var modNameSql = string.Join(", ", modColNames.Select(m => m.Key));insertTempTableSql.Append($"INSERT INTO {tmpTableName} ({priColName}, {modNameSql}) VALUES ");var parameters = new List<object>();int idx = 0;foreach (var data in dataList){PropertyInfo[] proInfos = data.GetType().GetProperties(); //获取所有属性insertTempTableSql.Append($"(");foreach (var pro in proInfos){if (priColName.ToLower() == pro.Name.ToLower()) //获取主键值{var val = pro.GetValue(data);insertTempTableSql.Append($"@{idx},");parameters.Add(val); // 添加对应修改值idx++;break; //已经拿到,跳出}}foreach (var modName in modColNames){foreach (var pro in proInfos){if (modName.Key.ToLower() == pro.Name.ToLower()) //获取修改字段{var val = pro.GetValue(data);insertTempTableSql.Append($"@{idx},");parameters.Add(val); // 添加对应修改值idx++;break; //已经拿到,跳出}}}insertTempTableSql.Length--; // 移除最后的逗号insertTempTableSql.Append($"),");}insertTempTableSql.Length--;insertTempTableSql.Append(";"); // 移除最后的逗号//通过JOIN批量更新更新到主表sqlvar modNameMapSql = string.Join(", ", modColNames.Select(m => "a." + m.Key + " = t." + m.Key));var updateSql = @$"UPDATE {tableName} a JOIN {tmpTableName} t ON a.{priColName} = t.{priColName} SET {modNameMapSql};";//删除临时表sql(MySQL在会话结束时会自动删除,手动删除以确保无残留)var deleteTempTableSql = $"DROP TEMPORARY TABLE IF EXISTS {tmpTableName};";//开始执行脚本db.Execute(createTempTableSql);db.Execute(insertTempTableSql.ToString(), parameters.ToArray());db.Execute(updateSql);db.Execute(deleteTempTableSql);return true;}}
}
使用方式:
//待更新的字段
var Database = new Database(); //来自PetaPoco
var modCols = new Dictionary<Expression<Func<ProductInfo, dynamic>>, string>();
modCols.Add(a => a.SalePrice, "decimal(10,2)");
modCols.Add(a => a.Stock, "int");
//测试数据
var dataList = new List<ProductInfo>();
dataList.Add(new ProductInfo { Id = "4347_429_3150_0", SalePrice = 90.8M, Stock = 8 });
dataList.Add(new ProductInfo { Id = "4347_429_3151_0", SalePrice = 90.9M, Stock = 9 });
//更新
TempTableUtil.BatchUpdateMutiColData<ProductInfo>(a => a.Id, "varchar(50)", modCols, Database, dataList);
相关文章:
为C#的PetaPoco组件增加一个批量更新功能(临时表模式)
总有一些数据是需要批量更新的,并且更新的字段,每个数据都不一样。 为了实现这样一个功能,写了这样一个方法: using System.Linq.Expressions; using System.Reflection; using System.Text; using NetRube.Data; using PetaPoc…...
Spring实战——入门讲解
博客主页: 南来_北往 系列专栏:Spring Boot实战 Spring介绍 Spring实战的入门讲解主要涵盖了Spring框架的基本概念、核心功能以及应用场景。以下是关于Spring实战入门的具体介绍: Spring框架概述:Spring是一个轻量级的Java开发框架…...
MTK芯片机型的“工程固件” 红米note9 5G版资源预览 写入以及改写参数相关步骤解析
小米机型:小米5 小米5x 米6 米6x 米8 米9 米10系列 米11系列 米12系列 mix mix2 mix2s mix3 max max2 max3 note3 8se 9se cc9系列 米play 平板系列等分享 红米机型:红米note4 红米note4x 红米note5 红米note6 红米note7 红米note8 红米note8pro 红米s2 红米note7pro 红米…...
[Golang] Context
[Golang] Context 文章目录 [Golang] Context什么是context创建context创建根context创建context context的作用并发控制context.WithCancelcontext.WithDeadlinecontext.WithTimeoutcontext.WithValue 什么是context Golang在1.7版本中引入了一个标准库的接口context…...
【JAVA集合总结-壹】
文章目录 synchronized 的实现原理以及锁优化?ThreadLocal原理,使用注意点,应用场景有哪些?synchronized和ReentrantLock的区别?说说CountDownLatch与CyclicBarrier 区别Fork/Join框架的理解为什么我们调用start()方法…...
Mysql梳理7——分页查询
目录 7、分页查询 7.1 背景 7.2 实现规则 分页原理 7.3 使用 LIMIT 的好处 7、分页查询 7.1 背景 背景1:查询返回的记录太多了,查看起来很不方便,怎么样能够实现分页查询呢? 背景2:表里有 4 条数据,…...
智能制造与工业互联网公益联播∣企企通副总经理杨华:AI的浪潮下,未来智慧供应链迭代方向
近两年在IT圈子里面,AI毫无疑问是最火的一个词语,最近的ChatGPT、文心一言、通义千问,从千亿参数到万亿参数,再往前就是Sora文生视频异军突起... 在人工智能的浪潮下,AI之于供应链的价值体现在哪些地方?其发…...
《深度学习》—— 卷积神经网络(CNN)的简单介绍和工作原理
文章目录 一、卷积神经网络的简单介绍二、工作原理(还未写完)1.输入层2.卷积层3.池化层4.全连接层5.输出层 一、卷积神经网络的简单介绍 基本概念 定义:卷积神经网络是一种深度学习模型,通常用于图像、视频、语音等信号数据的分类和识别任务。其核心思想…...
数据结构:线性表
1、线性表概述 1.1线性表的定义 线性表(list):零个或多个数据元素的有限序列。 简单地来说,我们可以用下面这张图来描述一个线性表: 1.2 线性表的存储结构 1.2.1顺序存储结构——顺序表 顺序表是将数据全部存储到…...
Ansible PlayBook实践案例
一、PlayBook介绍 1.什么是playbook playbook 顾名思义,即剧本,现实生活中演员按照剧本表演,在 ansible 中,由被控计算机表演,进行安装,部署应用,提供对外的服务等,以及组织计算机处理各种各样…...
Tomcat后台弱口令部署war包
1.环境搭建 cd /vulhub/tomcat/tomcat8 docker-compose up -d 一键启动容器 2.访问靶场 点击Manager App tomcat8的默认用户名和密码都是tomcat进行登录 3.制作war包 先写一个js的一句话木马 然后压缩成zip压缩包 最后修改后缀名为war 4.在网站后台上传war文件 上传war文件…...
胤娲科技:DeepMind的FermiNet——带你穿越“薛定谔的早餐桌”
当AI遇上量子迷雾,FermiNet成了你的“量子导航仪” 想象一下,你早晨醒来,发现家里的厨房变成了薛定谔的实验室,你的咖啡杯和吐司同时处于“存在与不存在”的叠加态。 你伸手去拿,却不确定会不会摸到冰冷的空气或是热腾…...
迅为iTOP-STM32MP157开发板板载4G接口(选配)_千兆以太网_WIFI蓝牙模块_HDMI_CAN_RS485_LVDS接口等
迅为ITOP-STM32MP157是基于ST的STM32MP157芯片开发的一款开发平台。在STM32MP157开发平台上,我们也做了比较多的创新,其中重要的一点就是,iTOP-STM32MP157核心板电源管理采用ST全新配套研制的PMIC电源管理芯片STPMU1A。为整个系统的稳定运行提…...
Android Choreographer 监控应用 FPS
Choreographer 是 Android 提供的一个强大的工具类,用于协调动画、绘制和视图更新的时间。它的主要作用是协调应用的绘制过程,以确保流畅的用户体验。Choreographer 也可以帮助我们获取帧时间信息,从而为性能监测和优化提供重要的数据支持。 …...
关于 mybatis-plus-boot-starter 与 mybatis-spring-boot-starter 的错误
不是知道你是否 出现过这样的错误 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): 经过各种度娘,无非就是让你检查三种情况 情况一:mapper.xml没有按照传统的maven架构进行放置 情况二:mybatis的配置信…...
NLP 文本分类任务核心梳理
解决思路 分解为多个独立二分类任务将多标签分类转化为多分类问题更换 loss 直接由模型进行多标签分类 数据稀疏问题 标注更多数据,核心解决方案: 自己构造训练样本 数据增强,如使用 chatGPT 来构造数据更换模型 减少数据需求增加规则弥补…...
k8s中pod的创建过程和阶段状态
管理k8s集群 kubectl k8s中有两种用户 一种是登录的 一种是/sbin/nologin linux可以用密码登录,也可以用证书登录 k8s只能用证书登录 谁拿到这个证书,谁就可以管理集群 在k8s中,所有节点都被网络组件calico设置了路由和通信 所以pod的ip是可以…...
NSSCTF刷题篇1
js类型 [SWPUCTF 2022 新生赛]js_sign 这是一道js信息泄露的题目直接查看源码,有一个main.js文件点击之后,有一串数字和一段base64编码,解开base64编码得到这个编码为敲击码 解码在线网站:Tap Code - 许愿星 (wishingstarmoye.…...
[数据集][目标检测]棉花叶子病害检测数据集VOC+YOLO格式977张22类别
数据集格式:Pascal VOC格式YOLO格式(不包含分割路径的txt文件,仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数):977 标注数量(xml文件个数):977 标注数量(txt文件个数):977 标注类别…...
产品经理面试整理-常见面试问题
以下是一些常见的产品经理面试问题及其解答思路。这些问题涵盖了产品管理的各个方面,包括战略、执行、数据分析、用户体验、跨团队合作等。在准备这些问题时,使用结构化的回答方式(如STAR法)能够帮助你更好地表达你的观点和经验。 1. 常见产品经理面试问题 1.1 你如何定义用…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
基于距离变化能量开销动态调整的WSN低功耗拓扑控制开销算法matlab仿真
目录 1.程序功能描述 2.测试软件版本以及运行结果展示 3.核心程序 4.算法仿真参数 5.算法理论概述 6.参考文献 7.完整程序 1.程序功能描述 通过动态调整节点通信的能量开销,平衡网络负载,延长WSN生命周期。具体通过建立基于距离的能量消耗模型&am…...
【C语言练习】080. 使用C语言实现简单的数据库操作
080. 使用C语言实现简单的数据库操作 080. 使用C语言实现简单的数据库操作使用原生APIODBC接口第三方库ORM框架文件模拟1. 安装SQLite2. 示例代码:使用SQLite创建数据库、表和插入数据3. 编译和运行4. 示例运行输出:5. 注意事项6. 总结080. 使用C语言实现简单的数据库操作 在…...
【JVM面试篇】高频八股汇总——类加载和类加载器
目录 1. 讲一下类加载过程? 2. Java创建对象的过程? 3. 对象的生命周期? 4. 类加载器有哪些? 5. 双亲委派模型的作用(好处)? 6. 讲一下类的加载和双亲委派原则? 7. 双亲委派模…...
省略号和可变参数模板
本文主要介绍如何展开可变参数的参数包 1.C语言的va_list展开可变参数 #include <iostream> #include <cstdarg>void printNumbers(int count, ...) {// 声明va_list类型的变量va_list args;// 使用va_start将可变参数写入变量argsva_start(args, count);for (in…...
【C++】纯虚函数类外可以写实现吗?
1. 答案 先说答案,可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...
ArcGIS Pro+ArcGIS给你的地图加上北回归线!
今天来看ArcGIS Pro和ArcGIS中如何给制作的中国地图或者其他大范围地图加上北回归线。 我们将在ArcGIS Pro和ArcGIS中一同介绍。 1 ArcGIS Pro中设置北回归线 1、在ArcGIS Pro中初步设置好经纬格网等,设置经线、纬线都以10间隔显示。 2、需要插入背会归线…...
云原生安全实战:API网关Envoy的鉴权与限流详解
🔥「炎码工坊」技术弹药已装填! 点击关注 → 解锁工业级干货【工具实测|项目避坑|源码燃烧指南】 一、基础概念 1. API网关 作为微服务架构的统一入口,负责路由转发、安全控制、流量管理等核心功能。 2. Envoy 由Lyft开源的高性能云原生…...
前端工具库lodash与lodash-es区别详解
lodash 和 lodash-es 是同一工具库的两个不同版本,核心功能完全一致,主要区别在于模块化格式和优化方式,适合不同的开发环境。以下是详细对比: 1. 模块化格式 lodash 使用 CommonJS 模块格式(require/module.exports&a…...
k8s从入门到放弃之Pod的容器探针检测
k8s从入门到放弃之Pod的容器探针检测 在Kubernetes(简称K8s)中,容器探测是指kubelet对容器执行定期诊断的过程,以确保容器中的应用程序处于预期的状态。这些探测是保障应用健康和高可用性的重要机制。Kubernetes提供了两种种类型…...
