当前位置: 首页 > news >正文

为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组件增加一个批量更新功能(临时表模式)

总有一些数据是需要批量更新的&#xff0c;并且更新的字段&#xff0c;每个数据都不一样。 为了实现这样一个功能&#xff0c;写了这样一个方法&#xff1a; using System.Linq.Expressions; using System.Reflection; using System.Text; using NetRube.Data; using PetaPoc…...

Spring实战——入门讲解

​ 博客主页: 南来_北往 系列专栏&#xff1a;Spring Boot实战 Spring介绍 Spring实战的入门讲解主要涵盖了Spring框架的基本概念、核心功能以及应用场景。以下是关于Spring实战入门的具体介绍&#xff1a; Spring框架概述&#xff1a;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&#xf…...

【JAVA集合总结-壹】

文章目录 synchronized 的实现原理以及锁优化&#xff1f;ThreadLocal原理&#xff0c;使用注意点&#xff0c;应用场景有哪些&#xff1f;synchronized和ReentrantLock的区别&#xff1f;说说CountDownLatch与CyclicBarrier 区别Fork/Join框架的理解为什么我们调用start()方法…...

Mysql梳理7——分页查询

目录 7、分页查询 7.1 背景 7.2 实现规则 分页原理 7.3 使用 LIMIT 的好处 7、分页查询 7.1 背景 背景1&#xff1a;查询返回的记录太多了&#xff0c;查看起来很不方便&#xff0c;怎么样能够实现分页查询呢&#xff1f; 背景2&#xff1a;表里有 4 条数据&#xff0c…...

智能制造与工业互联网公益联播∣企企通副总经理杨华:AI的浪潮下,未来智慧供应链迭代方向

近两年在IT圈子里面&#xff0c;AI毫无疑问是最火的一个词语&#xff0c;最近的ChatGPT、文心一言、通义千问&#xff0c;从千亿参数到万亿参数&#xff0c;再往前就是Sora文生视频异军突起... 在人工智能的浪潮下&#xff0c;AI之于供应链的价值体现在哪些地方&#xff1f;其发…...

《深度学习》—— 卷积神经网络(CNN)的简单介绍和工作原理

文章目录 一、卷积神经网络的简单介绍二、工作原理(还未写完)1.输入层2.卷积层3.池化层4.全连接层5.输出层 一、卷积神经网络的简单介绍 基本概念 定义&#xff1a;卷积神经网络是一种深度学习模型&#xff0c;通常用于图像、视频、语音等信号数据的分类和识别任务。其核心思想…...

数据结构:线性表

1、线性表概述 1.1线性表的定义 线性表&#xff08;list&#xff09;&#xff1a;零个或多个数据元素的有限序列。 简单地来说&#xff0c;我们可以用下面这张图来描述一个线性表&#xff1a; 1.2 线性表的存储结构 1.2.1顺序存储结构——顺序表 顺序表是将数据全部存储到…...

Ansible PlayBook实践案例

一、PlayBook介绍 1.什么是playbook playbook 顾名思义&#xff0c;即剧本&#xff0c;现实生活中演员按照剧本表演&#xff0c;在 ansible 中&#xff0c;由被控计算机表演,进行安装&#xff0c;部署应用&#xff0c;提供对外的服务等&#xff0c;以及组织计算机处理各种各样…...

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遇上量子迷雾&#xff0c;FermiNet成了你的“量子导航仪” 想象一下&#xff0c;你早晨醒来&#xff0c;发现家里的厨房变成了薛定谔的实验室&#xff0c;你的咖啡杯和吐司同时处于“存在与不存在”的叠加态。 你伸手去拿&#xff0c;却不确定会不会摸到冰冷的空气或是热腾…...

迅为iTOP-STM32MP157开发板板载4G接口(选配)_千兆以太网_WIFI蓝牙模块_HDMI_CAN_RS485_LVDS接口等

迅为ITOP-STM32MP157是基于ST的STM32MP157芯片开发的一款开发平台。在STM32MP157开发平台上&#xff0c;我们也做了比较多的创新&#xff0c;其中重要的一点就是&#xff0c;iTOP-STM32MP157核心板电源管理采用ST全新配套研制的PMIC电源管理芯片STPMU1A。为整个系统的稳定运行提…...

Android Choreographer 监控应用 FPS

