当我选择Analyze>关于Visual Studio 2013中的解决方案的RUn代码分析,我得到,“ CA2202不要多次处置对象对象'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.Close();”
,则警告声称FileStream正在关闭两次虽然我没有肯定地反驳这一点,但我对此提出质疑,因为我认为它并未在其他地方关闭。
毕竟,它不在“使用”块中,所以它是如何被关闭的?
问题是:我应该删除那行代码(“fs.Close();”)吗?
注意:Resharper并没有对此表示怀疑 - 用“fs.Close();”无论是进出,它都不会引起任何警告标志。
答案 0 :(得分:4)
坦率地说,你不应该明确关闭这些流,你应该使用using
块。
无论如何,它会向您发出警告,因为该流已经关闭。当读者/编写者包装流时,关闭它们也将关闭基础流。一些读者/作者可以选择让流保持打开状态。
在您的特定情况下,您可以使用File
课程中提供的其他一些方法一举两得。请考虑使用File.ReadAllBytes()
来读取您的文件。
答案 1 :(得分:3)
想要补充一点,它仍然是无用的警告。我从未看到IDisposable
的任何实现,当您多次调用Dispose时会抛出ObjectDisposedException
。实际上在IDisposable.Dispose
的文档中写了以下内容:
如果多次调用对象的Dispose方法,则该对象必须忽略第一个之后的所有调用。如果多次调用Dispose方法
,则该对象不得抛出异常
但是,你在你的流上调用Close,而不是Dispose,虽然在这种情况下它是相同的,但一般来说你确实不应该在被处置对象上调用任何非Dispose方法,所以至少改变Close to处置(或更好地包装所有使用)。