使用OleDbDataAdapter保存数据时,如何获取触发器返回的信息?

PB_QuickGun 2009-05-05 05:10:57
例如:某个用户表,s_user ,有一个删除触发器,如果该用户正在使用,则不允许删除。

那么在程序中,代码如下:

其中类型分别为:
OleDbDataAdapter oleda_master
DataSet ids

try
{
li_row = oleda_master.Update(ids.GetChanges(), "master");
ids.AcceptChanges();
}
catch (Exception ex)
{
string ls_error = ex.Message.ToString();
ids.RejectChanges();
g.gole_conn.Close();
MessageBox.Show("数据删除失败!\r\n\r\n" + ls_error, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}

那么在 ls_error 中获取到的信息是:未指定的错误。

而我的触发器中明确地raiserror一个很详细的信息,但是就是没有办法获取该触发器的信息。

首先声明,我在删除一个不在用的用户时,数据是可以保存成功的。这个保存的过程是没有问题。

请问大侠们,这个如何获取?是 Exception 用得不对,还是什么?也尝试过 DBConcurrencyException 还是不行。

谢谢指教!!!
...全文
188 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
PB_QuickGun 2009-05-09
  • 打赏
  • 举报
回复
终于搞清楚了,还是楼上 superzxf 一语惊醒梦中人啊!

在SQL2000中,raiserror必须指定错误级别大于10才能让try捕捉到,

对于低于10的错误级别,或者沿用SQLServer7以前的 [ raiserror 20028 '错误信息' ] 这样的语法,同样是捕捉不到,

必须是使用 [ raiserror('错误信息', 16, 1) ] 这样的语法才行,而且错误级别必须大于10。

非常感谢楼上各位大侠!
书屋清茶 2009-05-08
  • 打赏
  • 举报
回复
哦,楼上有意思学习PB么,这个可是C#阵营哦,呵呵。

既然有人顶,怎么也得贴点代码出来。

删除有两种方式,

一种通过datawindow直接操作,如下:

Long ll_currow
Integer li_rtn
ll_currow = dw_1.GetRow() // 例如删除当前行
if ll_currow < 1 then
return
end if
dw_1.DeleteRow(ll_currow)
li_rtn = dw_1.Update() // 注解 A
IF li_rtn = -1 THEN
RETURN
END IF

注解 A
在这个update过程中,如果有触发器防止删除,系统自动就弹出一个对话框,
把触发器的详细信息以及涉及到的SQL语句通通列出来,非常的详细。一看就知道是哪个地方出问题了。

如果你想把这个触发器的信息处理得更好,可以在 dw_1 的 dberror 事件中,
将错误信息 sqlerrtext 自己处理一下,然后 return 1 ,那么就不会弹出系统的对话框,而是
你自己经过处理的MessageBox消息。

另外一种方式是直接通过SQL语句的,那就更简单了,
执行一个SQL语句后,直接判断 SQLCA.SQLCODE 的值就知道是否有问题,一般:

IF SQLCA.SQLCODE <> 0 THEN
ls_error = SQLCA.SQLERRTEXT
ROLLBACK USING SQLCA;
MessageBox("提示", "数据操作失败!~r~n~r~n错误信息:" + ls_error, StopSign!)
RETURN
END IF



uncleson88 2009-05-08
  • 打赏
  • 举报
回复
LZ 用 PB 是怎么做的呢?能不能贴上来?偶学习学习
PB_QuickGun 2009-05-08
  • 打赏
  • 举报
回复
丁页人尔 ... 依然没人解决得了 …… 难怪我的结贴率那么低,都没人能给出个答案。。郁闷!!!
superzxf 2009-05-08
  • 打赏
  • 举报
回复
楼主数据保存成功,因为raiserror引发的错误级别太低,系统不认为是一个错误,故用try是捕捉不到的
因该提高raiserror的级别,如raiserror('xxxxx',18,1),这样系统才能捕捉错误并rollback回滚
如果既要成功保存,又要返回错误是不可能的,除非用存储过程,通过select语句作为结果集返回操作结果信息
Garnett_KG 2009-05-08
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 PB_QuickGun 的回复:]
楼上的高手 Garnett_KG ,非常感谢你!

