Automatisches Erzeugen eines Datenbankdiagrams aus einer MSSQL-Datenbank mit Hilfe von YED

Mit dem Microsoft SQL Server Management Studio (Express) kann man seiner Datenbank unter dem Punkt „Database Diagrams“ eine grafische Darstellung der Datenbank hinzufügen.

Soweit so gut – nur sieht das dann meistens so aus:

ERMSQL

Also nicht gerade übersichtlich. Und das Ganze per Hand in eine schöne Form zu bringen ist sehr mühselig.

Aber es gibt ein schönes Freewareprogramm: YED. Damit kann man sehr schön Diagramme machen. Und vor allem: es kann die Elemente automatisch anordnen, so dass sie (einigermaßen) übersichtlich dargestellt werden. Aber leider kann es keine Datenbankstruktur auslesen…

Aber wozu ist man Programmierer….

Nachfolgendes C#.net Konsolen-Programm liest aus einer Datenbank die Tabellen aus, holt sich die Beziehungen (Relationships) der Tabellen untereinander und speichert es in Form einer *.gml Datei ab.

  1. class Program
  2.     {
  3.         /// <summary>
  4.         /// Datenstruktur für die Beziehungen (TabelleA nach TabelleB)
  5.         /// </summary>
  6.         public struct Relationship
  7.         {
  8.             public String tableA;
  9.             public String tableB;
  10.         }
  11.         static void Main(string[] args)
  12.         {
  13.  
  14.             try
  15.             {
  16.                 SqlConnection dbConnection = new SqlConnection
  17.                  (@"data source=xxxxx;Integrated Security=SSPI;initial catalog=xxxx;persist security info=false;packet size=4096");
  18.                 dbConnection.Open();
  19.                 List<String> tables = GetTableNames(dbConnection);
  20.                 List<Relationship> rels = GetRelationsships(dbConnection);
  21.                 SaveGml(TablesToGml(tables), RelationshipsToGml(rels));
  22.                 Console.WriteLine("Die Datei wurde erfolgreich erzeugt");
  23.                
  24.             }
  25.             catch (Exception e)
  26.             {
  27.                 Console.Write(e.Message);
  28.             }
  29.             Console.ReadLine();
  30.         }
  31.  
  32.         /// <summary>
  33.         /// Speichert die endgültige GML-Datei ab.
  34.         /// </summary>
  35.         /// <param name="tables"></param>
  36.         /// <param name="rels"></param>
  37.         private static void SaveGml(string tables, string rels)
  38.         {
  39.             File.WriteAllText("test.gml",
  40.                 @"Creator   ""yFiles""
  41. Version ""2.6""
  42. graph
  43. [
  44.     hierarchic  1
  45.     label   """"
  46.     directed    1" + tables + rels+"]");
  47.         }
  48.  
  49.         /// <summary>
  50.         /// Wandelt die Liste der Tabelle ins (stark vereinfachte) GML-Format um.
  51.         /// </summary>
  52.         /// <param name="tables"></param>
  53.         /// <returns></returns>
  54.         public static String TablesToGml(List<String> tables)
  55.         {
  56.             String gml = "";
  57.             foreach (string tab in tables)
  58.             {
  59.                gml = String.Concat(gml,Environment.NewLine,
  60.                     "node",Environment.NewLine,
  61.                     "[",Environment.NewLine,
  62.                     "id \""+tab+"\"",Environment.NewLine,
  63.                     "label  \""+tab+"\"",Environment.NewLine,
  64.                     "]");
  65.             }
  66.             return gml;
  67.         }
  68.  
  69.         /// <summary>
  70.         /// Wandelt die Liste der Beziehungen ins (stark vereinfachte) GML-Format um
  71.         /// </summary>
  72.         /// <param name="rels"></param>
  73.         /// <returns></returns>
  74.         public static String RelationshipsToGml(List<Relationship> rels)
  75.         {
  76.             String gml = "";
  77.             foreach (Relationship rel in rels)
  78.             {
  79.                 gml = String.Concat(gml,Environment.NewLine,
  80.                     "edge",Environment.NewLine,
  81.                     "[",Environment.NewLine,
  82.                     "   source \""+rel.tableA+"\"",Environment.NewLine,
  83.                     "   target \""+rel.tableB+"\"",Environment.NewLine,
  84.                     "]");
  85.             }
  86.             return gml;
  87.         }
  88.        
  89.         /// <summary>
  90.         /// Liest die Namen der Tabellen aus der Datenbank
  91.         /// </summary>
  92.         /// <param name="dbConnection"></param>
  93.         /// <returns></returns>
  94.         public static List<String> GetTableNames(SqlConnection dbConnection)
  95.         {
  96.             List<string> tables = new List<string>();
  97.             SqlCommand sqlCommand = dbConnection.CreateCommand();
  98.             sqlCommand.CommandText =
  99.                 @"Select Name from dbo.sysobjects WHERE xType = 'U' order by Name";
  100.             SqlDataReader sqlReader = sqlCommand.ExecuteReader();
  101.             while (sqlReader.Read())
  102.             {
  103.                 tables.Add(sqlReader["Name"].ToString());
  104.             }
  105.             sqlReader.Close();
  106.             return tables;
  107.         }
  108.  
  109.         /// <summary>
  110.         /// Liest die Relationsships aus der Datenbank aus
  111.         /// </summary>
  112.         /// <param name="dbConnection"></param>
  113.         /// <returns></returns>
  114.         public static List<Relationship> GetRelationsships(SqlConnection dbConnection)
  115.         {
  116.             List<Relationship> rel = new List<Relationship>();
  117.             SqlCommand sqlCommand = dbConnection.CreateCommand();
  118.             sqlCommand.CommandText =
  119.                 @"SELECT
  120. K_Table = FK.TABLE_NAME,
  121. FK_Column = CU.COLUMN_NAME,
  122. PK_Table = PK.TABLE_NAME,
  123. PK_Column = PT.COLUMN_NAME,
  124. Constraint_Name = C.CONSTRAINT_NAME
  125. FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS C
  126. INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK ON C.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
  127. INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS PK ON C.UNIQUE_CONSTRAINT_NAME = PK.CONSTRAINT_NAME
  128. INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE CU ON C.CONSTRAINT_NAME = CU.CONSTRAINT_NAME
  129. INNER JOIN (
  130. SELECT i1.TABLE_NAME, i2.COLUMN_NAME
  131. FROM INFORMATION_SCHEMA.TABLE_CONSTRAINTS i1
  132. INNER JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE i2 ON i1.CONSTRAINT_NAME = i2.CONSTRAINT_NAME
  133. WHERE i1.CONSTRAINT_TYPE = 'PRIMARY KEY'
  134. ) PT ON PT.TABLE_NAME = PK.TABLE_NAME";
  135.             SqlDataReader sqlReader = sqlCommand.ExecuteReader();
  136.             while (sqlReader.Read())
  137.             {
  138.                 Relationship singleRel = new Relationship();
  139.                 singleRel.tableA = sqlReader["K_Table"].ToString();
  140.                 singleRel.tableB = sqlReader["PK_Table"].ToString();
  141.  
  142.                 //Gibt's mehrere gleiche Beziehungen wird nur EINE dargestellt.
  143.                 if (!rel.Contains(singleRel))
  144.                 {
  145.                     rel.Add(singleRel);
  146.                 }
  147.  
  148.             }
  149.             sqlReader.Close();
  150.             return rel;
  151.  
  152.         }
  153.     }

Die damit erzeugte Datei „test.gml“ kann man nun mit YED öffnen – und sieht dann so aus:

ERMYED_First

Alle „Kästchen“ sind hier hintereinander angeordnet, da ich mit obigem Programm nur ein vereinfachtes GML-Format angelegt habe. Das macht aber nichts, denn YED kann nun daraus ein übersichtliches Diagramm machen!

Man wählt dazu lediglich aus:

Layout – Orthogonal – Kompakt
YedMenue

Und siehe da: nun habe ich ein schönes Datenmodell, das ich nur noch ein bischen aufhübschen muß! Die Breite der Kästchen ändert man am besten gleich zuerst: alles markieren und per Maus breiter ziehen. Hintergrundfarbe festlegen, etwas rumspielen und fertig:

ERMYED

Einzige Voraussetzung ist, dass die Beziehungen zwischen den Tabellen auch in der Datenbank als Relationships angelegt sind.

Danke an
Bernhard für den Tipp mit YED
Pinal Dave für die Select-Anweisung

0 Antworten zu „Automatisches Erzeugen eines Datenbankdiagrams aus einer MSSQL-Datenbank mit Hilfe von YED“



  1. Noch keine Kommentare

Eine Antwort schreiben




 

Juli 2009
M D M D F S S
« Jun    
 12345
6789101112
13141516171819
20212223242526
2728293031  

Kategorien