我有一个查询通过SqlDataReader
获取报告数据,并将SqlDataReader
发送到将内容导出到.CSV
文件的方法;但是,列名称在.CSV
文件中以它们在数据库中出现的方式显示,这是不理想的。
我不想改变查询本身(更改名称以包含空格),因为此查询在另一个映射到对象的位置调用,空格不起作用。我宁愿不创建重复的查询,因为维护可能会有问题。我也不想修改写出.CSV
的方法,因为这是一种全局使用的方法。
我可以在填写数据阅读器之后但在将其发送到.CSV
方法之前修改列名吗?如果是这样,怎么样?
如果我不能这样做,如果它是DataTable
,我可以这样做吗?
以下是一般流程:
public static SqlDataReader RunMasterCSV(Search search)
{
SqlDataReader reader = null;
using (Network network = new Network())
{
using (SqlCommand cmd = new SqlCommand("dbo.MasterReport"))
{
cmd.CommandType = CommandType.StoredProcedure;
//Parameters here...
network.FillSqlReader(cmd, ref reader);
<-- Ideally would like to find a solution here -->
return reader;
}
}
}
public FileInfo CSVFileWriter(SqlDataReader reader)
{
DeleteOldFolders();
FileInfo file = null;
if (reader != null)
{
using (reader)
{
var WriteDirectory = GetExcelOutputDirectory();
double folderToSaveInto = Math.Ceiling((double)DateTime.Now.Hour / Folder_Age_Limit.TotalHours);
string uploadFolder = GetExcelOutputDirectory() + "\\" + DateTime.Now.ToString("ddMMyyyy") + "_" + folderToSaveInto.ToString();
//Add directory for today if one does not exist
if (!Directory.Exists(uploadFolder))
Directory.CreateDirectory(uploadFolder);
//Generate random GUID fileName
file = new FileInfo(uploadFolder + "\\" + Guid.NewGuid().ToString() + ".csv");
if (file.Exists)
file.Delete();
using (file.Create()) { /*kill the file stream immediately*/};
StringBuilder sb = new StringBuilder();
if (reader.Read())
{
//write the column names
for (int i = 0; i < reader.FieldCount; i++)
{
AppendValue(sb, reader.GetName(i), (i == reader.FieldCount - 1));
}
//write the column names
for (int i = 0; i < reader.FieldCount; i++)
{
AppendValue(sb, reader[i] == DBNull.Value ? "" : reader[i].ToString(), (i == reader.FieldCount - 1));
}
int rowcounter = 1;
while (reader.Read())
{
for (int i = 0; i < reader.FieldCount; i++)
{
AppendValue(sb, reader[i] == DBNull.Value ? "" : reader[i].ToString(), (i == reader.FieldCount - 1));
}
rowcounter++;
if (rowcounter == MaxRowChunk)
{
using (var sw = file.AppendText())
{
sw.Write(sb.ToString());
sw.Close();
sw.Dispose();
}
sb = new StringBuilder();
rowcounter = 0;
}
}
if (sb.Length > 0)
{
//write the last bit
using (var sw = file.AppendText())
{
sw.Write(sb.ToString());
sw.Close();
sw.Dispose();
sb = new StringBuilder();
}
}
}
}
}
return file;
}
答案 0 :(得分:1)
我会尝试重构你的CSVFileWriter。
首先你应该添加一个委托声明
public delegate string onColumnRename(string);
然后创建CSVFileWriter的重载,将代理与读者一起传递
public FileInfo CSVFileWriter(SqlDataReader reader, onColumnRename renamer)
{
// Move here all the code of the old CSVFileWriter
.....
}
将以前的CSVFileWriter的代码移动到新方法,并从旧方法调用新方法
public FileInfo CSVFileWriter(SqlDataReader reader)
{
// Pass null for the delegate to the new version of CSVFileWriter....
return this.CSVFileWriter(reader, null)
}
这将使旧方法的现有客户满意。对他们来说没有任何改变.....
在新版本的CSVFileWriter中,您可以更改准备列名称的代码
for (int i = 0; i < reader.FieldCount; i++)
{
string colName = (renamer != null ? renamer(reader.GetName(i))
: reader.GetName(i))
AppendValue(sb, colName, (i == reader.FieldCount - 1));
}
现在只需要创建一个可以翻译列名的重命名函数
private string myColumnRenamer(string columnName)
{
if(columnName == "yourNameWithoutSpaces")
return "your Name with Spaces";
else
return text;
}
这可以使用静态字典进行优化,以删除ifs列表
此时你可以调用新的CSVFileWriter传递你的函数
FileInfo fi = CSVFileWrite(reader, myColumnRenamer);