1

我需要一些有关动态创建包的 SSIS 脚本任务 (SQL 2008 R2) 的帮助。我正在改进一个包,它将数据从 Sage Timberline(现在更名为 Sage 300)Pervasive SQL 环境复制到 SQL Server 数据仓库。我可以创建一个包来打开与 Timberline 的连接并将数据复制到 SQL Server 中的表中。问题是,对于林中的每个公司和 SQL 中的每个表,我都需要创建一个单独的数据流任务。考虑到三个 Timberline 公司文件夹和每个文件夹中的表格数量,这将花费大量时间来创建,并且维护和故障排除也很麻烦。

我正在尝试创建一个包,该包使用 Foreach 循环来创建一个包,该包创建一个 ADO/ODBC 源(Timberline)、一个 OLE 目标(SQL)并动态处理列映射。我在这里找到了几乎可以满足我需要的代码。

我测试了这段代码,它在使用 OLE SQL 源和目标时效果很好。使这个脚本工作的原因是它动态地处理列映射。因此,如果您将其放入 100 个左右表的 Foreach 循环中,每个循环都可以动态创建数据流并映射列,然后执行新包。

我的问题是我只能使用 ODBC 连接到 Timberline。因此,我需要修改脚本以使用 ADO NET (ODBC) 而不是 OLE 创建源连接。我在试图弄清楚这一点时遇到了很多麻烦。有人可以帮我解决这个问题吗?

除了这种方法,我首先尝试了其他几件事:

解决方案:设置链接服务器到 Timberline Pervasive SQL
问题:SQL 服务器是 64 位的,而 Timberline 驱动程序是 32 位的。使用链接服务器会返回架构不匹配错误。我打电话给 Sage,他们说他们没有发布 64 位驱动器的计划。

解决方案:使用 SQL 传输任务之一
问题:仅适用于 SQL 数据库。此源是 Pervasive SQL 数据库

解决方案:使用“INSERT ... INTO ...”类型的脚本
问题:这需要一个链接服务器。看上面的问题

这是我需要帮助的原始 VB .NET 代码部分:

'To Create a package named [Sample Package]
Dim package As New Package()
package.Name = "Sample Package"
package.PackageType = DTSPackageType.DTSDesigner100
package.VersionBuild = 1

'To add Connection Manager to the package
'For source database (OLTP)
Dim OLTP As ConnectionManager = package.Connections.Add("OLEDB")
OLTP.ConnectionString = "Data Source=.;Initial Catalog=OLTP;Provider=SQLNCLI10;Integrated Security=SSPI;Auto Translate=False;"
OLTP.Name = "LocalHost.OLTP"

'To add Load Employee Dim to the package [Data Flow Task]
Dim dataFlowTaskHost As TaskHost = DirectCast(package.Executables.Add("SSIS.Pipeline.2"), TaskHost)
dataFlowTaskHost.Name = "Load Employee Dim"
dataFlowTaskHost.FailPackageOnFailure = True
dataFlowTaskHost.FailParentOnFailure = True
dataFlowTaskHost.DelayValidation = False
dataFlowTaskHost.Description = "Data Flow Task"

'-----------Data Flow Inner component starts----------------
Dim dataFlowTask As MainPipe = TryCast(dataFlowTaskHost.InnerObject, MainPipe)
' Source OLE DB connection manager to the package.
Dim SconMgr As ConnectionManager = package.Connections("LocalHost.OLTP")

' Create and configure an OLE DB source component.
Dim source As IDTSComponentMetaData100 = dataFlowTask.ComponentMetaDataCollection.[New]()
source.ComponentClassID = "DTSAdapter.OLEDBSource.2"

' Create the design-time instance of the source.
Dim srcDesignTime As CManagedComponentWrapper = source.Instantiate()
' The ProvideComponentProperties method creates a default output.
srcDesignTime.ProvideComponentProperties()
source.Name = "Employee Dim from OLTP"

' Assign the connection manager.
source.RuntimeConnectionCollection(0).ConnectionManagerID = SconMgr.ID
source.RuntimeConnectionCollection(0).ConnectionManager = DtsConvert.GetExtendedInterface(SconMgr)
' Set the custom properties of the source.
srcDesignTime.SetComponentProperty("AccessMode", 0)
' Mode 0 : OpenRowset / Table - View
srcDesignTime.SetComponentProperty("OpenRowset", "[dbo].[Employee_Dim]")
' Connect to the data source, and then update the metadata for the source.
srcDesignTime.AcquireConnections(Nothing)
srcDesignTime.ReinitializeMetaData()
srcDesignTime.ReleaseConnections()

