使用BulkCopy将通用.CSV文件的加载到SQL表中
我正在尝试创建一个通用模块,该模块将.CSV文件加载到SQL表中。 SQL表已创建,其名称以及文件的名称将作为参数传递。到目前为止,这是我所拥有的...
public void Main()
{
var mFilepath = Dts.Variables["InputFile"].Value.ToString();
var mSQLTable = "[Staging].[tblLoadBUF]";
try
{
DataTable dt = new DataTable();
string contents = File.ReadAllText(mFilepath, System.Text.Encoding.GetEncoding(1252));
TextFieldParser parser = new TextFieldParser(new StringReader(contents));
parser.HasFieldsEnclosedInQuotes = true;
parser.SetDelimiters(",");
string[] fields;
while (!parser.EndOfData)
{
fields = parser.ReadFields();
if (dt.Columns.Count == 0)
{
foreach (string field in fields)
{
dt.Columns.Add(new DataColumn(string.IsNullOrWhiteSpace(field.Trim('\"')) ? null : field.Trim('\"'), typeof(string)));
}
}
else
{
dt.Rows.Add(fields.Select(item => string.IsNullOrWhiteSpace(item.Trim('\"')) ? null : item.Trim('\"')).ToArray());
}
}
parser.Close();
string connectionString = Dts.Connections["OLEDB_CONN"].ConnectionString; // ConnectionString will contain unsupported keywords like 'provider'
connectionString = connectionString.Trim(';'); // Remove the trailing semicolon so that when we perform the split in the following line, there are no index errors.
var connStrDictionary = connectionString.Split(';').Select(x => x.Split('=')).ToDictionary(x => x[0], x => x[1]); // Here we get each value-pair from connection string by splitting by ';', then splitting each element by '=' and adding the pair to a Dictionary.
connectionString = "Data Source=" + connStrDictionary["Data Source"] + ";Initial Catalog=" + connStrDictionary["Initial Catalog"] + ";Integrated Security=" + connStrDictionary["Integrated Security"]; // Build the actual connection string to be used.
using (SqlConnection con = new SqlConnection(connectionString))
{
using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(con))
{
sqlBulkCopy.DestinationTableName = mSQLTable;
sqlBulkCopy.ColumnMappings.Clear();
con.Open();
foreach (var column in dt.Columns)
{
sqlBulkCopy.ColumnMappings.Add(column.ToString(), column.ToString());
}
sqlBulkCopy.WriteToServer(dt);
con.Close();
}
}
Dts.TaskResult = (int)ScriptResults.Success;
}
catch (Exception ex)
{
Dts.Events.FireError(0, "Something went wrong ", ex.ToString(), string.Empty, 0);
Dts.TaskResult = (int)ScriptResults.Failure;
}
}
这还没有起作用。收到的错误:
System.InvalidoperationException:给定的列映射与源或目标中的任何列不匹配。
我确实验证了输入文件列的名称,因为我知道它们对案例敏感,并且它们都是相同的。但是,我真的想获得一个周转来验证源和目标列,因为输入文件将从许多源发送,我们对它们将如何创建...使用大写或小写的变量有任何控制权。名称。
有人可以帮我解决这个问题吗?请注意,英语不是我的主要语言,所以让我知道这是否还不够清晰。预先感谢您的帮助:-)
Mylene
I am trying to create a generic module that will load .csv files into SQL tables. The SQL tables are already created and their names, and the name of the file, will be passed as parameters. This what I have so far...
public void Main()
{
var mFilepath = Dts.Variables["InputFile"].Value.ToString();
var mSQLTable = "[Staging].[tblLoadBUF]";
try
{
DataTable dt = new DataTable();
string contents = File.ReadAllText(mFilepath, System.Text.Encoding.GetEncoding(1252));
TextFieldParser parser = new TextFieldParser(new StringReader(contents));
parser.HasFieldsEnclosedInQuotes = true;
parser.SetDelimiters(",");
string[] fields;
while (!parser.EndOfData)
{
fields = parser.ReadFields();
if (dt.Columns.Count == 0)
{
foreach (string field in fields)
{
dt.Columns.Add(new DataColumn(string.IsNullOrWhiteSpace(field.Trim('\"')) ? null : field.Trim('\"'), typeof(string)));
}
}
else
{
dt.Rows.Add(fields.Select(item => string.IsNullOrWhiteSpace(item.Trim('\"')) ? null : item.Trim('\"')).ToArray());
}
}
parser.Close();
string connectionString = Dts.Connections["OLEDB_CONN"].ConnectionString; // ConnectionString will contain unsupported keywords like 'provider'
connectionString = connectionString.Trim(';'); // Remove the trailing semicolon so that when we perform the split in the following line, there are no index errors.
var connStrDictionary = connectionString.Split(';').Select(x => x.Split('=')).ToDictionary(x => x[0], x => x[1]); // Here we get each value-pair from connection string by splitting by ';', then splitting each element by '=' and adding the pair to a Dictionary.
connectionString = "Data Source=" + connStrDictionary["Data Source"] + ";Initial Catalog=" + connStrDictionary["Initial Catalog"] + ";Integrated Security=" + connStrDictionary["Integrated Security"]; // Build the actual connection string to be used.
using (SqlConnection con = new SqlConnection(connectionString))
{
using (SqlBulkCopy sqlBulkCopy = new SqlBulkCopy(con))
{
sqlBulkCopy.DestinationTableName = mSQLTable;
sqlBulkCopy.ColumnMappings.Clear();
con.Open();
foreach (var column in dt.Columns)
{
sqlBulkCopy.ColumnMappings.Add(column.ToString(), column.ToString());
}
sqlBulkCopy.WriteToServer(dt);
con.Close();
}
}
Dts.TaskResult = (int)ScriptResults.Success;
}
catch (Exception ex)
{
Dts.Events.FireError(0, "Something went wrong ", ex.ToString(), string.Empty, 0);
Dts.TaskResult = (int)ScriptResults.Failure;
}
}
This was not working. Error received :
System.InvalidOperationException: The given ColumnMapping does not match up with any column in the source or destination.
I did verified the input file column names as I know that they are case sensitive, and they are all the same. However, I really would like to get a turnaround to verify the source and destination columns, since the input files will be sent from many sources and we don't have any control on how they will be created... with uppercase or lowercase variable names.
Can somebody help me solve this ? Pease note that English is not my primary language, so just let me know if this is not clear enough. And thanks in advance for you help guys :-)
Mylene
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我终于找到了一种方法!您必须查询目标表以获取列列表。如果可以帮助某人,这是代码...
I finally found a way to do it ! You have to query the destination table to get the list of column. Here is the code if it can help somebody...