首页 > 数据库 >Oracle批量插入和更新

Oracle批量插入和更新

时间:2023-10-27 14:13:14浏览次数:37  
标签:string 批量 插入 typeof Oracle table parameters Columns Name

一、驱动。使用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;
        }
View Code

 

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);
            }
        }
View Code

 

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);
            }
        }
View Code

 四、用例

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

//插入
ExampleClass.BulkInsert(addList, connection);

 

标签:string,批量,插入,typeof,Oracle,table,parameters,Columns,Name
From: https://www.cnblogs.com/ggtc/p/17792183.html

相关文章

  • https://www.modb.pro/db/1717179181560324096 --转载 Oracle 批量更新(BULK)优化技巧
    面对一个需要更新大量数据的任务,我平时的处理方法是通过循环,每N行提交来完成这个任务。这样做的两个主要原因:1、频繁地提交大量小事务比处理和提交一个大事务更快,也更高效2、没有足够的UNDO空间今天在学到了一种新的解决思路,在此记录一下方便后面使用。  假设我们有一个表T,......
  • 金蝶KIS VB插件 老单据如何插入多行值,老单获取基础资料内码、代码、名称
    转自:https://blog.csdn.net/ssyyll/article/details/16804273WhileNotrs.EOF '填充对应的行 Withm_BillTransfer '如果超过两行以上的值,需要先用 .BillForm.InsertRow '插入一行 .SetGridTextLRow,dicFieldEntry("FItemID"),rs("FNumber") .SetGridText......
  • 卸载oracle11g
    1.卸载1.1停止使用Oracle的服务停用oracle服务,进入计算机管理,在服务中,找到oracle开头的所有服务,右击选择停止。1.2.运行卸载Oracle数据库程序在开始菜单中找到Oracle安装产品,点击运行Oracle自带的卸载程序UniversalInstaller工具卸载。1.3.删除使用Oracle的服......
  • 高效技巧揭秘:Java轻松批量插入或删除Excel行列操作
    摘要:本文由葡萄城技术团队原创并首发。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。前言在职场生活中,对Excel工作表的行和列进行操作是非常普遍的需求。一般情况下在Excel中,可以通过右键菜单插入或者删除行与列。不过在软件开发......
  • 在不知带头节点地址的情况下删除和插入一个p指针指向的节点总结
    在不知带头节点地址的情况下删除和插入一个p指针指向的节点总结(p指向的不是第一个,也不是最后一个)A->B->C*p->B插入(在p结点之前插入q)解析:直接往p前插入q,由于没有头节点,不能遍历到p的位置,所以向p的后面插入q,在交换p、q的值q->next=p->next;p->next=q;swap(&p......
  • 使用NvicatPremium时,Mysql数据库插入数据时,报错1064
    使用navicatPremium新版本时,插入数据,显示错误1064-YouhaveanerrorinyourSQLsyntax;checkthemanualthatcorrespondstoyourMySQLserverversionfortherightsyntaxtousenear''choose'('ChooseNo','SNo','CNo','......
  • 批量手机号码归属地查询工具
    在日常工作和生活中,手机号码归属地的查询需求越来越普遍。这款查询软件,具有高效、便捷、隐私保护等诸多优势,让您轻松解决手机号码归属地查询问题。可以快速批量查询手机号码归属地,为您节省宝贵的时间和精力。无需联网即可进行查询。无需上传号码到远程服务器,确保您的数据安全,本地......
  • 10月《中国数据库行业分析报告》已发布,深度剖析甲骨文大会Oracle技术新趋势
    为了帮助大家及时了解中国数据库行业发展现状、梳理当前数据库市场环境和产品生态等情况,从2022年4月起,墨天轮社区行业分析研究团队出品将持续每月为大家推出最新《中国数据库行业分析报告》,持续传播数据技术知识、努力促进技术创新与行业生态发展,目前已更至第十七期,并发布了共计1......
  • oracle 11g 由于0rc4km05kgzb9占用undo 使用率高问题
    设置参数解决altersystemset"_smu_debug_mode"=33554432;设置这个之后v$undostat.tuned_undoretention会取(maxquerylensecs+300)和参数undo_retention里的最大值altersystemset"_undo_autotune"=false;直接禁用了AutomaticTuningofUndoRetention特性altersystem......
  • lightdb支持@dblink方式访问oracle
    在lightdb23.4版本开始,兼容了oracle中通过@dblink方式跨库访问oracle库中表的方式。以下为具体的实现方案:*假设在oracle库中存在表youyus(t1int,co1number(2),co2varchar(100),co3varchar2(40))1.在lightdb对应的业务库中创建oracle_fdw插件lightdb@testdb=#createe......