将 C# 对象列表中的多行数据插入 Oracle 12 数据库中的表中

Posted

技术标签:

【中文标题】将 C# 对象列表中的多行数据插入 Oracle 12 数据库中的表中【英文标题】:Insert multiple rows of data from C# List of objects into a table in Oracle 12 database 【发布时间】:2020-04-08 17:19:25 【问题描述】:

我想通过调用它的存储过程插入多行 来自 C#.NET。我正在使用 OracleDataAccess.dll 非托管 .net 驱动程序 由 Oracle 为 .NET 提供并使用 VS 2015。我的程序是控制台 将读取 excel 文件(一个接一个)查找特定的程序的程序 excel中的工作表并将工作表中的数据插入到 oracle 中的表。

我研究发现有人说可以通过 XML、UDT 和 OracleBulkCopy 完成,但我发现的代码不起作用。一世 尝试通过将其作为 xml 代码行运行来对其进行测试。屏幕转储 最后提供了这个错误。

我正在寻找有关如何将其从 C# 传递到 Oracle 以实现将这些记录插入 Oracle 表中的结果的解决方案。一世 如果您能帮助我在 Oracle 和 C#.NET。

C#.NET 端代码如下:

public class DSelect

  public string Installation  get; set; 
  public int Account  get; set; 
  public int BusinessNumber  get; set; 
  public long Sysd  get; set;         
  public decimal LocX  get; set;         
  public string Type  get; set; 
  public string Wattage  get; set; 
  public decimal ALen  get; set; 
  public int LWatt  get; set; 
  public string Tempr  get; set; 
  public DateTime CreatedDate  get; set;        


List<DSelect> listDSelect = new List<DSelect>();

.... Reading an excel worksheet row in a loop and building my list. There can be between 500 to 1000 rows of data in the worksheet

var deSel= new DSelect();
deSel.Installation  = "install1";
.................................
listDSelect.Add(deSel)

XmlSerializer serializer = new XmlSerializer(typeof(List<DSelect>));

var stringwriter = new System.IO.StringWriter();

serializer.Serialize(stringwriter, listDSelect);

传递给存储过程以插入到 Oracle 数据库 12c 中的表中。

    我想将整个列表作为对象传递给 oracle 存储过程。 在 oracle 存储过程中接收它并将其插入到表中。

在 SQL Developer 中失败的测试代码:

DECLARE
  p_AdditionRequest varchar2(30000); -- CLOB;
  t_xmlType SYS.XMLTYPE;
BEGIN    
  p_AdditionRequest:= '<?xml version="1.0" encoding="utf-16"?>
<ArrayOfDetailedSelection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <DetailedSelection>
    <Installation>645805</InstallationNumber>
    <AccountNumber>33170019251</AccountNumber>
  </DetailedSelection>
</ArrayOfDetailedSelection>';
  --t_xmlType := sys.xmltype.createxml(p_AdditionRequest); 

  SELECT InstallationNumber, AccountNumber (
  SELECT ExtractValue(column_value, '/DetailedSelection/InstallationNumber') InstallationNumber,
         ExtractValue(column_value, '/DetailedSelection/AccountNumber') AccountNumber         
  FROM TABLE(XMLSequence(XMLTYPE(p_AdditionRequest).EXTRACT('/ArrayOfDetailedSelection/DetailedSelection')))
       )
END;
/

【问题讨论】:

【参考方案1】:

您的 SQL 代码很接近,但您有几个错误。首先,您在 Installation 和 InstallationNumber 之间不一致,其次您缺少 INTO。我创建了一个测试表来保存数据,但是这样的东西应该可以工作:

DECLARE
  p_AdditionRequest varchar2(30000); -- CLOB;
BEGIN    
  p_AdditionRequest:= '<?xml version="1.0" encoding="utf-16"?>
<ArrayOfDetailedSelection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <DetailedSelection>
    <InstallationNumber>645805</InstallationNumber>
    <AccountNumber>33170019251</AccountNumber>
  </DetailedSelection>
</ArrayOfDetailedSelection>';

INSERT INTO TESTDETAILEDSECTION
  SELECT InstallationNumber, AccountNumber
  FROM (
  SELECT ExtractValue(column_value, '/DetailedSelection/InstallationNumber') InstallationNumber,
         ExtractValue(column_value, '/DetailedSelection/AccountNumber') AccountNumber         
  FROM TABLE(XMLSequence(XMLTYPE(p_AdditionRequest).EXTRACT('/ArrayOfDetailedSelection/DetailedSelection')))
       );
END;
/

但是我更喜欢对 SELECT 使用稍微不同的语法,因此:

INSERT INTO TESTDETAILEDSECTION
  SELECT xt.INSTALLATION, xt.ACCOUNTNUMBER FROM 
XMLTABLE('/ArrayOfDetailedSelection/DetailedSelection' PASSING xmlType(p_AdditionRequest)
  COLUMNS 
  "INSTALLATION" varchar(20) PATH 'InstallationNumber',
  "ACCOUNTNUMBER" varchar(20) PATH 'AccountNumber') xt;

后者的好处是可以在解析时设置xml中字段的数据类型。 (我假设 InstallationNumber 和 AccountNumber 都是 varchars)。您的怀疑也是正确的;从 c# 传递时,您需要使用clob。这里有个小提示,从 c# 开始,您需要将 OracleDbTypeOracleDbTypeEx 的参数设置为 OracleDbTyp.Clob

【讨论】:

乔纳森 感谢您的友好回复。我喜欢你使用 XMLTable 的想法。如果我传入更长的 XML 字符串。假设 XML 字符串中还有 500 个“DetailedSelection”部分,那么即使我将数据类型的大小增加到 varchar(100),它也会引发错误“可以绑定 LONG 值以插入 LONG 列”。跨度> 抱歉 Jonathan 更正了我之前的评论:我将类型更改为 DECLARE p_AdditionRequest CLOB; INSERT INTO TESTDETAILEDSELECTION SELECT xt.INSTALLATION, xt.ACCOUNTNUMBER FROM XMLTABLE('/ArrayOfDetailedSelection/DetailedSelection' PASSING to_clob(p_AdditionRequest) COLUMNS "INSTALLATION" varchar(100) PATH 'InstallationNumber', "ACCOUNTNUMBER" varchar(100) PATH 'AccountNumber') xt;使用 t_clob() 函数它编译得很好,但是当我运行它时,没有任何东西插入到表中。 不要使用 to_clob()。将您的 xml 声明为 clob,但您仍必须使用 PASSING xmltype(p_AdditionRequest)。如果这不起作用,请将不起作用的 xml 发邮件给我,我会在早上再看一遍。这里已经很晚了(德国时间 21.40)。我的电子邮件是 jwillcock19@gmail.com 乔纳森非常感谢。我会尝试一下,如果它不起作用,会通过电子邮件发送给您。晚安。

以上是关于将 C# 对象列表中的多行数据插入 Oracle 12 数据库中的表中的主要内容,如果未能解决你的问题,请参考以下文章

将 R Dataframe 中的多行插入 Oracle 数据库

C#,将多行插入 SQL 数据库

使用 C# 在 oracle 数据库中更新多行的最佳方法

使用 PHP 将多行 Oracle 结果集插入 MYSQL

Oracle数据库多行-> c# [关闭]

如何使用一个插入语句将多行插入到 oracle 数据库中? [复制]