使用 DataTable 中的 OracleDataAdapter 更新记录并将记录插入 Oracle 表

Posted

技术标签:

【中文标题】使用 DataTable 中的 OracleDataAdapter 更新记录并将记录插入 Oracle 表【英文标题】:Update and insert records into Oracle table using OracleDataAdapter from DataTable 【发布时间】:2014-04-11 18:53:30 【问题描述】:

一个新手向 c# 提出的问题,并为它的长度道歉。我有以下情况。我有一个小型控制台应用程序,它通过连接到外部系统来填充数据表,然后需要更新现有记录并将新记录插入到 oracle 表中。数据表中的列与 oracle 表列的名称不同,并且顺序也不相同。我在这里阅读了另一篇具有类似场景(从文件加载到表中)的帖子,并提到使用 OracleDataAdapter 进行更新/插入是可行的。一个简化的数据表和oracle表是

DataTable table = new DataTable(); table.Columns.Add("Product", typeof(String)); table.Columns.Add("Price", typeof(double)); table.Columns.Add("Effective_Date", typeof(DateTime));

//sample data table.Rows.Add("abcd", 1.011, DateTime.Today); table.Rows.Add("efg", 1.00, DateTime.Today); table.Rows.Add("hijk", 20, DateTime.Today);

oracle表的结构

ITEM VARCHAR2(20 BYTE) NOT NULL ENABLE, EFF_DATE DATE, VALUE NUMBER

我尝试了以下代码来使用数据表和适配器来更新 oracle 表,但我遗漏了一些东西。我也想知道我是不是找错树了。我看到的大多数使用数据适配器的示例首先从表中进行选择,然后将结果放入网格中,用户可以在其中添加、更新、插入或删除记录,然后使用数据适配器更新桌子。就我而言,我想知道如果数据表中的所有记录都将被视为插入,我是否可以让它工作,因为数据表和 oracle 表之间没有连接。

我正在使用 Oracle.ManagedDataAccess.Client 进行连接并进行更新

public static void UpdateOrSaveItems(DataTable dt)

    String insert_statement, update_statement, select_statement;

    select_statement = "SELECT * from items";
    insert_statement = "INSERT INTO items (item, eff_date, value) values (:pInsItem,:pInsEffDate,:pInsValue)";
    update_statement = "UPDATE items set eff_date = :pUpdEffDate, value = :pUpdValue where item = :pUpdItem";

    using (OracleConnection conn = theDatabase.ConnectToDatabase())
    
        using (OracleDataAdapter oraAdapter = new OracleDataAdapter(select_statement, conn))
           

         //build update/insert commands and parameters
         oraAdapter.UpdateCommand = new OracleCommand(update_statement, conn);
         oraAdapter.InsertCommand = new OracleCommand(insert_statement, conn);

         oraAdapter.UpdateCommand.BindByName = true;
         oraAdapter.InsertCommand.BindByName = true;

         OracleParameter pUpdItem = new OracleParameter("pUpdItem", OracleDbType.Varchar2);
         pUpdItem.SourceColumn = dt.Columns[0].ColumnName;                  

         OracleParameter pUpdEffDate = new OracleParameter("pUpdEffDate", OracleDbType.Date);
         pUpdEffDate.SourceColumn = dt.Columns[2].ColumnName;

         OracleParameter pUpdValue = new OracleParameter("pUpdValue", OracleDbType.Double);
         pUpdValue.SourceColumn = dt.Columns[1].ColumnName;

         OracleParameter pInsItem = new OracleParameter("pInsItem", OracleDbType.Varchar2);
         pUpdItem.SourceColumn = dt.Columns[0].ColumnName;

         OracleParameter pInsEffDate = new OracleParameter("pInsEffDate", OracleDbType.Date);
         pInsEffDate.SourceColumn = dt.Columns[2].ColumnName;

         OracleParameter pInsValue = new OracleParameter("pInsValue", OracleDbType.Double);
         pInsValue.SourceColumn = dt.Columns[1].ColumnName;              oraAdapter.UpdateCommand.Parameters.Add(pUpdItem);

         oraAdapter.UpdateCommand.Parameters.Add(pUpdEffDate);
         oraAdapter.UpdateCommand.Parameters.Add(pUpdValue);

         oraAdapter.InsertCommand.Parameters.Add(pInsItem);
         oraAdapter.InsertCommand.Parameters.Add(pInsEffDate);
         oraAdapter.InsertCommand.Parameters.Add(pInsValue);

         oraAdapter.Update(dt);
    
 

当我运行它时,我得到一个错误,我无法将空值插入到定义为键的列中。在数据表中,它们都不是空的。我在告诉它数据在哪里时遗漏了一些东西,但我不确定它是什么。还想知道这是否是做这类事情的正确方法。我想避免

loop through datatable select to see if record is in oracle table if in table update else insert

因为记录的数量可能有几十万,并且不确定性能会如何。

【问题讨论】:

【参考方案1】:

您是否正在初始化您传入的 DataTable 对象的 ColumnName 属性?如果不是,它们可能会被读取为空。

例如

public static void Main()


 Datatable myDataTable = new DataTable();
 myDataTable.Columns = new Columns[3];
 myDataTable.Columns[0].ColumnName = "Employees";
 myDataTable.Columns[1].ColumnName = "Salary";
 myDataTable.Columns[2].ColumnName = "Department";


 UpdateOrSaveItems(myDataTable);



【讨论】:

从调试中查看数据表看来,所有行都填充了数据。 我发现了我的错误。我没有在名为 pInsItem 的参数上设置源列。我有以下【参考方案2】:

我发现了错误。我没有在我的插入参数之一上设置源列。我在 pUdpItem 上设置了两次源列,而不是为 pUdpItem 和 pInsItem 设置它

【讨论】:

以上是关于使用 DataTable 中的 OracleDataAdapter 更新记录并将记录插入 Oracle 表的主要内容,如果未能解决你的问题,请参考以下文章

C#中删除DataTable中的行的方法

DataTable 中的多个数组

循环删除DataTable.Row中的多行问题

使用SqlBulkCopy将DataTable中的数据批量插入数据库中

关于c#中的datatable,不知道如何清空里面的数据

使用 SqlBulkCopy 将 DataTable 中的列映射到 SQL 表