不是 git 专家,但我对 SSIS 有所了解。
SSIS 包是集成服务对象的 XML 序列化。不幸的是,它还包含演示数据以支持设计体验的画布布局。
假设以下定义了一个截断表的 SSIS 包,并且您将其签入。
<SSIS>
<TASKS>
<EXECUTE_SQL_TASK COMMAND="TRUNCATE TABLE dbo.T1;"/>
</TASKS>
<LAYOUT>
<EXECUTE_SQL_TASK X="100" Y="200" HEIGHT="300" WIDTH="50" />
</LAYOUT>
</SSIS>
下一位开发人员打开包并调整任务的大小。不会发生语义变化,但包的序列化版本会发生变化。
<SSIS>
<TASKS>
<EXECUTE_SQL_TASK COMMAND="TRUNCATE TABLE dbo.T1;"/>
</TASKS>
<LAYOUT>
<EXECUTE_SQL_TASK X="50" Y="200" HEIGHT="300" WIDTH="150" />
</LAYOUT>
</SSIS>
同时,开发人员 #2 对包进行结构更改,因此他们创建了原始包的这种表示
<SSIS>
<TASKS>
<EXECUTE_SQL_TASK COMMAND="TRUNCATE TABLE dbo.T2;"/>
<EXECUTE_SQL_TASK COMMAND="TRUNCATE TABLE dbo.T1;"/>
</TASKS>
<LAYOUT>
<EXECUTE_SQL_TASK X="100" Y="200" HEIGHT="300" WIDTH="50" />
</LAYOUT>
</SSIS>
最后一个签入更改的人将遇到合并冲突。没有版本控制工具可以优雅地处理 XML 合并(至少 rcs、cvs、svn、SourceSafe、TFS、git 不会)
在精神上,是的,您可以处理合并示例 XML,但表示 SSIS 的实际 XML 非常复杂。在深入研究 SSIS 15 年多之后,我可能能够手动修改 XML 以解决合并冲突,即使那样它也将高度依赖于版本(仅限 2012+请)。
在较小程度上,同样的问题发生在同样基于 XML 的 .NET 项目 (MyProject.csproj) 中。如果您添加了一个新类,而另一个开发人员也添加了一个新类,那么如果您同时签入您的项目,您可能会遇到合并冲突。
我该怎么办
以下是我鼓励的一组良好做法
沟通
开发人员 A 将 packageSales 添加到项目中,开发人员 B 将 packageCustomer 添加到项目中,并且都将更改提交到源代码管理,其中一个可能会“丢失”他们的包,因为 XML 合并不会发生。该包仍在文件系统中,只是Visual Studio使用的.dtproj文件合并的已知包列表
<PACKAGES>
<PACKAGE Name="packageSales.dtsx"/>
</PACKAGES>
到
当它真的应该“合并”为时
<PACKAGES>
<PACKAGE Name="packageSales.dtsx"/>
<PACKAGE Name="packageCustomer.dtsx"/>
</PACKAGES>
具有多个并发 SSIS 开发人员的大型项目,指定一个人负责将包添加到项目中。让他们添加一个空白包并将更新的包和项目文件提交到版本控制,然后让其他开发人员知道从源代码控制获取最新版本。
将 SSIS 包视为二进制对象
将 SSIS 包视为二进制对象会更好。由于“噪音”太多,尝试生成diff 来识别版本之间的变化没有任何理由或价值。每次保存时,即使您没有对包进行任何更改,也会始终更新两个字段:VersionNumber 和 VersionGuid(名称近似)
我什至在各种版本控制系统中将 SSIS 标记为二进制对象,因为合并包几乎可以保证是 XML 包方言的损坏表示。
越小越好
由于我们已经将包视为二进制对象,并且系统生成的差异文件无助于识别发生了什么变化,因此创建专注于业务流程的 SSIS 包。将运行 N 个任务的“加载数据”替换为“加载销售”、“加载客户”,也许“加载数据”仍然存在,但它只是协调销售和客户包的运行。因为我们正在制作更多包但范围更小,这允许您将工作分配给多个开发人员,但不会有包中合并冲突的风险。
重新思考你的方法
取决于您的开发的可重复性,虽然表示实际 SSIS 包的 XML 过于复杂,但 Biml 不是。 Biml 是一种描述表和包的领域特定语言。它的美妙之处在于它足够小,可以准确地描述您在 SSIS 中可以做的所有事情,但没有实际 XML 中的所有繁琐内容。
这是一个用 Biml 表示的 hello world 级 SSIS 包
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<Packages>
<Package Name="SimpleBimlPackage" />
</Packages>
</Biml>
通过BimlExpress 上的免费 Visual Studio 添加运行它,它将创建一个没有任何内容的 SSIS 包。
以下是 Biml 的重要部分,它描述了具有两个 OLEDB 连接管理器的 SSIS 包。它有一个名为RowCountNew 的变量。它有一个数据流,从 Adventureworks Sales.Currency 表中获取数据,计算管道中的行数,然后将其放入名为 RAW.SalesCurrency 的表中,并将 Name 的原始列映射到 CurrencyName 的目标
<Biml xmlns="http://schemas.varigence.com/biml.xsd">
<Connections>
<OleDbConnection
ConnectionString="Data Source=localhost\dev2012;Initial Catalog=AdventureWorks2012;Provider=SQLNCLI11.1;Integrated Security=SSPI;Auto Translate=False;" Name="AdventureWorks"/>
<OleDbConnection
ConnectionString="Data Source=localhost\dev2012;Initial Catalog=TypeMoreClickLess;Provider=SQLNCLI11.1;Integrated Security=SSPI;Auto Translate=False;" Name="TypeMoreClickLessLocal"/>
</Connections>
<Packages>
<PackageName="HelloDataFlow"
<Variables>
<Variable Name="RowCountNew" DataType="Int32" Namespace="User">0</Variable>
</Variables>
<Tasks>
<Dataflow Name="DFT Basic Dataflow">
<Transformations>
<OleDbSource Name="OLE_SRC Demo"
ConnectionName="AdventureWorks" >
<DirectInput>
SELECT SC.CurrencyCode, SC.Name
FROM Sales.Currency AS SC;
</DirectInput>
</OleDbSource>
<RowCount Name="CNT New"
VariableName="User.RowCountNew"/>
<OleDbDestination
Name="OLE_DST RAW_SalesCurrency"
ConnectionName="TypeMoreClickLessLocal"
KeepIdentity="false"
TableLock="true"
UseFastLoadIfAvailable="true"
KeepNulls="true"
>
<ExternalTableOutput Table="[RAW].[SalesCurrency]"/>
<Columns>
<Column SourceColumn="Name" TargetColumn="CurrencyName" />
</Columns>
</OleDbDestination>
</Transformations>
</Dataflow>
</Tasks>
</Package>
</Packages>
</Biml>
这对开发人员来说更容易理解。并且比 SSIS 所涉及的所有鼠标点击更容易实现自动化。
另外,您可以将现有的 SSIS 包逆向工程为 Biml。然后,这可以使手动识别两组 SSIS 程序包之间发生的变化的前景变得不那么艰巨,而只是凡人可以处理的事情。