Choreographer 是 Android 提供的一个强大的工具类&#xff0c;用于协调动画、绘制和视图更新的时间。它的主要作用是协调应用的绘制过程&#xff0c;以确保流畅的用户体验。Choreographer 也可以帮助我们获取帧时间信息&#xff0c;从而为性能监测和优化提供重要的数据支持。 …...

关于 mybatis-plus-boot-starter 与 mybatis-spring-boot-starter 的错误

不是知道你是否 出现过这样的错误 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): 经过各种度娘&#xff0c;无非就是让你检查三种情况 情况一&#xff1a;mapper.xml没有按照传统的maven架构进行放置 情况二&#xff1a;mybatis的配置信…...

NLP 文本分类任务核心梳理

解决思路 分解为多个独立二分类任务将多标签分类转化为多分类问题更换 loss 直接由模型进行多标签分类 数据稀疏问题 标注更多数据&#xff0c;核心解决方案&#xff1a; 自己构造训练样本 数据增强&#xff0c;如使用 chatGPT 来构造数据更换模型 减少数据需求增加规则弥补…...

k8s中pod的创建过程和阶段状态

管理k8s集群 kubectl k8s中有两种用户 一种是登录的 一种是/sbin/nologin linux可以用密码登录&#xff0c;也可以用证书登录 k8s只能用证书登录 谁拿到这个证书&#xff0c;谁就可以管理集群 在k8s中&#xff0c;所有节点都被网络组件calico设置了路由和通信 所以pod的ip是可以…...

NSSCTF刷题篇1

js类型 [SWPUCTF 2022 新生赛]js_sign 这是一道js信息泄露的题目直接查看源码&#xff0c;有一个main.js文件点击之后&#xff0c;有一串数字和一段base64编码&#xff0c;解开base64编码得到这个编码为敲击码 解码在线网站&#xff1a;Tap Code - 许愿星 (wishingstarmoye.…...

[数据集][目标检测]棉花叶子病害检测数据集VOC+YOLO格式977张22类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;977 标注数量(xml文件个数)&#xff1a;977 标注数量(txt文件个数)&#xff1a;977 标注类别…...

产品经理面试整理-常见面试问题

以下是一些常见的产品经理面试问题及其解答思路。这些问题涵盖了产品管理的各个方面,包括战略、执行、数据分析、用户体验、跨团队合作等。在准备这些问题时,使用结构化的回答方式(如STAR法)能够帮助你更好地表达你的观点和经验。 1. 常见产品经理面试问题 1.1 你如何定义用…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

Zustand 状态管理库:极简而强大的解决方案

Zustand 是一个轻量级、快速和可扩展的状态管理库&#xff0c;特别适合 React 应用。它以简洁的 API 和高效的性能解决了 Redux 等状态管理方案中的繁琐问题。 核心优势对比 基本使用指南 1. 创建 Store // store.js import create from zustandconst useStore create((set)…...

【WiFi帧结构】

文章目录 帧结构MAC头部管理帧 帧结构 Wi-Fi的帧分为三部分组成&#xff1a;MAC头部frame bodyFCS&#xff0c;其中MAC是固定格式的&#xff0c;frame body是可变长度。 MAC头部有frame control&#xff0c;duration&#xff0c;address1&#xff0c;address2&#xff0c;addre…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

vscode(仍待补充)

写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh&#xff1f; debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

Linux云原生安全:零信任架构与机密计算

Linux云原生安全&#xff1a;零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言&#xff1a;云原生安全的范式革命 随着云原生技术的普及&#xff0c;安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测&#xff0c;到2025年&#xff0c;零信任架构将成为超…...

反射获取方法和属性

Java反射获取方法 在Java中&#xff0c;反射&#xff08;Reflection&#xff09;是一种强大的机制&#xff0c;允许程序在运行时访问和操作类的内部属性和方法。通过反射&#xff0c;可以动态地创建对象、调用方法、改变属性值&#xff0c;这在很多Java框架中如Spring和Hiberna…...

【HTTP三个基础问题】

面试官您好&#xff01;HTTP是超文本传输协议&#xff0c;是互联网上客户端和服务器之间传输超文本数据&#xff08;比如文字、图片、音频、视频等&#xff09;的核心协议&#xff0c;当前互联网应用最广泛的版本是HTTP1.1&#xff0c;它基于经典的C/S模型&#xff0c;也就是客…...

网络编程(UDP编程)

思维导图 UDP基础编程&#xff08;单播&#xff09; 1.流程图 服务器&#xff1a;短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...