从后面的 C# 代码调用存储过程时插入语句不起作用
Posted
技术标签:
【中文标题】从后面的 C# 代码调用存储过程时插入语句不起作用【英文标题】:Insert statement not working when calling stored proc from C# code behind 【发布时间】:2013-03-31 13:46:26 【问题描述】:我的数据库中有一个存储过程,可将数据插入 3 个表。该过程已正确编译。我已经使用带有示例数据的 PL/SQL DEVELOPER 工具对其进行了测试,并且运行良好。
在存储过程的代码中,我使用了一个变量successCnt1,它计算编号。成功的插入语句。然后将此变量分配给successCnt。我从后面的代码中获取这个变量的值。如果 successCnt == 0 则显示错误。
问题是,当我从过程后面的 C# 代码调用它时返回successCnt == 0。请告诉我哪里做错了!提前致谢。
表架构:
TBLTRAIN 架构: TRAINID (VARCHAR2(5)), DATE1 (DATE) , AC2SEAT (NUMBER) , AC3SEAT (NUMBER) , SLEEPERSEAT (NUMBER) , ACCHAIRCARSEAT (NUMBER) , SECONDSEAT (NUMBER )
TBLTRAINFARE 架构: TRAINID (VARCHAR2(5)), CLASS (VARCHAR2(5)), FARE (NUMBER)
TBLTRAINDETAIL 架构: TRAINID (VARCHAR2(5)) , FROM1 (VARCHAR2(15)), TO1 (VARCHAR2(15)) , TRAINNAME (VARCHAR2(15))
程序:
CREATE OR REPLACE PROCEDURE TrainInsertByParameter (p_ac2seat in number,
p_ac3seat in number,
p_ccseat in number,
p_sleeperseat in number,
p_secondseat in number,
p_date1 in date,
p_trainid in varchar2,
p_fare in number,
p_fromplace in varchar2,
p_toplace in varchar2,
p_class in varchar2,
p_trainname in varchar2,
p_successCnt out number) IS
successCnt1 number(6) NOT NULL := 0;
rowUpdated1 number(6) NOT NULL := 0;
rowUpdated2 number(6) NOT NULL := 0;
rowUpdated3 number(6) NOT NULL := 0;
BEGIN
SAVEPOINT before;
INSERT INTO tbltrain (ac2seat,ac3seat,acchaircarseat,sleeperseat,secondseat,date1,trainid) VALUES(p_ac2seat,p_ac3seat,p_ccseat,p_sleeperseat,p_secondseat,p_date1,p_trainid);
rowUpdated1 := SQL%RowCount;
successCnt1 := successCnt1 + 1;
dbms_output.put_line('Successful Insertion tbltrain. count ='||successCnt1);
dbms_output.put_line('Successful Insertion tbltrain. Row Updated ='||rowUpdated1);
INSERT INTO tbltraindetail (trainid,trainname,from1,to1) VALUES(p_trainid,p_trainname,p_fromplace,p_toplace);
rowUpdated2 := SQL%RowCount;
successCnt1 := successCnt1 + 1;
dbms_output.put_line('Successful Insertion tbltraindetail. count ='||successCnt1);
dbms_output.put_line('Successful Insertion tbltraindetail. Row Updated= '||rowUpdated2);
INSERT INTO tbltrainfare(trainid,class,fare) VALUES (p_trainid,p_class,p_fare);
rowUpdated3 := SQL%RowCount;
successCnt1 := successCnt1 + 1;
p_successCnt := successCnt1;
COMMIT;
dbms_output.put_line('Successful Insertion tbltrainfare. count ='||p_successCnt);
dbms_output.put_line('Successful Insertion tbltrainfare. Row Updated= '||rowUpdated3);
EXCEPTION
WHEN Others THEN
successCnt1 := 0;
p_successCnt := successCnt1;
dbms_output.put_line('An error has occured. count ='||p_successCnt);
ROLLBACK TO before;
END;
调用 C# 代码背后的代码(使用 Microsoft Visual Studio)
OracleConnection con1 = new OracleConnection();
con1.ConnectionString = ConfigurationManager.ConnectionStrings["myConnectionStringOracle"].ConnectionString;
Int32 fare = Convert.ToInt32(txtFare.Value);
String date1 = txtDate.Value.ToString();
String class1 = ddlClass.SelectedItem.Text.ToString();
String fromplace = txtFromPlace.Text.ToString();
String toplace = txtToPlace.Text.ToString();
String trainid = txtId1.Text.ToString();
String trainname = txtTrainName.Text.ToString();
Int32 ac2seat = Convert.ToInt32(txtAc2TierSeat.Value);
Int32 ac3seat = Convert.ToInt32(txtAc3TierSeat.Value);
Int32 ccseat = Convert.ToInt32(txtAcChairCarSeat.Value);
Int32 sleeperseat = Convert.ToInt32(txtSleeperSeat.Value);
Int32 secondseat = Convert.ToInt32(txtSecondSeat.Value);
Int32 SuccessCnt;
OracleCommand cmd = new OracleCommand();
cmd.Connection = con1;
cmd.CommandText = "TrainInsertByParameter";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("p_ac2seat", OracleType.Number).Value = ac2seat;
cmd.Parameters.Add("p_ac3seat", OracleType.Number).Value = ac3seat;
cmd.Parameters.Add("p_ccseat", OracleType.Number).Value = ccseat;
cmd.Parameters.Add("p_sleeperseat", OracleType.Number).Value = sleeperseat;
cmd.Parameters.Add("p_secondseat", OracleType.Number).Value = secondseat;
cmd.Parameters.Add("p_date1", OracleType.DateTime).Value = date1;
cmd.Parameters.Add("p_trainid", OracleType.VarChar).Value = trainid;
cmd.Parameters.Add("p_fare", OracleType.Number).Value = fare;
cmd.Parameters.Add("p_fromplace", OracleType.VarChar).Value = fromplace;
cmd.Parameters.Add("p_toplace", OracleType.VarChar).Value = toplace;
cmd.Parameters.Add("p_class", OracleType.VarChar).Value = class1;
cmd.Parameters.Add("p_trainname", OracleType.VarChar).Value = trainname;
cmd.Parameters.Add("p_successCnt", OracleType.Number).Direction = ParameterDirection.Output;
try
cmd.ExecuteNonQuery();
SuccessCnt = Convert.ToInt32(cmd.Parameters["p_successCnt"].Value);
if (SuccessCnt == 0)
Page.ClientScript.RegisterStartupScript(this.GetType(), "Window", "alert('An error has occured. No data has been inserted. Please try again with valid data');", true);
else if (SuccessCnt > 0)
Page.ClientScript.RegisterStartupScript(this.GetType(), "Window", "alert('Data has been inserted successfully.');", true);
catch (Exception ex)
我的问题在这里:当我调试时,在 if-else 块中(在 try 块内),控件总是转到 if(SuccessCnt= =0) 部分,因为该过程返回 p_successCnt ==0 。我期待的控制去 else if(SuccessCnt > 0) 阻塞,因为过程应该返回 p_successCnt ==3
【问题讨论】:
@Mat 我在 C# 中没有收到任何错误。我在存储过程中遇到了一些异常(我不知道),而它是从后面的代码调用的。但是当我通过编写一个带有一些数据的小型 PL/SQL 调用代码来测试这个过程时,它运行良好。这就是问题..我会记住你所说的大写标题..谢谢 【参考方案1】:我建议将输出参数添加到您的过程中,以便返回 SQLCODE 和 SQLERRM 值,这些值是由您的过程执行时发生的任何异常产生的。这样,您可以通过检查 SQLCODE = 0 来检查是否成功完成。建议的更改用-- added
注释标记:
CREATE OR REPLACE PROCEDURE TrainInsertByParameter (p_ac2seat in number,
p_ac3seat in number,
p_ccseat in number,
p_sleeperseat in number,
p_secondseat in number,
p_date1 in date,
p_trainid in varchar2,
p_fare in number,
p_fromplace in varchar2,
p_toplace in varchar2,
p_class in varchar2,
p_trainname in varchar2,
p_successCnt out number,
p_sqlcode out number, -- added
p_sqlerrm out varchar2) -- added
IS
successCnt1 number(6) NOT NULL := 0;
rowUpdated1 number(6) NOT NULL := 0;
rowUpdated2 number(6) NOT NULL := 0;
rowUpdated3 number(6) NOT NULL := 0;
BEGIN
SAVEPOINT before;
INSERT INTO tbltrain
(ac2seat,ac3seat,acchaircarseat,sleeperseat,secondseat,date1,trainid)
VALUES
(p_ac2seat,p_ac3seat,p_ccseat,p_sleeperseat,p_secondseat,p_date1,p_trainid);
rowUpdated1 := SQL%RowCount;
successCnt1 := successCnt1 + 1;
dbms_output.put_line('Successful Insertion tbltrain. count ='||successCnt1);
dbms_output.put_line('Successful Insertion tbltrain. Row Updated ='||rowUpdated1);
INSERT INTO tbltraindetail
(trainid,trainname,from1,to1)
VALUES
(p_trainid,p_trainname,p_fromplace,p_toplace);
rowUpdated2 := SQL%RowCount;
successCnt1 := successCnt1 + 1;
dbms_output.put_line('Successful Insertion tbltraindetail. count ='||successCnt1);
dbms_output.put_line('Successful Insertion tbltraindetail. Row Updated= ' || rowUpdated2);
INSERT INTO tbltrainfare(trainid,class,fare) VALUES (p_trainid,p_class,p_fare);
rowUpdated3 := SQL%RowCount;
successCnt1 := successCnt1 + 1;
p_successCnt := successCnt1;
COMMIT;
dbms_output.put_line('Successful Insertion tbltrainfare. count ='||p_successCnt);
dbms_output.put_line('Successful Insertion tbltrainfare. Row Updated= '||rowUpdated3);
p_sqlcode := 0; -- added
p_sqlerrm := NULL; -- added
EXCEPTION
WHEN Others THEN
p_sqlcode := SQLCODE; -- added
p_sqlerrm := SQLERRM; -- added
DBMS_OUTPUT.PUT_LINE('Exception: ' || p_sqlcode || ' ' || SQLERRM); -- added
successCnt1 := 0;
p_successCnt := successCnt1;
dbms_output.put_line('An error has occured. count ='||p_successCnt);
ROLLBACK TO before;
END;
IMO 从另一个系统调用的任何 PL/SQL 过程返回 SQLCODE 和 SQLERRM 是一个好主意,因为它为您提供了一种一致的方法来确定是否发生了错误,并告诉您错误是什么。 YMMV。
分享和享受。
【讨论】:
我是 PL/SQL 的新手。我也想看看异常发生的原因,但不知道如何捕获错误消息。感谢您的快速回复。我现在将尝试您的代码,如果问题仍未解决,我会回复。 非常感谢!! 使用您添加的代码,我发现了我的错误并解决了它。我传递的 p_class1 值对于我的 tbltablefare 中的类字段来说太大了表..这就是存储过程中发生异常的原因。虽然我已经单独测试过,但我的 p_class1 值很小! 再次非常感谢您的快速回复!【参考方案2】:我自己没有亲自做过,但我怀疑你必须设置参数大小:
// cmd.Parameters.Add("p_successCnt", OracleType.Number).Direction = ParameterDirection.Output;
OracleParameter count = new OracleParameter("p_successCnt", OracleType.Number);
count.Direction = ParameterDirection.Output;
count.Size = 8;
cmd.Parameters.Add(count);
另请参阅:Oracle Store Procedure does not return any thing in the out parameter
【讨论】:
非常感谢您的代码.. 虽然如果 out 参数是数字,则参数大小可能不是必需的,但当 out 参数是 varchar 时,它是必需的。我首先使用了 Bob Jarvis 的代码,然后使用了您的代码,错误消息出现在我的屏幕上 :).. 感谢您的帮助!!以上是关于从后面的 C# 代码调用存储过程时插入语句不起作用的主要内容,如果未能解决你的问题,请参考以下文章
从存储过程调用时,PL SQL Execute Immediate 不起作用
使用存储过程执行时,executeUpdate() 不起作用