我有以下简单的类定义(Windows控制台应用程序):
预期的样本
using System;
namespace ConsoleApplication1 {
class Test: IDisposable {
string Text;
public Test(string str) {
Text = str;
}
public void print() {
Console.WriteLine("Text: " + Text);
}
public void Dispose() {
Text = "";
}
}
class Program {
static void Main(string[] args) {
string TeXT = "Data Source=localhost;Initial Catalog=master;";
using (Test test = new Test(TeXT)) {
test.print();
}
using (Test test = new Test(TeXT)) {
test.print();
}
Console.ReadKey();
}
}
}
在上面的示例中,我将string
传递给IDisposable
类test
。一旦代码超出范围,它就会被处理掉。正如预期的那样,第一次处理测试后没有触及局部变量TeXT
,并且可以像测试类一样访问第二个测试类实例。
现在这是真实的情景让我头疼了好几个小时。
实际结果
using System;
using System.Data;
using System.Data.SqlClient;
namespace ConsoleApplication1 {
class Test: IDisposable{
SqlConnection dbConn;
public Test(SqlConnection connection){
dbConn = connection;
}
public void print(){
Console.WriteLine("Connection" + dbConn.ConnectionString);
}
public void Dispose() {
dbConn.Dispose();
}
}
class Program {
static void Main(string[] args) {
SqlConnection sqlConn = new SqlConnection("Data Source=localhost;Initial Catalog=master;");
using(Test test = new Test(sqlConn)){
test.print();
}
using(Test test = new Test(sqlConn)){
test.print();
}
Console.ReadKey();
}
}
}
与我将SqlConnection
传递给test
类的第一个实例之前相同。处理完第一个实例后,SqlConnection
将丢失连接字符串。这使得它无法用于下一个类实例。
问题 为什么在第二种情况下我丢失了ConnectionString?这是一个错误还是故意的?是否有任何解决方案可以避免这种情况,除了与DB Server建立多个连接?我应该停止处理内部连接实例吗?
答案 0 :(得分:8)
当您处置SqlConection
时,您正在处置Test
- 但您正在尝试再次使用它。
最好的方法几乎总是在每次需要时创建一个新的SqlConnection
- 并在完成后立即处理它。您已经在做第二部分了,但是您应该为第二部分操作创建一个新的SqlConnection
实例。
请注意,不意味着必须与服务器建立多个连接 - .NET连接池将处理需要多少实际网络连接。
答案 1 :(得分:0)
为什么在第二种情况下我丢失了ConnectionString?
因为你的两个例子很少见。
在第一堂课的Dispose()
方法中,您设置了Text = "";
。这将改变您的班级所持有的参考,但不会改变Main()
,或其值的参考。因此TeXT
中的Main()
仍将保留您的连接字符串。
在第二个示例中,您在同一个实例上调用Dispose()
,即从sqlConn
传递的Main()
。
当您Dispose()
某个对象时,这并不意味着您无法调用方法或访问属性。一个类在处理它时究竟做了什么,每种类型都不同。对于SqlConnection
,它显然将其ConnectionString
属性设置为空字符串,其中包括将连接(如果有)返回到连接池。