一、驱动。使用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. C++ 条件与 If 语句:掌握逻辑判断与流程控制精髓

    C++ 条件和 If 语句 您已经知道 C++ 支持数学中的常见逻辑条件: 小于:a < b 小于或等于:a <= b 大于:a > b 大于或等于:a >= b 等于:a = ...

  2. RabbitMQ 11 死信队列

    死信队列 概述 消息队列中的数据,如果迟迟没有消费者来处理,就会一直占用消息队列的空间. 比如抢车票的场景,用户下单高铁票之后,会进行抢座,然后再进行付款,但是如果用户下单之后并没有及时的付款,这张票 ...

  3. 给你安利一款鲁班大叔开发的maven依赖搜索神器

    写在前面 一款好的插件往往能提高我们的开发效率.今天就给大家安利一款maven 依赖搜索插件. 插件是自己一直关注的鲁班大叔开发的,用了几天真的好用 废话不多说,我们就来看看这是一款什么插件 一.ma ...

  4. nginx重新整理——————https[七]

    前言 简单介绍一些https. 正文 pki 公钥基础设施: 证书链: tls 通讯过程 验证身份 达成安全套件共识 传递秘钥 加密通讯 sudo yum install epel-release s ...

  5. 重新整理.net core 计1400篇[三] (.net core 如何源代码调试和查看源码 )

    前言 本来这里是写源代码的,因为vs没有那么容易调试查看到源代码,所以先把调试源代码和查看源代码弄完. 正文 需要修改一些vs配置,这个vs也是有要求的,要vs2017. 那么你还需要加载远程符号. ...

  6. js 使用flow

    前言 what is flow?我想是的,很多人都没有接触过,的确,他是一个新的项目,是的facebook开发的东西,一般还是可以的,有必要去学习一下,在react还是比较重要的. 它做的一件事叫做静 ...

  7. 高云1N1开发板高云gowin软件使用教程

    国产FPGA是最近几年起来的产品,具有性价比高特点.高云FPGA,很多用户都用在LED,电机控制,PLC设备上. 开发板子采用GW1N-LV1QN48C6/I5 FPGA器件.具有低功耗,瞬时启动,高 ...

  8. WPF随笔收录-实时绘制心率曲线

    一.前言 在自己的项目中,涉及到实时心率曲线的绘制,项目上的曲线绘制,一般很难找到能直接用的第三方库,而且有些还是定制化的功能,所以还是自己绘制比较方便.很多人一听到自己画就害怕,感觉很难,今天就分享 ...

  9. springboot多模块项目启动经历

    springboot多模块使用 @ 目录 springboot多模块使用 前言 大佬把项目权限给我了,我就先下下来看看学习一下 一.识别 二.maven配置 1.安装maven 三.加载刷新 总结 前 ...

  10. 不常用的技能-【手动编译java类】

    jdk版本:1.7 冒号分割jar包,1.8 分号分割jar包 javac -classpath fastjson-1.2.24.jar:jedis-2.9.0.jar Test.javajava - ...