一、驱动。使用Oracle.ManagedDataAccess.Client

二、原理。利用OracleCommand的ArrayBindCount属性设置批量大小。

三、实现

函数使用的实体是efcore生成的实体,其字段命名法是帕斯卡命名法。

1.辅助函数

public static DataTable ToDataTable<T>(List<T> items)
{
DataTable dataTable = new DataTable(typeof(T).Name); // 获取所有属性
var properties = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance); foreach (var prop in properties)
{
// 添加DataTable的列,列名为属性名
dataTable.Columns.Add(prop.Name, Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType);
} foreach (var item in items)
{
var values = new object[properties.Length];
for (int i = 0; i < properties.Length; i++)
{
// 通过反射获取属性值
values[i] = properties[i].GetValue(item, null);
}
dataTable.Rows.Add(values);
} return dataTable;
} private static OracleDbType GetOracleType(Type type)
{
// 如果类型是可空类型,获取基础类型
if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
type = Nullable.GetUnderlyingType(type);
}
// 添加更多类型的映射,以适应您的特定需求
if (type == typeof(int))
{
return OracleDbType.Int32;
}
else if (type == typeof(string))
{
return OracleDbType.Varchar2;
}
else if (type == typeof(DateTime))
{
return OracleDbType.Date;
}
else if (type == typeof(decimal))
{
return OracleDbType.Decimal;
}
// 如果您有其他类型的映射需求,请在此处添加更多条件 // 默认情况下返回一个通用的值
return OracleDbType.Varchar2; // 或者您认为合适的默认类型
} private static string ConvertPascalToSnakeCase(string input)
{
if (string.IsNullOrEmpty(input))
{
return input;
} string snakeCase = char.ToUpper(input[0]).ToString(); // 将首字母大写 for (int i = 1; i < input.Length; i++)
{
char currentChar = input[i];
if (char.IsUpper(currentChar))
{
// 如果当前字符是大写字母,添加下划线并转换为小写
snakeCase += "_";
snakeCase += currentChar;
}
else
{
// 否则,直接添加字符
snakeCase += char.ToUpper(currentChar);
}
} return snakeCase;
} private static string GenerateInsertStatement(Type entityType, string tableName)
{
PropertyInfo[] properties = entityType.GetProperties(); string columns = string.Join(", ", properties.Select(p => ConvertPascalToSnakeCase(p.Name)));
string values = string.Join(", ", properties.Select(p => $":{ConvertPascalToSnakeCase(p.Name)}")); string insertStatement = $"INSERT INTO {tableName} ({columns}) VALUES ({values})"; return insertStatement;
} private static string GenerateUpdateStatement(Type entity, string tableName, string whereField)
{
PropertyInfo[] properties = entity.GetProperties(); // 生成 SET 部分,用于更新列
string setClause = string.Join(", ", properties.Select(p => $"{ConvertPascalToSnakeCase(p.Name)} = :{ConvertPascalToSnakeCase(p.Name)}"));
// 生成 WHERE 子句,基于指定的字段
string whereClause = $"{ConvertPascalToSnakeCase(whereField)} = :{whereField}";
string updateStatement = $"UPDATE {tableName} SET {setClause} WHERE {whereClause}"; return updateStatement;
}

2.批量插入

