使用与DbTransactions组合的DbDataReader,它的方式是否错误或性能不足?代码示例:
public DbDataReader ExecuteReader()
{
try
{
if (this._baseConnection.State == ConnectionState.Closed)
this._baseConnection.Open();
if (this._baseCommand.Transaction != null)
return this._baseCommand.ExecuteReader();
return this._baseCommand.ExecuteReader(CommandBehavior.CloseConnection);
}
catch (Exception excp)
{
if (this._baseCommand.Transaction != null)
this._baseCommand.Transaction.Rollback();
this._baseCommand.CommandText = string.Empty;
this._baseConnection.Close();
throw new Exception(excp.Message);
}
}
有些方法会调用此操作。有时打开DbTransaction。它使用DbConnection和DbCommand。
真正的问题是,在生产环境中(如5000访问/天)ADO操作开始抛出异常
它有一个方法,它不会打开DbTransaction,但无论如何都会抛出excp。
编辑:我们实施了日志,以分析ADO操作。这是一种在生产环境中捕捉ADO问题的方法。捕获的例外情况是:
已经有一个与此命令关联的打开DataReader,必须先关闭它。
读取器关闭时无效尝试调用Read。
连接未关闭。连接的当前状态是打开的。
另外,我们意识到dbHelper类是以这种方式实例化的:
private static readonly dbHelper<T> _instance = new dbHelper<T>();
public static dbHelper<T> GetInstance()
{
return _instance;
}
DAO的构造函数,实例化dbHelper:
this._dataPersist =
Registro.Classes.dbHelper<System.Data.SqlClient.SqlClientFactory>.GetInstance();
我们认为更改数据访问代码,用另一种方法替换通用dbHelper可能会解决问题。任何建议将不胜感激。
答案 0 :(得分:1)
一个潜在的问题是DbTransaction,DbConnection及其同类都是抽象类。在某些时候,您需要提供这些类型的真实具体实现。尽管如此,编译器会抓住这个问题,这让我感到震惊,但我认为这仍然值得一提。
更有可能的是,你将连接打开的时间太长了。阅读你粗体的句子,我留下的印象是生产代码最初不会抛出异常。例外情况只有在你让它运行一段时间之后才出现。这也与您发布的代码相匹配,因为在您的小共享代码中我已经看到两个地方您的代码无法正确清理它的资源。
如果在回滚事务时抛出异常,则执行读取器功能将不会关闭基本连接。此外,您在问题末尾发布的代码段可能无法正确关闭阅读器。处理资源的正确方法是使用using块,如下所示:
using (var reader = this._dataPersist.ExecuteReader(true))
{
/* populate the obj here
* */
}
return obj;
请注意,无需调用Close()或Dispose()方法。 using块会为你处理,即使抛出异常也会 。