使用脚本任务创建ADO NET(ODBC)数据流源

时间:2012-09-14 20:34:39

标签: ado.net ssis pervasive-sql

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

我正在尝试创建一个包,它使用Foreach循环创建一个包,该包创建一个ADO / ODBC源(Timberline),一个OLE目标(SQL)并动态处理列映射。我发现代码here几乎可以满足我的需求。

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

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

除了这种方法之外,我首先尝试了另外几件事:

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

解决方案:使用其中一个SQL Transfer任务
问题:仅适用于SQL数据库。此源是Pervasive SQL数据库

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

以下是我需要帮助的original VB .NET code部分:

'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()

提前致谢!

1 个答案:

答案 0 :(得分:0)

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

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

获取Source&目的地连接工作,这里有一些秘密的调整,以使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(“列”)检索的每个列的数据类型,以使您的SQL Server创建表脚本(我我假设你已经完成了。 为了至少弄清楚哪些表具有主键,您需要遍历从GetSchema(“Tables”)返回的每个表,以便使用GetSchema(“索引”)。有一个错误要求您一次查询一个表的索引。这很容易google - 创建一个字符串数组作为第3个参数传入:GetSchema(“Indexes”,tblName,resultArray [])

我所做的是将我的父SSIS包中的Tables和Columns集合转换为对象变量。因为Timberline是如此之快(不是),所以将所有列向下拉并在本地过滤它们似乎更有效...如果需要,我会在SQL Server中创建表。

完成后,再次使用Tables的本地副本在“设计模式”下​​操作脚本任务中的SSIS包(更改源和目​​标目标表,并重做列映射),然后执行now-in -memory 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框架。

我使用了Derived Column代码,因为我需要将多个Timberline DB复制到一个SQL Server DB中。派生列将“CompanyID”值添加到SQL Server的输出管道。

最后,根据Destination附加到的管道,将Destination的Virtual Input列映射到其External Metadata列:

      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#kungfu在我拥有的时候还不够强大......

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

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

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