你的答案是对的。但有一个条件是数据库是 MSSQL2005 。

而同样的代码,同样的表和触发器,在 MSSQL2000 中还是不能获取到相关信息。

估计是新版本的开发工具与旧数据库的兼容性有点问题吧。

如果真的是这样的话,难道只能升级数据库?

如果这样的话,估计Linux下老版本的Sybase估计会有同样的问题哦。

再研究一下。。。

[/Quote]

很奇怪,我用的是SQL2000啊,而且还是还没打SP4的.

SELECT @@VERSION
----------------------------------------------------------------------
Microsoft SQL Server 2000 - 8.00.194 (Intel X86) Aug 6 2000 00:57:48 Copyright (c) 1988-2000 Microsoft Corporation Personal Edition on Windows NT 5.1 (Build 2600: )


zzxap 2009-05-08
  • 打赏
  • 举报
回复
触发器错误信息可以用catch
zzxap 2009-05-08
  • 打赏
  • 举报
回复
cmd.Parameters.Add("@Amount", SqlDbType.Decimal).Direction=ParameterDirection.Output;
zzxap 2009-05-08
  • 打赏
  • 举报
回复
如果要获取返回值就用存储过程。

[code=C#]
1.获取Return返回值


程序代码
//存储过程
//Create PROCEDURE MYSQL
// @a int,
// @b int
//AS
// return @a + @b
//GO
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ToString());
conn.Open();
SqlCommand MyCommand = new SqlCommand("MYSQL", conn);
MyCommand.CommandType = CommandType.StoredProcedure;
MyCommand.Parameters.Add(new SqlParameter("@a", SqlDbType.Int));
MyCommand.Parameters["@a"].Value = 10;
MyCommand.Parameters.Add(new SqlParameter("@b", SqlDbType.Int));
MyCommand.Parameters["@b"].Value = 20;
MyCommand.Parameters.Add(new SqlParameter("@return", SqlDbType.Int));
MyCommand.Parameters["@return"].Direction = ParameterDirection.ReturnValue;
MyCommand.ExecuteNonQuery();
Response.Write(MyCommand.Parameters["@return"].Value.ToString());

2.获取Output输出参数值

程序代码
//存储过程
//Create PROCEDURE MYSQL
// @a int,
// @b int,
// @c int output
//AS
// Set @c = @a + @b
//GO
SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ToString());
conn.Open();
SqlCommand MyCommand = new SqlCommand("MYSQL", conn);
MyCommand.CommandType = CommandType.StoredProcedure;
MyCommand.Parameters.Add(new SqlParameter("@a", SqlDbType.Int));
MyCommand.Parameters["@a"].Value = 20;
MyCommand.Parameters.Add(new SqlParameter("@b", SqlDbType.Int));
MyCommand.Parameters["@b"].Value = 20;
MyCommand.Parameters.Add(new SqlParameter("@c", SqlDbType.Int));
MyCommand.Parameters["@c"].Direction = ParameterDirection.Output;
MyCommand.ExecuteNonQuery();
Response.Write(MyCommand.Parameters["@c"].Value.ToString());
---------------------------------------------------------------------------------------------------------------

以下代码转自网络:

C#接收存储过程返回值:

