【问题标题】:Only one record inserted into Oracle database from datagridview只有一条记录从 datagridview 插入到 Oracle 数据库中
【发布时间】:2017-01-23 18:51:08
【问题描述】:

我正在尝试从DataGridView 读取数据并将其插入数据库。当DataGridView 中有一条记录时,一切正常,但是当DataGridView 中有不止一条记录时,我只插入了一条记录,而所有其他记录都没有插入数据库。

我已附上Oracle函数代码以获取更多详细信息。

我认为功能引起的问题,因为第一个table order 应该有一个记录,而子table order_details 应该有购买项目的列表。所以函数执行一次然后因为第一个table (Order)上的主键异常而停止。

我不知道这是否正确,但如果正确,那么如何解决并保持事情发生在一个事务中,以便所有事务都会成功,或者它会回滚之前已经完成的所有事情?

string connstr = @"Data Source=orcl; User Id=user; password=pwd;";
                string insertcmdtxt = @"F_INS_ORDER_DATA";   

                using (OracleConnection conn = new OracleConnection(connstr))
                using (OracleCommand cmd = new OracleCommand(insertcmdtxt, conn))
                {
                    try
                    {
                        conn.Open();

                        cmd.CommandType = CommandType.StoredProcedure;

                        cmd.CommandText = insertcmdtxt;

                        foreach (DataGridViewRow Row in DGV_INVOICE.Rows)
                        {
                            cmd.Parameters.Clear();

                            cmd.Parameters.Add(":vORDER_ID", OracleDbType.Int32, ParameterDirection.ReturnValue);

                            cmd.Parameters.Add(new OracleParameter(":P_CUSTOMER_ID", OracleDbType.Int32)).Value     = TB_CUSTOMER_ID.Text;
                            cmd.Parameters.Add(new OracleParameter(":P_ORDER_NOTE", OracleDbType.Varchar2)).Value   = TB_ORDER_NOTE.Text;

                            cmd.Parameters.Add(new OracleParameter(":P_PRODUCT_ID", OracleDbType.Int32)).Value      = Row.Cells[DGV_INVOICE.Columns["DGV_PRODUCT_ID"].Index].Value;
                            cmd.Parameters.Add(new OracleParameter(":P_UNIT_PRICE", OracleDbType.Int32)).Value      = Row.Cells[DGV_INVOICE.Columns["DGV_UNIT_PRICE"].Index].Value;
                            cmd.Parameters.Add(new OracleParameter(":P_QUANTITY", OracleDbType.Int32)).Value        = Row.Cells[DGV_INVOICE.Columns["DGV_QUANTITY"].Index].Value;
                            cmd.Parameters.Add(new OracleParameter(":P_DISCOUNT", OracleDbType.Int32)).Value        = Row.Cells[DGV_INVOICE.Columns["DGV_DISCOUNT"].Index].Value;
                            cmd.Parameters.Add(new OracleParameter(":P_ORDER_STATUS", OracleDbType.Varchar2)).Value = '1';
                            cmd.Parameters.Add(new OracleParameter(":P_ITEM_NOTE", OracleDbType.Varchar2)).Value    = Row.Cells[DGV_INVOICE.Columns["DGV_ITEM_NOTE"].Index].Value;

                            cmd.ExecuteNonQuery();
                        }

                        TB_INVOICE_ID.Text = (cmd.Parameters[":vORDER_ID"].Value).ToString();
                    }
                    catch (Exception EX)
                    {
                        MessageBox.Show(EX.Message, "حدث خطاء", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        return;
                    }
                }

功能代码

CREATE OR REPLACE FUNCTION F_INS_Order_Data (P_CUSTOMER_ID     IN NUMBER,
                                                                                       P_ORDER_NOTE       IN VARCHAR2,
                                                                                       P_PRODUCT_ID        IN NUMBER,
                                                                                       P_UNIT_PRICE         IN NUMBER,
                                                                                       P_QUANTITY           IN NUMBER,
                                                                                       P_DISCOUNT           IN NUMBER,
                                                                                       P_ORDER_STATUS  IN VARCHAR2,
                                                                                       P_ITEM_NOTE         IN VARCHAR2)
   RETURN NUMBER
IS
   VOrder_Id      NUMBER;                --ORDER_ID Filled by trigger
   vCreated_by   VARCHAR2 (64)         := 'SYSTEM';
   vCreated_On   DATE                        := SYSDATE;

   sql_stmt           VARCHAR2 (4000);
   ERR_CODE      VARCHAR2(64);
   ERR_MSG       VARCHAR2(1024);

BEGIN

    SAVEPOINT Setp1;

    sql_stmt := 'INSERT INTO orders (ORDER_ID,
                                                          CUSTOMER_ID,
                                                          NOTES,
                                                          CREATED_BY,
                                                          CREATED_ON)
                                            VALUES (NULL,                       --ORDER_ID Filled by trigger
                                                          :PCUSTOMER_ID,    --CUSTOMER_ID
                                                          :POrderNote,            --NOTES
                                                          :PCREATED_BY,       --CREATED_BY
                                                          :PCREATED_ON)     --CREATED_ON
                      RETURNING ORDER_ID INTO :vORDER_ID';

    EXECUTE IMMEDIATE sql_stmt USING P_CUSTOMER_ID,
                                                                   P_ORDER_NOTE,
                                                                   vCreated_by,
                                                                   vCreated_ON
                      RETURNING INTO vORDER_ID;

    --DBMS_OUTPUT.PUT_LINE (sql_stmt);    /* For Testing Purpose */


    sql_stmt:='INSERT INTO ORDER_DETAILS (ORDER_ID,
                                                                           PRODUCT_ID,
                                                                           UNIT_PRICE,
                                                                           QUANTITY,
                                                                           DISCOUNT,
                                                                           ORDER_STATUS,
                                                                           NOTES,
                                                                           CREATED_BY,
                                                                           CREATED_ON)
                                                           VALUES ( :PvORDER_ID,              --ORDER_ID,
                                                                           :PPRODUCT_ID,          --PRODUCT_ID
                                                                           :PUNIT_PRICE,           --UNIT_PRICE
                                                                           :PQUANTITY,             --QUANTITY
                                                                           :PDISCOUNT,             --DISCOUNT
                                                                           :PORDER_STATUS,    --ORDER_STATUS
                                                                           :PItem_Note,                 --NOTES
                                                                           :PCREATED_BY,          --CREATED_BY
                                                                           :PCREATED_ON         --CREATED_ON
                                                                          )';

    EXECUTE IMMEDIATE sql_stmt USING vORDER_ID,
                                                                   P_PRODUCT_ID,
                                                                   P_UNIT_PRICE,
                                                                   P_QUANTITY,
                                                                   P_DISCOUNT,
                                                                   P_ORDER_STATUS,
                                                                   P_ITEM_NOTE,
                                                                   vCreated_by,
                                                                   vCreated_On;

   --DBMS_OUTPUT.PUT_LINE (sql_stmt);    /* For Testing Purpose */

   RETURN (VOrder_Id);

