C# 跳过SqlBulkCopy中的某些列
我正在对两个具有不同列集的SQL Server 2008使用C# 跳过SqlBulkCopy中的某些列,c#,sql-server,sql-server-2008,sqlbulkcopy,columnmappings,C#,Sql Server,Sql Server 2008,Sqlbulkcopy,Columnmappings,我正在对两个具有不同列集的SQL Server 2008使用SqlBulkCopy(将一些数据从prod服务器移动到dev)。因此,希望跳过一些尚未存在/尚未删除的列 我该怎么做?使用列映射的一些技巧 编辑: 我下一步要做: DataTable table = new DataTable(); using (var adapter = new SqlDataAdapter(sourceCommand)) { adapter.Fill(table); } table.Columns
SqlBulkCopy
(将一些数据从prod
服务器移动到dev
)。因此,希望跳过一些尚未存在/尚未删除的列
我该怎么做?使用列映射的一些技巧
编辑:
我下一步要做:
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)
DataTable=newdatatable();
使用(var adapter=newsqldataadapter(sourceCommand))
{
适配器。填充(表格);
}
表3.列
第()类
.ForEach(c=>bulk.ColumnMappings.Add(
新的SqlBulkCopyColumnMapping(c.ColumnName,c.ColumnName));
bulk.WriteToServer(表)
并获得:
给定的ColumnMapping与源或目标中的任何列都不匹配
试试这个:
希望您正在寻找相同的当使用SqlBulkCopyColumnMapping时,只会复制为其创建映射的列 如果不为列创建映射,复制过程将忽略该映射 您可以在演示代码中看到这一点-AdventureWorks演示数据库中的示例源表包含的列多于映射或复制的列 编辑 如果没有关于数据库模式的更多信息,很难确定,但猜测问题在于以下语句:
new SqlBulkCopyColumnMapping(c.ColumnName, c.ColumnName)
根据您的描述,听起来并不是源表中的所有列都存在于目标表中。在SqlBulkCopyColumnMapping
构造循环中需要一个过滤器来跳过目标中不存在的任何列
我的C#不够好,无法给出一个我相信会奏效的示例,但在伪代码中它会起作用
foreach column c in sourcetable
{
if c.ColumnName exists in destination_table.columns
{
new SqlBulkCopyColumnMapping(c.ColumnName, c.ColumnName)
}
}
(我确信可以将其转换为lambda表达式)
请注意,在列名匹配但数据类型不兼容的情况下,这并不特别可靠。DataTable=newdatatable();
使用(var adapter=newsqldataadapter(sourceCommand))
{
适配器。填充(表格);
}
使用(SqlBulkCopy bulk=new SqlBulkCopy(targetConnection,SqlBulkCopyOptions.KeepIdentity,null){DestinationTableName=tableName})
{
foreach(GetMapping中的字符串列名(stringSource、stringTarget、tableName))
{
添加(新的SqlBulkCopyColumnMapping(columnName,columnName));
}
targetConnection.Open();
bulk.WriteToServer(表);
}
私有静态IEnumerable GetMapping(字符串stringSource、字符串stringTarget、字符串tableName)
{
返回可枚举的.Intersect(
GetSchema(stringSource,tableName),
GetSchema(stringTarget,tableName),
StringComparer.Ordinal);//或StringComparer.OrdinalIgnoreCase
}
私有静态IEnumerable GetSchema(字符串连接字符串,字符串表名)
{
使用(SqlConnection连接=新的SqlConnection(connectionString))
使用(SqlCommand=connection.CreateCommand())
{
command.CommandText=“sp_Columns”;
command.CommandType=CommandType.storedProcess;
command.Parameters.Add(“@table_name”,SqlDbType.NVarChar,384),Value=tableName;
connection.Open();
使用(var reader=command.ExecuteReader())
{
while(reader.Read())
{
收益返回(字符串)读取器[“列名称”];
}
}
}
}
埃德·哈珀,这就是没有伪代码的情况
(在这种情况下,从DataTable dt(完全定义)到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;
}
是的,我说的正是这个类。但是如何跳过源代码中的一列?
.Add(newsqldatamapping(“目标上已删除的列”),“”)
?当然,我可以在基础查询中将其从源代码中删除-选择a、b、c
而不是选择*
-但这不是一个解决方案如果您不想将其从源代码复制到目标,只需将其从映射中删除。映射将只复制指定列中的数据。请参阅我更新的帖子。我在做什么rong?也许我理解-source有一个列,但target没有。我应该比较source/target模式,只使用中存在的列both@abatishchev-添加了更多详细信息谢谢!您清除了我的视野。但您的示例不适合我,很遗憾,因为我没有目标表,只有它的名称。因此必须调用sp_列
to确定表列。@abtishchev-很酷而且是可重用的。我相信“stringTarget”和“stringSource”是列名,对吗?@student:嘿,IIRC这些分别是源数据库和目标数据库的连接字符串。太棒了。我需要添加一些代码来正确处理架构和数据库名称,但这正是我需要的。这是一种享受,但值得指出的是,您需要在表上插入权限,因此这可能不起作用,这取决于某些It部门的DB策略:-(horray用于使用sp_列,而不是从表中选择*,其中1=0并从DataReader获取SchemaTable()。您是一个英雄。