aba*_*hev 9 c# sql-server sqlbulkcopy sql-server-2008 columnmappings
我正在使用SqlBulkCopy两个不同列的SQL Server 2008(将一些数据从prod服务器移动到dev).所以想要跳过一些尚未存在/尚未删除的列.
我怎样才能做到这一点?一些技巧ColumnMappings?
编辑:
我做下一个:
DataTable table = new DataTable();
using (var adapter = new SqlDataAdapter(sourceCommand))
{
adapter.Fill(table);
}
table.Columns
.OfType<DataColumn>()
.ForEach(c => bulk.ColumnMappings.Add(
new SqlBulkCopyColumnMapping(c.ColumnName, c.ColumnName)));
bulk.WriteToServer(table)
Run Code Online (Sandbox Code Playgroud)
得到:
给定的ColumnMapping与源或目标中的任何列都不匹配.
aba*_*hev 16
DataTable table = new DataTable();
using (var adapter = new SqlDataAdapter(sourceCommand))
{
adapter.Fill(table);
}
using (SqlBulkCopy bulk = new SqlBulkCopy(targetConnection, SqlBulkCopyOptions.KeepIdentity, null) { DestinationTableName = tableName })
{
foreach (string columnName in GetMapping(stringSource, stringTarget, tableName))
{
bulk.ColumnMappings.Add(new SqlBulkCopyColumnMapping(columnName, columnName));
}
targetConnection.Open();
bulk.WriteToServer(table);
}
private static IEnumerable<string> GetMapping(string stringSource, string stringTarget, string tableName)
{
return Enumerable.Intersect(
GetSchema(stringSource, tableName),
GetSchema(stringTarget, tableName),
StringComparer.Ordinal); // or StringComparer.OrdinalIgnoreCase
}
private static IEnumerable<string> GetSchema(string connectionString, string tableName)
{
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = connection.CreateCommand())
{
command.CommandText = "sp_Columns";
command.CommandType = CommandType.StoredProcedure;
command.Parameters.Add("@table_name", SqlDbType.NVarChar, 384).Value = tableName;
connection.Open();
using (var reader = command.ExecuteReader())
{
while (reader.Read())
{
yield return (string)reader["column_name"];
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
Ed *_*per 10
使用SqlBulkCopyColumnMapping时,仅复制为其创建映射的列.
如果不为列创建映射,则复制过程将忽略该映射.
您可以在此处的演示代码中看到这一点 - AdventureWorks演示数据库中的示例源表包含的列数多于映射或复制的列数.
编辑
如果没有关于数据库模式的更多信息,很难确定,但是猜测问题是这个语句:
new SqlBulkCopyColumnMapping(c.ColumnName, c.ColumnName)
Run Code Online (Sandbox Code Playgroud)
根据您的描述,听起来并非源表中的所有列都存在于目标表中.您需要在SqlBulkCopyColumnMapping构造循环中使用过滤器来跳过目标中不存在的任何列.
我的C#不够好,不能给出一个我相信会工作的例子,但在伪代码中它会是
foreach column c in sourcetable
{
if c.ColumnName exists in destination_table.columns
{
new SqlBulkCopyColumnMapping(c.ColumnName, c.ColumnName)
}
}
Run Code Online (Sandbox Code Playgroud)
(我确定可以将它转换为lambda表达式)
请注意,在列名匹配但数据类型不兼容的情况下,这不是特别健壮.
小智 5
Ed Harper, this is what it looks like without pseudo code (in this case from DataTable dt (fully defined) to an existing table in the db:
using (SqlBulkCopy bulkCopy = new SqlBulkCopy(connectionString))
{
bulkCopy.DestinationTableName = "dbo.DepartmentsItems";
// Write from the source to the destination.
foreach (DataColumn c in dt.Columns)
{
bulkCopy.ColumnMappings.Add(c.ColumnName, c.ColumnName);
}
bulkCopy.WriteToServer(dt);
return dt.Rows.Count;
}
Run Code Online (Sandbox Code Playgroud)