当前位置: 首页 > 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);

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 【贪心算法】贪心算法二
  • Linux驱动开发 ——架构体系
  • C++编译环境(IDE)推荐及安装
  • Python 单元测试:深入理解与实战应用20240919
  • 【Ubuntu】ubuntu如何使用ufw(Uncomplicated Firewall)管理防火墙?一文带你学会!
  • Java笔试面试题AI答之设计模式(1)
  • Ceph容器化最佳实践_超融合架构
  • [Redis][Hash]详细讲解
  • 计算一个矩阵的逆矩阵的方法
  • C++11中引入的thread
  • c语言中“sizeof”和“strlen”的区别
  • linux atomic 原子变量操作
  • 【数列求值 / B】
  • Parallels Desktop 20(Mac虚拟机) v20.0.0 for Mac 最新破解版(支持M系列)
  • 【tomcat】tomcat学习笔记
  • “Material Design”设计规范在 ComponentOne For WinForm 的全新尝试!
  • 【刷算法】求1+2+3+...+n
  • Bootstrap JS插件Alert源码分析
  • C学习-枚举(九)
  • ECMAScript入门(七)--Module语法
  • ES6核心特性
  • Facebook AccountKit 接入的坑点
  • input的行数自动增减
  • java架构面试锦集:开源框架+并发+数据结构+大企必备面试题
  • Koa2 之文件上传下载
  • mac修复ab及siege安装
  • Mithril.js 入门介绍
  • nginx(二):进阶配置介绍--rewrite用法,压缩,https虚拟主机等
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • Python学习笔记 字符串拼接
  • React 快速上手 - 06 容器组件、展示组件、操作组件
  • SQL 难点解决:记录的引用
  • Vue.js源码(2):初探List Rendering
  • Work@Alibaba 阿里巴巴的企业应用构建之路
  • 前端每日实战:70# 视频演示如何用纯 CSS 创作一只徘徊的果冻怪兽
  • 吐槽Javascript系列二:数组中的splice和slice方法
  • 线上 python http server profile 实践
  • 一些基于React、Vue、Node.js、MongoDB技术栈的实践项目
  • 远离DoS攻击 Windows Server 2016发布DNS政策
  • Oracle Portal 11g Diagnostics using Remote Diagnostic Agent (RDA) [ID 1059805.
  • ionic入门之数据绑定显示-1
  • ​渐进式Web应用PWA的未来
  • ​人工智能之父图灵诞辰纪念日,一起来看最受读者欢迎的AI技术好书
  • #Ubuntu(修改root信息)
  • #前后端分离# 头条发布系统
  • #我与Java虚拟机的故事#连载10: 如何在阿里、腾讯、百度、及字节跳动等公司面试中脱颖而出...
  • (AtCoder Beginner Contest 340) -- F - S = 1 -- 题解
  • (Charles)如何抓取手机http的报文
  • (k8s)kubernetes 部署Promehteus学习之路
  • (k8s中)docker netty OOM问题记录
  • (附源码)c#+winform实现远程开机(广域网可用)
  • (附源码)springboot宠物管理系统 毕业设计 121654
  • (附源码)ssm码农论坛 毕业设计 231126
  • (蓝桥杯每日一题)love
  • (六)激光线扫描-三维重建