Mik*_*ike 3 .net c# sql ado.net
我正在使用企业库和ADO的原始Fill方法的组合.这是因为我需要自己打开和关闭命令连接,因为我捕获事件信息消息
到目前为止,这是我的代码
// Set Up Command
SqlDatabase db = new SqlDatabase(ConfigurationManager.ConnectionStrings[ConnectionName].ConnectionString);
SqlCommand command = db.GetStoredProcCommand(StoredProcName) as SqlCommand;
command.Connection = db.CreateConnection() as SqlConnection;
// Set Up Events for Logging
command.StatementCompleted += new StatementCompletedEventHandler(command_StatementCompleted);
command.Connection.FireInfoMessageEventOnUserErrors = true;
command.Connection.InfoMessage += new SqlInfoMessageEventHandler(Connection_InfoMessage);
// Add Parameters
foreach (Parameter parameter in Parameters)
{
db.AddInParameter(command,
parameter.Name,
(System.Data.DbType)Enum.Parse(typeof(System.Data.DbType), parameter.Type),
parameter.Value);
}
// Use the Old Style fill to keep the connection Open througout the population
// and manage the Statement Complete and InfoMessage events
SqlDataAdapter da = new SqlDataAdapter(command);
DataSet ds = new DataSet();
// Open Connection
command.Connection.Open();
// Populate
da.Fill(ds);
// Dispose of the adapter
if (da != null)
{
da.Dispose();
}
// If you do not explicitly close the connection here, it will leak!
if (command.Connection.State == ConnectionState.Open)
{
command.Connection.Close();
}
Run Code Online (Sandbox Code Playgroud)
...
现在,如果我传入变量StoredProcName ="ThisProcDoesNotExists"
并运行这个代码.CreateCommand也不是da.Fill通过错误消息.为什么是这样.我可以告诉它没有运行的唯一方法是它返回一个包含0个表的数据集.但是在调查错误时,并不表示该程序不存在.
编辑进一步调查command.Connection.FireInfoMessageEventOnUserErrors = true; 导致错误被压缩到InfoMessage事件中
来自BOL
将FireInfoMessageEventOnUserErrors设置为true时,先前作为异常处理的错误现在将作为InfoMessage事件处理.所有事件立即触发并由事件处理程序处理.如果FireInfoMessageEventOnUserErrors设置为false,则在过程结束时处理InfoMessage事件.
我想要的是来自Sql的每个print语句来创建一个新的日志记录.将此属性设置为false会将其组合为一个大字符串.因此,如果我将属性设置为true,那么问题是我可以从错误中识别出打印消息
另一个编辑
所以现在我有了代码,以便将标志设置为true并检查方法中的错误号
void Connection_InfoMessage(object sender, SqlInfoMessageEventArgs e)
{
// These are not really errors unless the Number >0
// if Number = 0 that is a print message
foreach (SqlError sql in e.Errors)
{
if (sql.Number == 0)
{
Logger.WriteInfo("Sql Message",sql.Message);
}
else
{
// Whatever this was it was an error
throw new DataException(String.Format("Message={0},Line={1},Number={2},State{3}", sql.Message, sql.LineNumber, sql.Number, sql.State));
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在的问题是,当我抛出错误时,它不会冒泡到发出调用的语句,甚至是上面的错误处理程序.它只是轰炸了那条线
人口看起来像
// Populate
try
{
da.Fill(ds);
}
catch (Exception e)
{
throw new Exception(e.Message, e);
}
Run Code Online (Sandbox Code Playgroud)
现在即使我看到调用代码和方法仍然在调用堆栈中,这个异常似乎没有冒出来?
我花了一些时间在这上面得出结论,InfoMessageHandler不会在执行命令对象的范围内引发.因此,您在事件中抛出的异常不会冒泡到命令对象的方法.它必须在不同的线程中执行.
我假设您使用的是Visual Studio 2008,因为我能够在该环境中完全重现您的问题.当我将代码迁移到Visual Studio 2010时,仍然使用框架3.5,新的IDE捕获了自定义异常,但我无法找到一种简单的方法来捕获代码中的异常.Visual Studio 2010调试器在调试多个线程方面要好得多.
如果要捕获此事件的异常,则必须编写可以跟踪线程异常的代码.