public static void BulkInsert<T>(List<T> entities, OracleConnection connection)
{
DataTable table = ToDataTable<T>(entities);
try
{
string cmdstr = GenerateInsertStatement(typeof(T), ConvertPascalToSnakeCase(typeof(T).Name));
using (OracleCommand command = new OracleCommand(cmdstr, connection))
{
command.ArrayBindCount = entities.Count; // 设置为批量操作的大小
command.BindByName = true; // 使用参数名称绑定
// 创建参数数组
OracleParameter[] parameters = new OracleParameter[table.Columns.Count];
for (int i = 0; i < table.Columns.Count; i++)
{
parameters[i] = new OracleParameter(ConvertPascalToSnakeCase(table.Columns[i].ColumnName), GetOracleType(table.Columns[i].DataType));
// 选择特定列的所有行,并将其转换为数组
object[] columnArray = table.AsEnumerable().Select(row => row.Field<object>(table.Columns[i].ColumnName)).ToArray();
parameters[i].Value = columnArray;
}
// 添加参数到命令
command.Parameters.AddRange(parameters);
// 执行批量插入
command.ExecuteNonQuery();
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}

3.批量更新

public static void BulkUpdate<T>(List<T> entities, OracleConnection connection, PropertyInfo keyField)
{
DataTable table = ToDataTable<T>(entities);
try
{
string cmdstr = GenerateUpdateStatement(typeof(T), ConvertPascalToSnakeCase(typeof(T).Name), keyField.Name);
using (OracleCommand command = new OracleCommand(cmdstr, connection))
{
command.ArrayBindCount = entities.Count; // 设置为批量操作的大小
command.BindByName = true; // 使用参数名称绑定
// 创建参数数组
OracleParameter[] parameters = new OracleParameter[table.Columns.Count + 1];
for (int i = 0; i < table.Columns.Count; i++)
{
parameters[i] = new OracleParameter(ConvertPascalToSnakeCase(table.Columns[i].ColumnName), GetOracleType(table.Columns[i].DataType));
// 选择特定列的所有行,并将其转换为数组
object[] columnArray = table.AsEnumerable().Select(row => row.Field<object>(table.Columns[i].ColumnName)).ToArray();
parameters[i].Value = columnArray;
}
//where参数绑定
parameters[table.Columns.Count] = new OracleParameter(keyField.Name, GetOracleType(keyField.PropertyType));
object[] whereArray = table.AsEnumerable().Select(row => row.Field<object>(keyField.Name)).ToArray();
parameters[table.Columns.Count].Value = whereArray;
// 添加参数到命令
command.Parameters.AddRange(parameters);
// 执行批量插入
command.ExecuteNonQuery();
}
}
catch (Exception e)
{
Console.WriteLine(e);
}
}

四、用例

//更新
ExampleClass.BulkUpdate(delList, connection, typeof(实体类).GetProperty("实体主键字段")); //插入
ExampleClass.BulkInsert(addList, connection);

Oracle批量插入和更新的更多相关文章

  1. Mybatis 向oracle批量插入与更新数据

    插入 <insert id="batchSave" parameterType="java.util.List"> INSERT INTO T_UP ...

  2. oracle 批量插入-支持序列自增

    1.创建表.序列 -- Create table create table test_batch ( id number not null, name ), account ) ) -- Create ...

  3. java批量插入或更新的问题

    在批量插入或者更新中,setXXX的时候字段类型必须一致.例如:在普通sql中 pstmt8.setBigDecimal(j ,xxx);可以写成pstmt8.setString(j,xxx.toSt ...

  4. C#使用SqlDataAdapter 实现数据的批量插入和更新

    近日由于项目要求在需要实现中型数据的批量插入和更新,晚上无聊,在网上看到看到这样的一个实现方法,特摘抄过来,以便以后可能用到参考. 一.数据的插入 DateTime begin = DateTime. ...

  5. mybatis 注解的方式批量插入,更新数据

    一,当向数据表中插入一条数据时,一般先检查该数据是否已经存在,如果存在更新,不存在则新增  使用关键字  ON DUPLICATE KEY UPDATE zk_device_id为主键 model  ...

  6. MySQL on duplicate key update 批量插入并更新已存在数据

    业务上经常存在一种现象,需要批量往表中插入多条数据,但在执行过程中,很可能因为唯一键冲突,而导致批量插入失败.因此需要事先判断哪些数据是重复的,哪些是新增的.比较常用的处理方法就是找出已存在的数据,并 ...

  7. Mybatis中实现oracle的批量插入、更新

    oracle 实现在Mybatis中批量插入,下面测试可以使用,在批量插入中不能使用insert 标签,只能使用select标签进行批量插入,否则会提示错误 ### Cause: java.sql.S ...

  8. Oracle+Mybatis批量插入,更新和删除

    1.插入 (1)第一种方式:利用<foreach>标签,将入参的list集合通过UNION ALL生成虚拟数据,从而实现批量插入(验证过) <insert id="inse ...

  9. mybatis+oracle 批量插入,若数据库中有则做更新操作

    1.只批量插入: insert into WXPAY_ACCOUNT(id ,out_trade_no ,transaction_id)select SEQ_WXPAY_ACCOUNT.nextval ...

  10. mybatis Oracle 批量插入,批量更新

    传入的参数只要是list类型的参数就行了..............1.批量插入<insert id="insertBatch" parameterType="ja ...

随机推荐

  1. Go 编程语言详解:用途、特性、与 Python 和 C++ 的比较

    什么是Go? Go是一个跨平台.开源的编程语言 Go可用于创建高性能应用程序 Go是一种快速.静态类型.编译型语言,感觉上像动态类型.解释型语言 Go由Robert Griesemer.Rob Pik ...

  2. Python 元组完全指南1

    元组用于在单个变量中存储多个项目. mytuple = ("apple", "banana", "cherry") 元组是 Python 中 ...

  3. Qt加Opencv实现 梯度矫正 功能

    废话: 有时候我们是从物品的斜上方拍摄的图片,看起来不直观,需要把视角拉正,这样的一个操作就叫做 梯度矫正,需要用到的技术是 Opencv 的 透视变换. 这个只是一个简单的演示demo,如果完善一下 ...

  4. Hypium框架使能ArkTS应用高效测试

     原文链接:https://mp.weixin.qq.com/s/Ncc-x_4zy4wBZmSjknw1lQ,点击链接查看更多技术内容:   HarmonyOS发布了声明式开发框架ArkUI,带来了 ...

  5. k8s之构建Mysql和Wordpress集群

    一.实验目的 基于Kubernetes集群实现多负载的WordPress应用.将WordPress数据存储在后端Mysql,Mysql实现主从复制读写分离功能. 工作负载 服务 持久卷 Mysql S ...

  6. js 闭包(新)

    前言 旧的没有搬过来,先写一下新的感悟. 正文 ECMAScript中,闭包指的是: 从理论角度:所有的函数.因为它们都在创建的时候就将上层上下文的数据保存起来了.哪怕是简单的全局变量也是如此,因为函 ...

  7. 重新整理 mysql 基础篇—————表锁和全局锁[六]

    前言 锁从大的方面可以分为: 1.全局锁 2.表锁 3.行锁 正文 全局锁 全局锁就是对整个数据加上读锁. 在mysql 中,加入全局锁的命令就是: Flush tables with read lo ...

  8. Deep Learning on Graphs: A Survey第五章自动编码论文总结

    论文地址:https://arxiv.org/pdf/1812.04202.pdf 最近老师让我们读的一片论文,已经开组会讲完了,我负责的是第五章,图的自动编码,现在再总结一遍,便于后者研读.因为这篇 ...

  9. Node中的EventEmitter? 如何实现一个EventEmitter?

    一.是什么 我们了解到,Node采用了事件驱动机制,而EventEmitter就是Node实现事件驱动的基础 在EventEmitter的基础上,Node几乎所有的模块都继承了这个类,这些模块拥有了自 ...

  10. 深入了解PBKDF2:密码学中的关键推导函数

    title: 深入了解PBKDF2:密码学中的关键推导函数 date: 2024/4/20 20:37:35 updated: 2024/4/20 20:37:35 tags: 密码学 对称加密 哈希 ...