我的数据库上有2个表,一个叫Sales.Salesperson,它是源,目标数据库是dbo.Salesperson . 我做了一个BIML,使用C#代码从源获取现有表的列表,然后将所有数据从源导入到目标,对于我的示例,我只有1个表,我在上面列出 . 在C#上,我使用SQL连接和SQL命令来获取所有表的表和模式(再次只有1,因此它可以是动态的),
问题,因为我有一个句点,对于sepearte模式和表,在我的SQL命令中,当我从BIML转到生成SSIS包时,它给我一个来自SSIS步骤EXECUTESQL DirectInput的错误消息,当我尝试截断表<#= table#> error表示“DynamicDataLoad包中的Sales.SalesPerson包含SSIS的无效字符(/:[] . = . 无效字符将替换为_”因此,我的SSIS包上出现错误
以下是以下代码的帮助:
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<Packages>
<Package Name="DynamicDataLoad" ConstraintMode ="Linear" ProtectionLevel="DontSaveSensitive">
<Tasks>
<# foreach(var table in GetTables()) { #>
<ExecuteSQL Name="Truncate Table Dest <#=table#>" ConnectionName="Target">
**<DirectInput>Truncate Table <#=table#></DirectInput>
</ExecuteSQL>**
<Dataflow Name="Load Table <#=table#>" >
<Transformations>
<OleDbSource Name="Source Table" ConnectionName="Source">
<ExternalTableInput Table="<#=table#>" />
</OleDbSource>
<OleDbDestination Name="Destination Table" ConnectionName="Target">
<ExternalTableOutput Table="<#=table#>" />
</OleDbDestination>
</Transformations>
</Dataflow>
<# } #>
</Tasks>
</Package>
</Packages>
</Biml>
以下是C#部分,如果你看一下SQL命令,我把Schema然后表带回一个叫做“table”的列表,它在上面的BIML中用来列出要转换成SSIS包的所有表,这用于BIML部分称为截断,这是错误来自BIML的地方 .
<#+
List<string> GetTables() {
List<string> tables = new List<string>();
SqlConnection cn = new SqlConnection("Data Source=mdsdqsdev;Initial Catalog=Test;Persist Security Info=False;Integrated Security=SSPI;");
SqlDataAdapter da = new SqlDataAdapter();
DataSet ds = new DataSet();
DataTable dt = new DataTable();
string q = "Select TABLE_SCHEMA+'.'+TABLE_NAME as name from INFORMATION_SCHEMA.TABLES";
var cmd = new SqlCommand(q);
cmd.Connection = cn;
try
{
da.SelectCommand = cmd;
ds.Tables.Add(new DataTable("Results"));
if(cn.State != ConnectionState.Open)
{
cn.Open();
}
ds.Tables[0].BeginLoadData();
da.Fill(ds,"Results");
ds.Tables[0].EndLoadData();
dt = ds.Tables[0];
if(cn.State != ConnectionState.Closed)
{
cn.Close();
}
}
catch (Exception ex)
{
throw ex;
}
finally
{
if (cn.State != ConnectionState.Closed)
{
cn.Close();
}
cn.Dispose();
}
foreach (DataRow row in dt.Rows)
{
tables.Add(row["name"].ToString());
}
return tables;
}
#>
1 回答
该错误由
<ExecuteSQL Name="Truncate Table Dest <#=table#>" ConnectionName="Target">
和<Dataflow Name="Load Table <#=table#>" >
生成,因为您的表变量将采用schema.table的形式,您的数据流名称将类似于"Dataflow Foo.Bar",如果您尝试手动输入,SSDT会拒绝指定您不能这样命名 .解决这个特定问题要做一些像“安全”的字符串 . 低租金方法只是应用替换呼叫来交换期间的下划线 .
更大的问题是在它们或空格中包含无效字符的表或模式 . 那将需要你用[]包装它们 . 而不是盲目地应用它们,我会用
QUOTENAME()
将该工作推送到SQL Server我发现通常将模式和表名称作为离散部分提供给我更好的服务,因为我发现连接比分割更容易 . 这使得GetTables()的签名不同 . 也许
List<KeyValuePair<string, string>>
,我不知道 .即便如此,当原生Biml方式约为4行代码时,你想要做到这一点 . 我有一个例子,我使用Biml到reverse engineer a specific schema的数据库,但在Biml GetDatabaseSchema上搜索将为你提供许多如何做的例子 .