由于代码重构而出现了一个问题,在这种情况下,最佳解决方案是什么?
问题是DbConnection是从本地方法变量重构为类变量的。 该应用程序是多线程的。 似乎问题是DbConnection对象在成员变量时被共享。 什么是最好的解决方案?把它作为一种本地方法变得可变吗?
public IDataReader Execute(CommandBehavior behavior, string[] parameterNames, object[] arguments)
{
DbConnection conn = null;
try
{
conn = Connection.CreateConnection();
DbCommand cmd = conn.CreateCommand();
cmd.CommandText = StoredProcedureName;
cmd.CommandType = CommandType.StoredProcedure;
// ..................................................
// Perform the call.
return DataCachingContext.SetCachedData(call, cmd.ExecuteReader(behavior));
}
catch (Exception ex)
{
//..........................
}
finally
{
//
}
}
只是为了澄清,这是导致问题的版本。有了运行时异常,索引到ResultSets的问题,这很可能是由于连接被覆盖。
DbConnection _conn = null;
public IDataReader Execute(CommandBehavior behavior, string[] parameterNames, object[] arguments)
{
try
{
_conn = Connection.CreateConnection();
DbCommand cmd = _conn.CreateCommand();
cmd.CommandText = StoredProcedureName;
cmd.CommandType = CommandType.StoredProcedure;
// ..................................................
// Perform the call.
return DataCachingContext.SetCachedData(call, cmd.ExecuteReader(behavior));
}
catch (Exception ex)
{
//..........................
}
finally
{
//
}
}
经过更多调查后,看起来DbConnection变量成为一个类变量来启用单元测试。当它是局部变量时,无法测试它的值。正在测试DbConnection的状态
答案 0 :(得分:4)
我认为您正在寻找lock statement
lock确保一个线程不进入代码的关键部分,而另一个线程处于临界区。如果另一个线程试图输入一个锁定的代码,它将等待,阻止,直到该对象被释放。
答案 1 :(得分:1)
数据库连接对象通常应该是局部变量,因为数据库连接是一种相对昂贵的资源,可以在任何时间内保持打开状态。将数据库连接作为类变量的危险在于,在实例化对象时将打开连接,然后在处理类之前保持打开状态。这可能导致锁定未及时释放,以及长时间运行的事务,这会严重影响性能。
最好在需要之前打开连接(例如,调用存储过程,执行SQL语句),然后立即关闭/处理它。在封面下,数据库连接通常都会被缓存,这可以最大限度地减少重复打开和关闭连接的开销,因为当您在代码中打开连接时,您可能会从缓存中获得已打开的连接。
答案 2 :(得分:1)
该应用程序是多线程的。似乎问题是DbConnection对象在成员变量时被共享。什么是最好的解决方案?把它作为一种本地方法变得可变吗?
是的,使用DbConnection
的一个好方法是在方法中创建和处理连接(将其存储在局部变量中)。在幕后,连接被汇集在一起,所以这样做没有明显的开销。您还可以避免处理共享状态和锁定。
问题中提供的代码完全符合我在此描述的内容。
答案 3 :(得分:1)
MSDN文档在DbConnection
上说:
不保证所有实例成员都是线程安全的。
因此,在我看来,将它作为一个类变量并不是一个好主意。即使您的实现可能是线程安全的,但假设这样做也是冒险的。您可以使用锁来避免线程问题,但这些方法通常会导致严重的扩展。因此,最好将对象保持在本地。
如果您在打开和关闭太多连接的情况下担心性能,请查看SQL Server Connection Pooling (ADO.NET),它可以很好地汇集实际连接,而不是DbConnection
个对象。< / p>
答案 4 :(得分:0)
在两个代码段中,您都可以创建新的Connection。那么将连接作为类变量的意图是什么?从您发布的代码中,看起来连接应该是局部变量。