0

由于代码重构而出现了问题,在这种情况下最好的解决方案是什么?

问题是 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 的状态

4

5 回答 5

4

我认为您正在寻找lock 语句

lock 确保一个线程不进入代码的临界区,而另一个线程在临界区。如果另一个线程试图输入一个锁定的代码,它将等待、阻塞,直到对象被释放。

于 2012-08-13T14:53:13.280 回答
1

MSDN 文档说DbConnection

不保证任何实例成员都是线程安全的。

因此,在我看来,将其保留为类变量并不是一个好主意。即使您的实现可能是线程安全的,但假设这样是有风险的。您可以使用锁来避免线程问题,但这些方法通常难以扩展。因此,最好将对象保持在本地。

如果您担心总是打开和关闭太多连接的性能,请查看SQL Server Connection Pooling (ADO.NET),它可以很好地池化实际连接而不是DbConnection对象。

于 2012-08-13T15:06:04.033 回答
1

该应用程序是多线程的。似乎问题在于 DbConnection 对象在它是成员变量时被共享。什么是最好的解决方案?将其保留为本地方法变量?

是的,一个好的使用模式DbConnection是在方法中创建和处理连接(将其存储在局部变量中)。在幕后,连接是池化的,因此这样做没有显着的开销。您还可以避免处理共享状态和锁。

问题中提供的代码完全符合我在此处描述的内容。

于 2012-08-13T15:03:11.880 回答
1

数据库连接对象通常应该是局部变量,因为数据库连接是一种相对昂贵的资源,要保持打开任何时间长度。将数据库连接作为类变量的危险在于,在实例化对象时会打开连接,然后在释放类之前保持打开状态。这会导致锁没有被及时释放,以及长时间运行的事务,这会严重影响性能。

最好在需要之前打开连接(例如,调用存储过程、执行 SQL 语句),然后立即关闭/释放它。在幕后,数据库连接通常无论如何都会被缓存,这样可以最大限度地减少重复打开和关闭连接的开销,因为当您在代码中打开一个连接时,您很可能会从缓存中获得一个已经打开的连接。

于 2012-08-13T15:01:44.087 回答
0

在这两个代码片段中,您都创建了新的连接。那么将连接作为类变量的意图是什么?从您发布的代码看来,连接应该是局部变量。

于 2012-08-13T15:46:14.777 回答