一、驱动。使用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. Python实现聊天机器人接口封装部署

    一.前言说明 博客声明:此文链接地址https://www.cnblogs.com/Vrapile/p/12427326.html,请尊重原创,未经允许禁止转载!!! 1. 功能简述 (1)将chat ...

  2. MySQL的下载、安装和配置

    ​ 一.MySQL的下载 下载地址:http://dev.mysql.com/downloads/mysql 进入下载页面,选择所需版本,这里示范MySQL8.0 图一 选择版本,下载MSI(软件安装 ...

  3. 双端队列的基本实现【数据结构与算法—TypeScript 实现】

    笔记整理自 coderwhy 『TypeScript 高阶数据结构与算法』课程 特性 本质:允许队列在两端进行 入队 和 出队 操作 设计 实现方式:基于 数组 实现 属性: data:存放队列元素 ...

  4. Centos调整分区存储大小

    将/home下900G转移到/目录下 1.查看分区大小:df -hl 2.备份home文件:tar cvf /run/home.tar /home 3.终止home文件进程(切换到非home路径下执行 ...

  5. Centos7、CentOS8、CentOS9 修改硬盘分区大小扩充root分区大小

    Centos7 修改硬盘分区大小,实现CentOS无损分区扩容 扩充root分区大小 安装了CentOS7 开发环境及软件后,发现root分区已经才剩下不到1G空间,难不成要干掉重装,OMG,NO! ...

  6. 报表如何批量导出成 excel 文件

    需求说明 报表展现后可以通过工具栏中的导出按钮将当前展现的报表导出成 excel 文件,但是在实际使用中通常会要求报表不需要展现,直接通过一些操作将报表导出成 excel 文件,并且往往会要求批量导出 ...

  7. Django框架——路由分发、名称空间、虚拟环境、视图层三板斧、JsonResponse对象、request获取文件、FBV与CBV、CBV源码剖析、模版层

    路由分发 # Django支持每个应用都可以有自己独立的路由层.静态文件.模版层.基于该特性多人开发项目就可以完全解耦合,之后利用路由分发还可以整合到一起 多个应用都有很多路由与视图函数的对应关系 这 ...

  8. 使用input标签的时候报错,提示Form elements must have labels: Element has no title attribute Element has no placeholder attribute

    使用input标签的时候报错,提示Form elements must have labels: Element has no title attribute Element has no place ...

  9. 力扣196(MySQL)-删除重复的电子邮箱(简单)

    题目: 表: Person 编写一个 SQL 删除语句来 删除 所有重复的电子邮件,只保留一个id最小的唯一电子邮件. 以 任意顺序 返回结果表. (注意: 仅需要写删除语句,将自动对剩余结果进行查询 ...

  10. 你不知道的 HTTPS 压测

    ​简介:随着互联网安全规范的普及,使用 HTTPS 技术进行通信加密,实现网站和 APP 的可信访问,已经成为公认的安全标准.本文将介绍针对 HTTPS 协议做压力测试的关注点,以及使用 PTS 做 ...