当我在Visual Studio 2013中选择"分析> RUn Code Analysis on Solution"时,我得到"CA2202 不要多次释放对象 Object 'fs' 可以在方法 'RoboReporterSQL.SaveReportDataToDB(string, string)' 中多次释放。为了避免生成 System.ObjectDisposedException,您不应该在一个对象上多次调用 Dispose 。
指示的代码行为:
fs.Close();
这是上下文中的代码:
internal static void SaveReportDataToDB(string filename, string
RESTFilename)
{
if (RecordAlreadyExists(RESTFilename)) return;
string EXCEL_FILE = "application/vnd.ms-excel";
DateTime begDate =
RoboReporterConstsAndUtils.GetBeginDate(RESTFilename);
DateTime endDate =
RoboReporterConstsAndUtils.GetEndDate(RESTFilename);
var fs = new FileStream(filename, FileMode.Open, FileAccess.Read);
BinaryReader br = new BinaryReader(fs);
Byte[] bytes = br.ReadBytes((Int32)fs.Length);
br.Close();
fs.Close();
using (var sqlConn = new SqlConnection(CPSConnStr))
{
var insertStr = "INSERT INTO ReportsGenerated (FileBaseName,
ContentType, BinaryData, BeginDate, EndDate) " +
"VALUES (@FileBaseName, @ContentType,
@BinaryData, @BeginDate, @EndDate)";
using (var insertRptsGenerated = new SqlCommand(insertStr))
{
insertRptsGenerated.Connection = sqlConn;
insertRptsGenerated.Parameters.Add("@FileBaseName",
SqlDbType.VarChar, 100).Value = RESTFilename;
insertRptsGenerated.Parameters.Add("@ContentType",
SqlDbType.VarChar, 50).Value = EXCEL_FILE;
insertRptsGenerated.Parameters.Add("@BinaryData",
SqlDbType.Binary).Value = bytes;
insertRptsGenerated.Parameters.Add("@BeginDate",
SqlDbType.DateTime).Value = begDate;
insertRptsGenerated.Parameters.Add("@EndDate",
SqlDbType.DateTime).Value = endDate;
sqlConn.Open();
insertRptsGenerated.ExecuteNonQuery();
}
}
}
因此,警告声称如果我调用"fs",则文件流正在关闭两次。关闭();"
虽然我没有肯定地反驳这一点,但我质疑它,因为我不认为它在其他地方关闭。
毕竟,它不在"使用"块中,那么它是如何关闭的呢?
问题是:我真的应该删除那行代码("fs.关闭();")?
注意:Resharper 对此没有抱怨 - 用"fs.关闭();" 输入或输出,无论哪种方式都不会引发警告标志。
坦率地说,你不应该显式关闭这些流,你应该使用using
块。
无论如何,它会给您该警告,因为流已经关闭。 当读取器/写入器包装流时,关闭它们也会关闭基础流。 但是,某些阅读器/编写器为您提供了使流保持打开状态的选项。
在您的特定情况下,您可以使用 File
类中可用的其他一些方法用一块石头杀死两只鸟。 请考虑使用 File.ReadAllBytes()
读取文件。
想补充一点,它仍然是相当无用的警告。我从未见过任何IDisposable
的实现,当您多次调用 Dispose 时会抛出ObjectDisposedException
。实际上,在IDisposable.Dispose
的文档中,编写了以下内容:
如果多次调用对象的 Dispose 方法,则该对象必须忽略第一个调用之后的所有调用。如果多次调用对象的 Dispose 方法,则不得引发异常
但是,您在流上调用 Close,而不是 Dispose,虽然在这种情况下它是相同的,但一般来说,您确实不应该在已释放的对象上调用任何非 Dispose 方法,因此至少将 Close 更改为 Dispose(或更好地包装所有使用)。