星辰.Net技术社区论坛

首页 » 数据库 » MSSQL » 数据库开发的持续集成 - Sql Server数据库结构比较
neptune - 2008-6-5 14:32:00
上回说到了数据库开发的持续集成的总的意图,提供一个数据库部署和升级的工具,接下来说说如何进行数据库比较。}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
    在我的开发中数据库比较工具主要需要两种形式: 桌面工具和MsBuid任务。}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
    桌面工具推荐开源的DaBCoS3,基本够用,有朋友推荐直接用VS2005,但我比较喜欢小巧一点的东东,因为不仅仅在数据库开发的时候用。}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
    MsBuild任务很重要,在持续集成的时候可用来验证升级脚本是否正常工作。在CC.Net中加入SqlDeply任务(MsBuild),对产品系统数据库的副本进行升级,然后使用MsBuild数据库比较任务比较升级后的结构与开发数据库是否相同。以此来验证升级脚本,相当于对升级脚本做自动测试(当然还有回归测试),可大大节约人力。}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
    在网上搜寻一大圈,发现Red Gate提供的程序集不错,但要$,放弃。绕了一大圈,回到M$,PowerTools被选中。要先装Team Edition for Database。}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
    数据结构比较的MsBuild任务如此例:}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
<Project DefaultTargets="SchemaCompare" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
   
<UsingTask TaskName="SqlSchemaCompareTask" AssemblyName="Microsoft.VisualStudio.TeamSystem.Data.PowerTools.Tasks, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
   
<PropertyGroup>}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
   
<UpdateSql/>}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
   
</PropertyGroup>}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
   
<Target Name ="SchemaCompare">}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
   
<SqlSchemaCompareTask}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
       
SourceConnectionString="server=product;user id=sa;password=mypass"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        SourceDatabaseName
="Northwind"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        TargetConnectionString
="Data Source=.;Integrated Security=True;Pooling=False"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        TargetDatabaseName
="Northwind"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        OutputPath
= "."}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        OutputFileName
= "update.sql"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        ForceColumnOrder
="true"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        IgnoreExtendedProperties
="true"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        IgnoreStatistics
="true" }GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        IgnoreConstraintNames
="true"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        IgnoreQuotedIdentifiersAndAnsiNullSettings
="true"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        IgnoreTriggerOrder
="true"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        IgnoreUsers
="true"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        IgnoreWhiteSpace
="true"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        DoNotOutputCommentHeader
="true"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        NoTransactionalChangeScript
="true"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        SkipSETStatements
="true"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        ScriptCollationWhenDifferentFromDefault
="true"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
       
/>    }GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
   
<ReadLinesFromFile File="update.sql">}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
       
<Output TaskParameter="Lines" PropertyName="UpdateSql"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
/>}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
   
</ReadLinesFromFile>    }GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
   
<!-- NOTE: If update.sql is emtpy, the two databases are same -->}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
   
<Message Text="$(UpdateSql)" Condition="'$(UpdateSql)' != ''"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
/>}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
   
<Error Text="Soure database is different from the target" Condition="'$(UpdateSql)' != ''"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
/>}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
   
</Target>}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
</Project>
}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
    注意:此例中SqlSchemaComapreTask的属性目前已优化,用以确保在数据库相同时产生的update.sql是空的,并以此来判断两个数据库是否相等。这个任务用来产生升级脚本的,这里只用于比较两个数据库是否结构相同。}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
    数据库数据比较的MsBuild任务如此例:}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
<Project DefaultTargets="DataCompare" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
   
<UsingTask TaskName="SqlDataCompareTask" AssemblyName="Microsoft.VisualStudio.TeamSystem.Data.PowerTools.Tasks, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"/>}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
   
<Target Name ="DataCompare">}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
   
<SqlDataCompareTask}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
       
SourceConnectionString="server=product;user id=sa;password=mypass"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        SourceDatabaseName
="Northwind"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        TargetConnectionString
="Data Source=.;Integrated Security=True;Pooling=False"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        TargetDatabaseName
="Northwind"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        OutputPath
= "."}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        OutputFileName
= "TestDataCompare.sql"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        TrimTrailingSpaces
="true"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        DisableTriggers
="true"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        DisableKeys
="false"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        DoNotOutputCommentHeader
="true"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
        DoNotUseTransactions
="true"}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
/>}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
   
</Target>}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
</Project>
}GéQaOŠï3(www.netcsharp.cnÀÀ¬$ ¨µ4p
1
查看完整版本: 数据库开发的持续集成 - Sql Server数据库结构比较