关于处置SqlConnection
的警告很少。
这是我的代码:
public Dictionary<string, MyObject> GetGrpDataFromDB(string btnGrp)
{
Globals glob = new Globals();
using (SqlConnection Connection = new SqlConnection((glob.Comms())))
{
SqlCommand sql = new SqlCommand("SELECT BrzaGrupaBroj,BrzaGrupaNaziv,BrzaGrupaColor FROM BrzaGrupaGUI", Connection);
using (SqlDataAdapter adapter = new SqlDataAdapter(sql))
{
DataTable dt = new DataTable();
try
{
Connection.Open();
adapter.Fill(dt);
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
finally
{
Connection.Close();
}
var myDictionary = new Dictionary<string, MyObject>();
foreach (DataRow row in dt.Rows)
{
var newObject = new MyObject(row);
myDictionary.Add(newObject.brzaGrpBr , newObject);
}
return myDictionary;
}
}
}
这是确切的警告:
Warning CA2202 Object 'Connection' can be disposed more than once in method 'GetGrpRowsDB.GetGrpDataFromDB(string)'. To avoid generating a System.ObjectDisposedException you should not call Dispose more than one time on an object.
如何仅处置SqlConnection
一次,以便摆脱这些警告? :)
编辑:
我尝试不使用Try Catch Finnaly,但即使这样,我也得到完全相同的警告。也许我找错地方了?
public Dictionary<string, MyObject> GetGrpDataFromDB(string btnGrp)
{
Globals glob = new Globals();
using (SqlConnection Connection = new SqlConnection((glob.Comms())))
{
SqlCommand sql = new SqlCommand("SELECT BrzaGrupaBroj,BrzaGrupaNaziv,BrzaGrupaColor FROM BrzaGrupaGUI", Connection);
using (SqlDataAdapter adapter = new SqlDataAdapter(sql))
{
DataTable dt = new DataTable();
Connection.Open();
adapter.Fill(dt);
Connection.Close();
var myDictionary = new Dictionary<string, MyObject>();
foreach (DataRow row in dt.Rows)
{
var newObject = new MyObject(row);
myDictionary.Add(newObject.brzaGrpBr , newObject);
}
return myDictionary;
}
}
}
答案 0 :(得分:2)
IDisposable
接口被专门记录为:所有实现均应支持任意次数的处置,并且在调用Dispose
时也不会出错(即使在重复调用时也是如此)。处置它们后,您可能会误以为您会使用它们,但是如果您多次处置它们,则不会出错。如果该对象实际上在第二次dispose调用上抛出了一个对象处置异常,则该错误将在该类中,而不是您的类别中(我强烈怀疑连接类的作者编写了这样的错误)。
没有特别的理由多次处理资源。如果需要,请务必除去多余的处置物,以避免冗余。 (在这种情况下,关闭连接是最有意义的删除方式,这样,创建命令或适配器的任何问题都不会泄漏连接。)
这不是实际的编译器警告,它只是代码分析语句,不幸的是,许多语句实际上并不表示存在问题的迹象。我建议只禁用该警告,因为这完全是错误的。
答案 1 :(得分:2)
如Servy所述,这很可能只是代码分析警告,可以忽略。
现在对代码进行一些偏离主题的建议改进:
避免在标识符中使用缩写。它使您的代码更难以阅读和理解。
您可以将using
语句链接在一起以减少不必要的嵌套。
SqlCommand
也实现了IDisposable
;它需要一个using
语句。
当类型明显时,您可以使用var
。
未使用btnGroup
参数,可以将其删除。
总是在您的任何更明确的catch (Exception ex)
语句之后添加catch
。否则,将捕获并吞下非SqlException
。
这是您的代码经过一些重构后的样子:
public Dictionary<string, MyObject> GetGroupDataFromDatabase()
{
var globals = new Globals();
using (var sqlConnection = new SqlConnection((globals.Comms()))) // If you can, I'd rename Comms too.
using (var sqlCommand = new SqlCommand("SELECT BrzaGrupaBroj, BrzaGrupaNaziv, BrzaGrupaColor FROM BrzaGrupaGUI", sqlConnection))
using (var sqlAdapter = new SqlDataAdapter(sqlCommand))
{
var dataTable = new DataTable();
try
{
sqlConnection.Open();
sqlAdapter.Fill(dataTable);
}
catch (SqlException ex)
{
MessageBox.Show(ex.Message);
}
// Without this, sqlConnection.Open() could throw an InvalidOperationException
// and you would never know.
catch (Exception ex)
{
// Do something with the exception, like logging
}
var myDictionary = new Dictionary<string, MyObject>();
foreach (var row in dataTable.Rows)
{
var newObject = new MyObject(row);
myDictionary.Add(newObject.brzaGrpBr, newObject);
}
return myDictionary;
}
}
答案 2 :(得分:0)
您可以摆脱代码中的finally块。您将Connection
对象的创建包装在using语句中,因此,当作用域离开using块时,它将自动为您处理Connection
变量。
您可以使用using语句,也可以使用try / catch / finally关闭连接,但不能同时关闭两者