Posted By

jmcd on 08/13/10


Tagged

sql server diff c Linq


Versions (?)

Who likes this?

1 person have marked this snippet as a favorite

Tyster


Simple SQL Server Diff Tool


 / Published in: C#
 

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Data.Linq;
  4. using System.Data.Linq.Mapping;
  5. using System.Linq;
  6.  
  7. namespace Sdiff
  8. {
  9. internal class Program
  10. {
  11. /// <param name = "args">arg[0] old schema connection string, arg[1] target schema connection string</param>
  12. /// <summary>
  13. /// Tells you what to do with old schema to get it into the shape of the new
  14. /// </summary>
  15. private static void Main(string[] args)
  16. {
  17. var diffs = new List<Diff>();
  18.  
  19. var oldContext = new IsDataContext(args[0]);
  20. var newContext = new IsDataContext(args[1]);
  21.  
  22. var newTableNames = newContext.Tables.Select(x => x.Name).ToList();
  23. var oldTableNames = oldContext.Tables.Select(x => x.Name).ToList();
  24.  
  25. AddDiffs(diffs, oldTableNames.Except(newTableNames), DiffKind.TableDelete);
  26. AddDiffs(diffs, newTableNames.Except(oldTableNames), DiffKind.TableCreate);
  27.  
  28. var commonTableNames = newTableNames.Intersect(oldTableNames);
  29. foreach (var tableName in commonTableNames)
  30. {
  31. var newColumns = newContext.Columns.Where(x => x.TableName == tableName).ToList();
  32. var oldColumns = oldContext.Columns.Where(x => x.TableName == tableName).ToList();
  33.  
  34. var newColumnNames = newColumns.Select(x => x.FullName);
  35. var oldColumnNames = oldColumns.Select(x => x.FullName);
  36.  
  37. AddDiffs(diffs, oldColumnNames.Except(newColumnNames), DiffKind.ColumnDelete);
  38. AddDiffs(diffs, newColumnNames.Except(oldColumnNames), DiffKind.ColumnCreate);
  39.  
  40. var commonColumnNames = newColumnNames.Intersect(oldColumnNames);
  41. foreach (var commonColumnName in commonColumnNames)
  42. {
  43. var newDataType = newColumns.Where(x => x.FullName == commonColumnName).Select(x => x.DataType).Single();
  44. var oldDataType = oldColumns.Where(x => x.FullName == commonColumnName).Select(x => x.DataType).Single();
  45. if (oldDataType != newDataType) diffs.Add(new Diff(commonColumnName + " " + oldDataType + " -> " + newDataType, DiffKind.ColumnDataTypeChange));
  46. }
  47. }
  48.  
  49. WriteSection(diffs.Where(x => x.Kind == DiffKind.TableDelete), "Tables to delete");
  50. WriteSection(diffs.Where(x => x.Kind == DiffKind.TableCreate), "Tables to create");
  51. WriteSection(diffs.Where(x => x.Kind == DiffKind.ColumnDelete), "Columns to delete");
  52. WriteSection(diffs.Where(x => x.Kind == DiffKind.ColumnCreate), "Columns to create");
  53. WriteSection(diffs.Where(x => x.Kind == DiffKind.ColumnDataTypeChange), "Columns to modify");
  54.  
  55. Console.ReadKey();
  56. }
  57.  
  58. private static void AddDiffs(List<Diff> diffs, IEnumerable<string> names, DiffKind diffKind)
  59. {
  60. diffs.AddRange(names.Select(name => new Diff(name, diffKind)));
  61. }
  62.  
  63.  
  64. private static void WriteSection(IEnumerable<Diff> diffs, string title)
  65. {
  66. if (!diffs.Any()) return;
  67. Console.WriteLine();
  68. Console.WriteLine(title);
  69. Console.WriteLine(string.Empty.PadLeft(title.Length, '-'));
  70. foreach (var name in diffs.Select(x => x.Name).OrderBy(x => x))
  71. {
  72. Console.WriteLine(name);
  73. }
  74. }
  75.  
  76. private class Diff
  77. {
  78. public Diff(string name, DiffKind kind)
  79. {
  80. Name = name;
  81. Kind = kind;
  82. }
  83.  
  84. public string Name { get; private set; }
  85. public DiffKind Kind { get; private set; }
  86. }
  87.  
  88. internal enum DiffKind
  89. {
  90. TableDelete,
  91. TableCreate,
  92. ColumnDelete,
  93. ColumnCreate,
  94. ColumnDataTypeChange
  95. }
  96. }
  97.  
  98.  
  99. public class IsDataContext : DataContext
  100. {
  101. public Table<Column> Columns;
  102. public Table<Table> Tables;
  103. public IsDataContext(string connection) : base(connection) {}
  104. }
  105.  
  106. [Table(Name = "INFORMATION_SCHEMA.TABLES")]
  107. public class Table
  108. {
  109. [Column(Name = "TABLE_NAME")] public string Name;
  110. }
  111.  
  112. [Table(Name = "INFORMATION_SCHEMA.COLUMNS")]
  113. public class Column
  114. {
  115. [Column(Name = "CHARACTER_MAXIMUM_LENGTH")] public int? CharacterMaximumLength;
  116. [Column(Name = "DATA_TYPE")] public string DataTypeName;
  117. [Column(Name = "COLUMN_NAME")] public string Name;
  118. [Column(Name = "TABLE_NAME")] public string TableName;
  119.  
  120. public string DataType
  121. {
  122. get
  123. {
  124. if (!CharacterMaximumLength.HasValue) return DataTypeName;
  125. if (CharacterMaximumLength.Value == -1) return DataTypeName + "(MAX)";
  126. return DataTypeName + "(" + CharacterMaximumLength.Value + ")";
  127. }
  128. }
  129.  
  130. public string FullName { get { return TableName + "." + Name; } }
  131. }
  132. }

Report this snippet  

You need to login to post a comment.