SQL Comparison SDK 10

Help for older versions available.

These pages cover SQL Comparison SDK 10, which is not the latest version. Help for other versions is also available.

Creating an HTML report of schema differences in Visual Basic .NET

SQL Compare's API does not directly support the creation of HTML reports as the user interface of the program does. By manually generating an XML document, a report can be generated by transforming the XML using the XSL template supplied with the SQL Compare program. This report code examines the differences between databases WidgetStaging and WidgetProduction, generates suitable XML, and converts it to HTML using the template SQLCompareInteractiveReportTemplate.xsl.

  1. '====================================================================
  2. ' Save the following as Module1.vb
  3. '====================================================================
  4. Imports RedGate.SQLCompare.Engine
  5. Imports RedGate.Shared.SQL
  6. Imports System.Diagnostics
  7. Module Module1
  8. Sub Main()
  9. Using dbSource As New Database(), dbTarget As New Database()
  10. 'Retrieve the schema information for the two databases
  11. Console.WriteLine("Registering databases")
  12. dbSource.Register(New ConnectionProperties(".", "WidgetStaging"), Options.Default)
  13. dbTarget.Register(New ConnectionProperties(".", "WidgetProduction"), Options.Default)
  14. Console.WriteLine("Comparing Databases")
  15. Dim dbSourceVsdbTarget As Differences = dbSource.CompareWith(dbTarget, Options.Default)
  16. ' Set the filespec for our HTML report
  17. Dim ReportOutput As String = "c:\Program files\Red Gate\SQL Compare 7\htmlreport.html"
  18. ' Set the XSL template to use for the report. These ship with the SQL Compare software
  19. Dim xsltemplate As String = "c:\Program files\Red Gate\SQL Compare 7\SQLCompareInteractiveReportTemplate.xsl"
  20. Console.WriteLine("Creating report...")
  21. HTMLReport.CreateHtmlReport(ReportOutput, dbSource, dbTarget, dbSourceVsdbTarget, Options.Default, xsltemplate)
  22. Console.WriteLine("Finished creating {0}, viewing", ReportOutput)
  23. HTMLReport.ViewReport(ReportOutput)
  24. End Using
  25. Console.WriteLine("Press any key to continue")
  26. Console.ReadLine()
  27. End Sub
  28. End Module
  29. '====================================================================
  30. ' EOF Module1.vb
  31. '====================================================================
  32. '====================================================================
  33. ' Save the following as HTMLReport.vb
  34. '====================================================================
  35. Imports System
  36. Imports System.Collections
  37. Imports System.Data
  38. Imports System.IO
  39. Imports System.Xml
  40. Imports System.Xml.Xsl
  41. Imports System.Text
  42. Imports System.Reflection
  43. Imports RedGate.SQLCompare.Engine
  44. Imports RedGate.Shared.SQL
  45. Imports System.Diagnostics
  46. Imports RedGate.Shared.Utils
  47. Imports System.Collections.Generic
  48. Public Class HTMLReport
  49. ' This method will create the XML needed for the report and transform it to an HTML page
  50. ' specified by fileName. It looks in the current folder for the template file.
  51. ' Please supply the two database objects, the Differences object that you get after a comparison,
  52. ' and the set of options that you used for the comparison.
  53. Public Shared Sub CreateHtmlReport(ByVal fileName As String, ByVal dbSourceDatabase As Database,ByVal dbTargetDatabase As Database, ByVal obDatabaseDifferences As Differences, ByVal enOptions AsOptions, ByVal xlstemplate As String)
  54. Dim tempFile As String = Path.GetTempFileName()
  55. Dim xslt As XslCompiledTransform = New XslCompiledTransform()
  56. 'Load the XSL template
  57. Dim xSettings As XsltSettings = New XsltSettings()
  58. xSettings.EnableScript = True
  59. xslt.Load(xlstemplate, xSettings, New XmlUrlResolver())
  60. Try
  61. Dim writer As XmlTextWriter = New XmlTextWriter(tempFile, Encoding.Unicode)
  62. ' Generate the raw data that will go into the report
  63. GenerateXml(writer, dbSourceDatabase, dbTargetDatabase, obDatabaseDifferences, enOptions)
  64. writer.Close()
  65. xslt.Transform(tempFile, fileName)
  66. Catch e As Exception
  67. Console.WriteLine("Unable to generate html report " + e.Message)
  68. Finally
  69. File.Delete(tempFile)
  70. End Try
  71. End Sub
  72. ''' <summary>
  73. ''' This is the method that creates the XML data used in the report (SQL Compare v7)
  74. ''' </summary>
  75. ''' <param name="writer">XmlTextWriter object</param>
  76. ''' <param name="dbSourceDatabase">A registered database</param>
  77. ''' <param name="dbTargetDatabase">The second registered database</param>
  78. ''' <param name="obDatabaseDifferences">The differences between the two databases</param>
  79. ''' <param name="m_Options">Set of options used during the comparison process</param>
  80. Private Shared Sub GenerateXml(ByVal writer As XmlTextWriter, ByVal dbSourceDatabase As Database,ByVal dbTargetDatabase As Database, ByVal obDatabaseDifferences As Differences, ByVal options As Options)
  81. writer.WriteStartDocument()
  82. ' Header
  83. writer.WriteStartElement("comparison")
  84. writer.WriteAttributeString("direction", "1to2")
  85. writer.WriteAttributeString("timestamp", DateTime.Now.ToString())
  86. 'Datasources
  87. writer.WriteStartElement("datasources")
  88. writer.WriteStartElement("datasource")
  89. writer.WriteAttributeString("type", "live")
  90. writer.WriteAttributeString("id", "1")
  91. writer.WriteStartElement("server")
  92. writer.WriteString(dbSourceDatabase.ConnectionProperties.ServerName)
  93. writer.WriteEndElement() ' </server>
  94. writer.WriteStartElement("database")
  95. writer.WriteString(dbSourceDatabase.ConnectionProperties.DatabaseName)
  96. writer.WriteEndElement() ' </database>
  97. writer.WriteEndElement() ' <datasource[@id=1]>
  98. 'Second database
  99. writer.WriteStartElement("datasource")
  100. writer.WriteAttributeString("type", "live")
  101. writer.WriteAttributeString("id", "2")
  102. writer.WriteStartElement("server")
  103. writer.WriteString(dbTargetDatabase.ConnectionProperties.ServerName)
  104. writer.WriteEndElement() ' </server>
  105. writer.WriteStartElement("database")
  106. writer.WriteString(dbTargetDatabase.ConnectionProperties.DatabaseName)
  107. writer.WriteEndElement() ' </database>
  108. writer.WriteEndElement() ' </datasource>
  109. writer.WriteEndElement() ' </datasources>
  110. 'Differences collection
  111. writer.WriteStartElement("differences")
  112. Dim d As Difference
  113. For Each d In obDatabaseDifferences
  114. If d.Type = DifferenceType.Equal Then Continue For
  115. If d.Selected = False Then Continue For ' do not report equal and nonselected objects
  116. writer.WriteStartElement("difference")
  117. writer.WriteAttributeString("objecttype", d.DatabaseObjectType.ToString().ToLower())
  118. writer.WriteAttributeString("status", d.Type.ToString().Trim().ToLower())
  119. writer.WriteAttributeString("fqn", String.Format("{0}-{1}", d.DatabaseObjectType.ToString().ToLower(), d.Name.ToString().ToLower()))
  120. Select Case d.Type
  121. Case DifferenceType.OnlyIn1
  122. writer.WriteStartElement("object")
  123. writer.WriteAttributeString("owner", d.ObjectIn1.Owner)
  124. writer.WriteAttributeString("id", "1")
  125. writer.WriteString(d.ObjectIn1.FullyQualifiedName)
  126. writer.WriteEndElement()
  127. writer.WriteStartElement("object")
  128. writer.WriteAttributeString("owner", "")
  129. writer.WriteAttributeString("id", "2")
  130. writer.WriteEndElement()
  131. Case DifferenceType.OnlyIn2
  132. writer.WriteStartElement("object")
  133. writer.WriteAttributeString("owner", "")
  134. writer.WriteAttributeString("id", "1")
  135. writer.WriteEndElement()
  136. writer.WriteStartElement("object")
  137. writer.WriteAttributeString("owner", d.ObjectIn2.Owner)
  138. writer.WriteAttributeString("id", "2")
  139. writer.WriteString(d.ObjectIn2.FullyQualifiedName)
  140. writer.WriteEndElement()
  141. Case Else ' object exists in both
  142. writer.WriteStartElement("object")
  143. writer.WriteAttributeString("owner", d.ObjectIn1.Owner)
  144. writer.WriteAttributeString("id", "1")
  145. writer.WriteString(d.ObjectIn1.FullyQualifiedName)
  146. writer.WriteEndElement()
  147. writer.WriteStartElement("object")
  148. writer.WriteAttributeString("owner", d.ObjectIn2.Owner)
  149. writer.WriteAttributeString("id", "2")
  150. writer.WriteString(d.ObjectIn2.FullyQualifiedName)
  151. writer.WriteEndElement()
  152. End Select
  153. ' Now we write the actual SQL code for the objects in database 1 and 2
  154. ' Since the reordering of lines is copyright code in SQL Compare
  155. ' we are going to simply dump the SQL in the order it comes
  156. writer.WriteStartElement("comparisonstrings")
  157. Dim w As Work = New Work()
  158. Dim regions1 As Regions = w.ScriptObject(d.ObjectIn1, options)
  159. Dim regions2 As Regions = w.ScriptObject(d.ObjectIn2, options)
  160. ' Work out which region is "shortest"
  161. Dim regionCount As Integer = regions1.Count
  162. Dim oneIsLonger As Boolean = True
  163. If regions2.Count > regions1.Count Then
  164. regionCount = regions2.Count
  165. oneIsLonger = False
  166. End If
  167. 'loop through all SQL regions -- append the longer lines
  168. Dim j As Integer = 0
  169. For j = 0 To regionCount - 1
  170. 'Start writing out the lines of SQL code
  171. Dim oneHasMoreLines As Boolean = False
  172. Dim linesFrom1() As String
  173. Dim linesFrom2() As String
  174. Try
  175. linesFrom1 = regions1(j).SQL.Split(vbCrLf)
  176. Catch a As ArgumentOutOfRangeException ' There are more regions in region2
  177. ReDim Preserve linesFrom1(regions2(j).SQL.Split(vbCrLf).Length)
  178. Dim y As Integer = 0
  179. For y = 0 To linesFrom1.Length - 1
  180. linesFrom1(y) = String.Empty
  181. Next y
  182. End Try
  183. Try
  184. linesFrom2 = regions2(j).SQL.Split(vbCrLf)
  185. Catch a As ArgumentOutOfRangeException ' There are more regions in region1
  186. ReDim Preserve linesFrom2(regions1(j).SQL.Split(vbCrLf).Length)
  187. Dim y As Integer = 0
  188. For y = 0 To linesFrom2.Length - 1
  189. linesFrom2(y) = String.Empty
  190. Next y
  191. End Try
  192. Dim sqlLineCount As Integer = linesFrom1.Length
  193. Dim sqlLineCount2 As Integer = linesFrom2.Length
  194. If sqlLineCount > sqlLineCount2 Then
  195. sqlLineCount = sqlLineCount2
  196. oneHasMoreLines = True
  197. End If
  198. Dim l As Integer = 0
  199. For l = 0 To sqlLineCount - 1
  200. writer.WriteStartElement("line")
  201. writer.WriteAttributeString("type", IIf(Not String.Compare(linesFrom1(l), linesFrom2(l), True) = 0, "different", "same"))
  202. ' Dump the line of SQL from db1
  203. writer.WriteStartElement("left")
  204. writer.WriteString(linesFrom1(l).Trim())
  205. writer.WriteEndElement() ' </left>
  206. ' ...and db2
  207. writer.WriteStartElement("right")
  208. writer.WriteString(linesFrom2(l).Trim())
  209. writer.WriteEndElement() ' </right>
  210. writer.WriteEndElement() '</line>
  211. Next l
  212. 'Write out any "leftover" SQL
  213. Dim leftoverSql() As String = linesFrom2
  214. If oneHasMoreLines = True Then leftoverSql = linesFrom1
  215. Dim m As Integer = 0
  216. For m = l To leftoverSql.Length - 1
  217. writer.WriteStartElement("line")
  218. writer.WriteAttributeString("type", "different")
  219. writer.WriteStartElement("left")
  220. If oneHasMoreLines = True Then writer.WriteString(leftoverSql(m).Trim())
  221. writer.WriteEndElement() ' </left>
  222. writer.WriteStartElement("right")
  223. If oneHasMoreLines = False Then writer.WriteString(leftoverSql(m).Trim())
  224. writer.WriteEndElement() ' </right>
  225. writer.WriteEndElement() '</line>
  226. Next m
  227. Next j
  228. writer.WriteEndElement() ' </comparisonStrings>
  229. writer.WriteEndElement() ' </difference>
  230. Next
  231. writer.WriteEndElement() ' </differences>
  232. writer.WriteEndElement() ' </comparison>
  233. writer.WriteEndDocument() 'EOF
  234. End Sub
  235. ' Feed the .htm file to Windows and let it start the viewer (IE)
  236. Public Shared Sub ViewReport(ByVal sPath As String)
  237. If sPath = String.Empty Then Return
  238. 'view the doc
  239. Try
  240. Dim psi As ProcessStartInfo = New ProcessStartInfo(sPath)
  241. psi.UseShellExecute = True
  242. Process.Start(psi)
  243. Catch
  244. End Try
  245. End Sub
  246. End Class
  247. '====================================================================
  248. ' EOF HTMLReport.vb
  249. '====================================================================

Didn't find what you were looking for?