提前致谢!

4

1 回答 1

0

如果您需要在源和目标之间进行派生列转换,这里的 C# 代码就是您所需要的...

http://bifuture.blogspot.com/2011/01/ssis-adding-derived-column-to-ssis.html

为了使源和目标连接正常工作,这里有一些秘诀可以让 COM 和 .Net 之间的工作正常... http://blogs.msdn.com/b/mattm/archive/2008/12/30/api -sample-ado-net-source.aspx 也有一个类似的页面显示如何处理 OleDB 连接。

创建源表很容易。应使用 GetSchema("MetaDataCollections") 检索可访问的可用 ODBC 元数据集合。这将返回可用于该特定 ODBC 驱动程序的可用架构集合的列表。接下来,您将希望查看从 GetSchema("DataTypes") 返回的数据类型,以便您可以正确解释从 GetSchema("Columns") 检索到的每一列的数据类型,以使您的 SQL Server 创建表脚本(我'我假设你已经完成了)。为了至少找出哪些表具有主键,您需要遍历从 GetSchema("Tables") 返回的每个表,以便使用 GetSchema("Indexes")。有一个错误要求您一次查询一个表的索引。

我所做的是将 Tables 和 Columns 集合放入我的父 SSIS 包中的对象变量中。因为 Timberline 非常快(不是),所以将所有列拉下来并在本地过滤它们似乎更有效……如果需要,我这样做是为了在 SQL Server 中创建表。

完成后,再次使用 Tables 的本地副本在“设计模式”中的脚本任务中操作 SSIS 包(更改源和目​​标目标表,并重做列映射),并执行现在在内存中的 SSIS包裹。

对我来说,花了一段时间才弄清楚。以上两个 URL 都是必需的。我找到并将 .Net 2.0 Dts.PipelineWrap 和 Dts.RuntimeWrap .dll 复制到 Microsoft.Net\FrameworkV2.0xxxxx 文件夹,然后在每个想要使用它们的脚本任务中引用这些,然后再设置我的“使用 DtsPW = Microsoft.SqlServer .Dts.Pipeline.Wrapper”等

值得注意的是,由于 Timberline 是 32 位 ODBC,我认为有必要构建 SSIS 包以使用“X86”,并将脚本任务定位为使用 .Net 2.0 框架。

我使用派生列代码是因为我需要将多个 Timberline 数据库复制到一个 SQL Server 数据库中。派生列将“CompanyID”值添加到 SQL Server 的输出管道。

最后,根据目标附加到的管道,将目标的虚拟输入列映射到其外部元数据列:

      foreach (DtsPW.IDTSVirtualInputColumn100 vColumn in destVirtInput.VirtualInputColumnCollection)
            {
                var vCol = destInst.SetUsageType(destInput.ID, destVirtInput, vColumn.LineageID, DtsPW.DTSUsageType.UT_READWRITE);
                destInst.MapInputColumn(destInput.ID, vCol.ID, destInput.ExternalMetadataColumnCollection[vColumn.Name].ID);

            }

无论如何,该代码在 bifuture.blogspot.com 页面的上下文中会更有意义。

EzApi 库也可以帮助解决这个问题,但它的 AdoNet 连接源被编码为虚拟类,因此您需要实现特定的类才能使用。我的 C# 功夫在我有的时候还不够强大...

此外,CozyRoc 出售带有自定义 SSIS 控件(数据流源和目标控件...)的工具集,看起来它也可以在输入到输出列映射时执行此操作。

我的包现在似乎工作得很好......哦,还有一个,我没有运气尝试使用无 DSN 的 ODBC 连接到 Timberline,只是: Dsn=dsnname;Uid=user;Pwd=pwd;

在 64 位土地上运行的 SSIS 包在 64 位操作系统上看不到 32 位 DSN,似乎……至少,它对我不起作用(win7-64、32 位文本 ODBC DSN)。

于 2013-07-12T23:07:38.820 回答