我正在构建一个每月读取5个CSV文件的系统。这些文件应该遵循某种格式和顺序。我有一个主表和5个临时表。首先读取每个CSV文件,然后将其批量插入其对应的临时表中。将5个csv文件批量插入各自的临时表后,我再次将临时表中的所有记录插入到主表中。这可确保在将数据插入主表之前先上载所有文件。
我使用ASP.net构建了这个系统,在调试和测试期间一切都很顺利。每当我将应用程序部署到生产服务器时,就会出现问题。部署应用程序后,我使用了在开发和测试期间上传的相同csv文件,系统显示了从字符串到日期时间格式的数据转换错误。
我尝试了很多东西来解决这个问题,但似乎问题仍然存在。我尝试将生产数据库的排序规则更改为我在开发期间使用的排序规则。我还尝试更改生产服务器中的某些区域设置,但它仍然无效。
我想也许我可以以编程方式处理这个问题,而不是从临时表批量插入到主表中,我会写一些for循环,它会将每个记录手动插入主表,但是我想它会因为我每次都会插入大约100,000条记录,所以会产生性能问题。
我想知道是否有人在部署期间遇到过类似的问题。对我来说,部署后应用程序的行为发生了变化,这似乎很奇怪。
以下是代码的一部分,它将inventory.csv文件上载到服务器,然后将csv批量插入临时表TB_TEMP_INVENTORY,然后将记录从temp插入主表TB_CATTLE。这是对其他4个文件完成的,几乎与此相同。
OleDbConnection conn = new OleDbConnection(ConfigurationManager.AppSettings["LivestockConnectionString"]);
OleDbCommand comm;
OleDbDataAdapter adapter;
DataTable table = new DataTable();
string file = string.Empty;
string content = string.Empty;
StreamReader reader;
StreamWriter writer;
string month = monthDropDownList.SelectedValue;
string year = yearDropDownList.SelectedItem.Text;
// upload inventory file
file = System.IO.Path.GetFileName(inventoryFileUpload.PostedFile.FileName);
inventoryFileUpload.PostedFile.SaveAs("C://LivestockCSV//" + file);
// clean inventory file
file = "C://LivestockCSV//" + file;
reader = new StreamReader(file);
content = reader.ReadToEnd();
reader.Close();
writer = new StreamWriter(file);
writer.Write(content.Replace("\"", "")); // remove quotation
writer.Close();
writer = new StreamWriter(file);
writer.Write(content.Replace(",NULL,", ",,")); // remove NULL
writer.Close();
writer = new StreamWriter(file);
writer.Write(content.Replace(",0,", ",,")); // remove 0 dates
writer.Close();
writer = new StreamWriter(file);
writer.Write(content.Replace(",0", ",")); // remove 0 dates at eol
writer.Close();
try
{
conn.Open();
comm = new OleDbCommand("TRUNCATE TABLE TB_TEMP_INVENTORY", conn); // clear temp table
comm.ExecuteNonQuery();
// bulk insert from csv to temp table
comm = new OleDbCommand(@"SET DATEFORMAT DMY;
BULK INSERT TB_TEMP_INVENTORY
FROM '" + file + "'" +
@" WITH
(
FIELDTERMINATOR = ',',
ROWTERMINATOR = '\n'
)", conn);
comm.ExecuteNonQuery();
// check if data for same month exists in cattle table
comm = new OleDbCommand(@"SELECT *
FROM TB_CATTLE
WHERE Report='Inventory' AND Month=" + month + " AND Year=" + year, conn);
if (comm.ExecuteScalar() != null)
{
comm = new OleDbCommand(@"DELETE
FROM TB_CATTLE
WHERE Report='Inventory' AND Month=" + month + " AND Year=" + year, conn);
comm.ExecuteNonQuery();
}
// insert into master cattle table
comm = new OleDbCommand(@"SET DATEFORMAT MDY;
INSERT INTO TB_CATTLE(ID, Sex, BirthDate, FirstCalveDate, CurrentUnit, OriginalCost, AccumulatedDepreciation, WrittenDownValue, NetRealizableValue, CapitalGainLoss, Month, Year, Report, Locked, UploadedBy, UploadedAt)
SELECT DISTINCT ID, Sex, BirthDate, FirstCalveDate, CurrentUnit, 0, 0, 0, 0, 0, " + month + ", " + year + @", 'Inventory', 0, 'Admin', '" + DateTime.Now + @"'
FROM TB_TEMP_INVENTORY", conn);
comm.ExecuteNonQuery();
conn.Close();
}
catch (Exception ex)
{
ClientScript.RegisterStartupScript(typeof(string), "key", "<script>alert('" + ex.Message + "');</script>");
return;
}
答案 0 :(得分:2)
您没有指定进行插入的方式,但这里的合理选项类似SqlBulkCopy
,可以使用DataTable
或IDataReader
作为输入;这将为您提供充足的机会按摩数据 - 在内存中(DataTable
)或通过流API(IDataReader
),同时仍使用高效导入。 CsvReader
是加载CSV的不错选择。
另一种选择是在登台表中使用非常基本的插入,并通过TSQL代码按摩数据。
为什么它在开发/生产之间发生了变化;最可能的答案是:
答案 1 :(得分:2)
1)检查dev / testing&amp;的SQL Server LANGUAGE和DATEFORMAT设置。生产环境:
DBCC USEROPTIONS
2)CSV文件(来源)中使用了什么日期格式?
3)什么数据类型用于日期/时间字段(目标)?
DECLARE @v VARCHAR(10) = '2010-08-23';
SET DATEFORMAT mdy;
SELECT CAST(@v AS DATETIME)
,CAST(@v AS DATE)
,YEAR(CAST(@v AS DATETIME))
,MONTH(CAST(@v AS DATETIME))
,DAY(CAST(@v AS DATETIME));
SET DATEFORMAT dmy;
SELECT CAST(@v AS DATETIME)
,CAST(@v AS DATE);