EXCEPTION WHEN OTHERS THEN 

    ROLLBACK TO Setp1;

    ERR_CODE := SQLCODE;
    ERR_MSG := SUBSTR(SQLERRM, 1, 1024);

    sql_stmt := F_INS_ERROR_LOG(SYSDATE,                        --P_ERROR_TIME,
                                                       vCreated_by,                    --P_USER_ID,
                                                       'F_INS_Order_Data',      --P_PROGRAM_UNIT,
                                                       NULL,                              --P_ERROR_LOCATION,
                                                       NULL,                             --P_KEY_DATA_DESC,
                                                       ERR_CODE,                    --P_ERROR_CODE,
                                                       ERR_MSG);                    --P_ERROR_MSG)';

RETURN -1;

END F_INS_Order_Data;
/

【问题讨论】:

  • 您在每次调用时都会添加一个 ORDER 和 ORDER_DETAILS,但您只需要一次 ORDER,因此您需要更改您的逻辑。您可以在 ExecuteNonQuery() 调用之后将您的 TB_INVOICE_ID.Text = 移动到循环内,然后如果它有一个值将其作为参数发送并更改您的 proc 以测试它是传入还是 null。否则,制作 2 个 proc(Add_Order、Add_Order_Details)。
  • @SteveGreene 我使用了一个函数来强制 Rollback 在出现任何错误的情况下回滚所有更改,以避免不确定事务和不完整事务的风险......如果我按照我们的建议执行两个函数,那么如何我能够回滚第一个和第二个函数所做的所有更改吗?以及如何让 c# 在一个事务中执行这两个函数?
  • 在 Oracle 中不确定何时涉及触发器。您可以选择第一个选项并在创建时返回 Order Id,然后在第二次和后续迭代中传递它。将proc中的逻辑更改为仅在未传入(null)时插入订单。

标签: c# datagridview oracle11gr2


【解决方案1】:

这不一定是问题,但是。 cmd.Parameters.Add(":vORDER_ID", OracleDbType.Int32, ParameterDirection.ReturnValue); 您没有在您的 proceuder 中使用 orderid,而是将其传入。

第二, foreach 是否真的为每个数据行循环?您没有提供足够的详细信息来帮助您进行调试。

第三,检查查询执行方式。我不认为它会返回 vorder_id ExecuteNonQuery()

最后,插入的每条记录的 vorderid 都会发生变化,文本只会显示最后插入的 vorderid。

【讨论】:

  • cmd.Parameters.Add(":vORDER_ID", OracleDbType.Int32, ParameterDirection.ReturnValue); out 函数返回的参数我认为 foreach 循环通过datagridview 因为我在ExecuteNonQuery(); 之前添加了MessageBox.Show(DGV_INVOICE.RowCount.ToString()); 并且它显示在对应于记录数datagridview 最后一点,为什么我有两个表,第一个表有 Order_ID 作为主键,它对第二个表 order_details 的引用完整性
  • 最后我不明白你所说的检查查询执行方法非常清楚,但是当我使用 toad 调用函数来测试它时,它的返回 order_id 和另一个证明它之后的原因插入一条记录返回orderid到接口
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-11-21
  • 1970-01-01
相关资源
最近更新 更多