public static int User_Add(User us)
{
int iRet;
SqlConnection conn = new SqlConnection(Conn_Str);
SqlCommand cmd = new SqlCommand("User_Add", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@UName", us.UName);
cmd.Parameters.AddWithValue("@UPass", us.UPass);
cmd.Parameters.AddWithValue("@PassQuestion", us.PassQuestion);
cmd.Parameters.AddWithValue("@PassKey", us.PassKey);
cmd.Parameters.AddWithValue("@Email", us.Email);
cmd.Parameters.AddWithValue("@RName", us.RName);
cmd.Parameters.AddWithValue("@Area", us.Area);
cmd.Parameters.AddWithValue("@Address", us.Address);
cmd.Parameters.AddWithValue("@ZipCodes", us.ZipCodes);
cmd.Parameters.AddWithValue("@Phone", us.Phone);
cmd.Parameters.AddWithValue("@QQ", us.QQ);
cmd.Parameters.Add("@RETURN_VALUE", "").Direction = ParameterDirection.ReturnValue;
try
{
conn.Open();
cmd.ExecuteNonQuery();
iRet = (int)cmd.Parameters["@RETURN_VALUE"].Value;
}
catch (SqlException ex)
{
throw ex;
}
finally
{
conn.Close();
}
return iRet;
}

C#接收存储过程输出参数:

public static decimal Cart_UserAmount(int UID)
{
decimal iRet;
SqlConnection conn = new SqlConnection(Conn_Str);
SqlCommand cmd = new SqlCommand("Cart_UserAmount", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("@UID", UID);
cmd.Parameters.Add("@Amount", SqlDbType.Decimal).Direction=ParameterDirection.Output;
try
{
conn.Open();
cmd.ExecuteNonQuery();
iRet = (decimal)cmd.Parameters["@Amount"].Value;
}
catch (SqlException ex)
{
throw ex;
}
finally
{
conn.Close();
}
return iRet;
}
[/CODE]
gyouyang 2009-05-08
  • 打赏
  • 举报
回复
板凳
十八道胡同 2009-05-08
  • 打赏
  • 举报
回复
帮顶
PB_QuickGun 2009-05-08
  • 打赏
  • 举报
回复
楼上的高手 Garnett_KG ,非常感谢你!

你的答案是对的。但有一个条件是数据库是 MSSQL2005 。

而同样的代码,同样的表和触发器,在 MSSQL2000 中还是不能获取到相关信息。

估计是新版本的开发工具与旧数据库的兼容性有点问题吧。

如果真的是这样的话,难道只能升级数据库?

如果这样的话,估计Linux下老版本的Sybase估计会有同样的问题哦。

再研究一下。。。
Garnett_KG 2009-05-08
  • 打赏
  • 举报
回复
我试过是可以捕捉到raiserror的信息啊。
不知你是如何做的.


CREATE TRIGGER trg ON tb
FOR UPDATE
AS
BEGIN
RAISERROR('错误!不允许删除',16,1)
ROLLBACK
END




static void Main(string[] args)
{

OleDbConnection cn = new OleDbConnection();
OleDbDataAdapter da = new OleDbDataAdapter();
OleDbCommand sel = new OleDbCommand();

cn.ConnectionString = "Provider=SQLOLEDB;UID=sa;PWD=var'123;Initial catalog=tempdb; Data source=NIPSAN";
cn.Open();


sel.CommandText = "SELECT * FROM tb";
sel.Connection = cn;
da.SelectCommand = sel;

OleDbCommandBuilder builder = new OleDbCommandBuilder();
builder.DataAdapter = da;
da.UpdateCommand = builder.GetUpdateCommand();


DataSet ds = new DataSet();
da.Fill(ds,"tb");
//change value
ds.Tables["tb"].Rows[0]["Company"] = "a";
try
{
da.Update(ds.GetChanges(), "tb");
}
catch (OleDbException e)
{
Console.WriteLine(e.Message);
}
finally
{
cn.Close();
}
Console.ReadLine();
}
/*
错误!不允许删除
事务在触发器中结束。批处理已中止。
*/



KKND2006 2009-05-08
  • 打赏
  • 举报
回复
把业务写在触发器里面本身就是很糟糕的设计

这种过时的设计只会出现在OO设计还不完善的早期项目里面

现在做项目就要改过来了
PB_QuickGun 2009-05-08
  • 打赏
  • 举报
回复
up
悔说话的哑巴 2009-05-07
  • 打赏
  • 举报
回复
楼主不知道这样可以不:你在用户登录是给他做个标记,然后来删除,我基本就是这样做的
benbenkui 2009-05-07
  • 打赏
  • 举报
回复
删除...,如果该用户正在使用,则不允许删除
这个可以用锁.
benbenkui 2009-05-07
  • 打赏
  • 举报
回复
UP,没用过触发器返回信息.
PB_QuickGun 2009-05-07
  • 打赏
  • 举报
回复
up
tsp860901 2009-05-07
  • 打赏
  • 举报
回复
学习。。。
加载更多回复(5)

111,126

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Creator Browser
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