问题
I am trying to read data from DataGridView
and insert it into database. Everything works fine when one record is in the DataGridView
, but when there is more than one record within the DataGridView
I got only one record inserted and all other records are not inserted into database.
I have attached the Oracle function code for more details.
I think the issue caused by function since the first table order
should have one record and the sub table order_details
should have the list of purchased items. So the function execute once and then stop because of primary key exception on the first table (Order)
.
I don't know if that is right but in case it is right then how to solve and keep thing happen in one transaction so all transaction will success, or it will rollback all things has been done before?
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;
}
}
function Code
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;
/
回答1:
This is not necessarily the issue but. cmd.Parameters.Add(":vORDER_ID", OracleDbType.Int32, ParameterDirection.ReturnValue); You are not using orderid in your proceuder and you are passing it in.
Second, Is the foreach actually looping for each data row? You have not provided enough detail to help you debug this.
Third, Check the query execution method. I dont think its going to return the vorder_id ExecuteNonQuery()
Finally, the vorderid is going to change for each record inserted and the text would only show the last vorderid inserted.
来源:https://stackoverflow.com/questions/41813535/only-one-record-inserted-into-oracle-database-from-datagridview