2013-08-01 15 views
11

Szukamy ulepszenia naszego dbproj do sqlproj, abyśmy mogli skierować go do nowej bazy danych SQL 2012. Mamy program, który wczytuje plik .dbschema xml, aby znaleźć wszystkie tabele i kolumny oraz pobrać z nich informacje. Używamy tych danych do tworzenia własnych niestandardowych klas.Jak przejść przez dacpac

Nowy plik sqlproj produkuje teraz dacpac, który chcemy przeportować, aby uzyskać potrzebne dane. Pisałem następujące spróbować i przemierzać dacpac i uzyskać informację, że muszę:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 
using Microsoft.SqlServer.Dac; 
using Microsoft.SqlServer.Dac.Extensions; 
using Microsoft.SqlServer.Dac.Model; 
namespace DacPacReader 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      using (System.IO.TextWriter writter = new System.IO.StreamWriter(@"c:\temp\output.txt")) 
      { 
       using (TSqlModel model = new TSqlModel(@"C:\temp\Data.dacpac")) 
       { 
        var allTables = model.GetObjects(DacQueryScopes.All, ModelSchema.Table); 

        foreach (var table in allTables) 
        { 
         writter.WriteLine(table.Name); 
         foreach (var column in table.GetChildren().Where(child => child.ObjectType.Name == "Column")) 
         { 
          writter.WriteLine("\t" + column.Name); 
          writter.WriteLine("\tProperties:"); 
          foreach (var property in column.ObjectType.Properties) 
          { 
           writter.WriteLine("\t\t" + property.Name + "\t\t" + property.DataType.FullName); 
          } 
          writter.WriteLine("\tMetadata:"); 
          foreach (var metaData in column.ObjectType.Metadata) 
          { 
           writter.WriteLine("\t\t" + metaData.Name + "\t\t" + metaData.DataType.FullName); 
          } 
         } 
        } 
       } 
      } 
     } 
    } 
} 

nie mam pojęcia, czy robię to we właściwy sposób, lub jeśli jest to znacznie lepszy/łatwiejszy sposób . Nie jestem pewien, czego szukać w Google/S.E. i nie można znaleźć żadnych przykładów.

Widzę, że kolumna zmiennej ma niepubliczny element członkowski o nazwie ContextObject, który jest Microsoft.Data.Tools.Schema.Sql.SchemaModel.SqlSimpleColumn. Gdybym mógł uzyskać dostęp do tego obiektu, byłbym w stanie wyciągnąć wszystkie potrzebne informacje. Tabela ma również podobny obiekt ContextObject, który mógłby mi pomóc.

W każdym razie, obecnie to otwiera dacpac i pobiera wszystkie nazwy tabel i kolumn. Przykładem danych pojawia się:

[dbo].[User] 
    [dbo].[User].[UserID] 
    Properties: 
     Collation  System.String 
     IsIdentityNotForReplication  System.Boolean 
     Nullable  System.Boolean 
     IsRowGuidCol  System.Boolean 
     Sparse  System.Boolean 
     Expression  Microsoft.Data.Tools.Schema.Sql.SchemaModel.SqlScriptProperty 
     Persisted  System.Boolean 
     PersistedNullable  System.Nullable`1[[System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] 
     Scale  System.Int32 
     Precision  System.Int32 
     Length  System.Int32 
     IsMax  System.Boolean 
     XmlStyle  Microsoft.SqlServer.Dac.Model.XmlStyle 
     IdentityIncrement  System.String 
     IdentitySeed  System.String 
     IsFileStream  System.Boolean 
     IsIdentity  System.Boolean 
    Metadata: 
     ColumnType  Microsoft.SqlServer.Dac.Model.ColumnType 

Zasadniczo chciałbym wykonać jedną z następujących czynności:

  1. dostęp do ContextObject uzyskania Microsoft.Data.Tools.Schema.Sql .SchemaModel. * obiekt LUB
  2. Pobierz wartość nieruchomości i metadanych z właściwości objectType LUB
  3. zaczynać od zera z łatwiejszy sposób, aby uzyskać te informacje się

Musimy uzyskać informacje na zewnątrz, takich jak typ kolumny, howif To pustych, a skala i precyzja kolumny

Odpowiedz

1

Sposób, że udało nam się znaleźć na to jest znalezienie nieruchomości w rodzaju obiektu za pomocą LINQ, a następnie za pomocą metody GetProperty uzyskać wartość:

bool isNullable = (bool)column.GetProperty(column.ObjectType.Properties.Where(p => p.Name == "Nullable").First()); 

ten nadal nie czuje się jak najlepszą opcją, więc jeśli ktoś ma lepszą odpowiedź proszę umieszczać go.

4

Istnieje więc w pełni zdefiniowany zestaw klas metadanych, których można używać podczas wysyłania zapytań do modelu. Jest to prostsze niż poleganie na Linq i konieczność przetestowania nazw łańcuchów każdej właściwości. Zobacz klasy Table i Column dla przykładu. Zaktualizowałem Twój przykład pokazujący, w jaki sposób są one używane:

// Query for UserDefined objects to just filter to your own objects. All will 
// include system objects (references to objects in master.dacpac if you reference that 
// and BuiltIn objects such as the data types. You probably don't care about those 
var allTables = model.GetObjects(DacQueryScopes.UserDefined, Table.TypeClass); 

foreach (var table in allTables) 
{ 
    writter.WriteLine(table.Name); 
    // Columns are referenced by tables, so GetReferenced can be used. The GetChildren can also be used 
    // but filtering by comparing "child.ObjectType == Column.TypeClass" would simplify your example 
    foreach (var column in table.GetReferenced(Table.Columns)) 
    { 
     // Now you can use the Column metadata class's properties to query your Column object 
     bool isNullable = column.GetProperty<bool>(Column.Nullable); 
     SqlDataType sdt = column.GetReferenced(Column.DataType).First().GetProperty<SqlDataType>(DataType.SqlDataType); 
    } 
+0

Jest to bardzo pomocne. Niestety dla mnie ta sama obsługa nie wydaje się istnieć na zdefiniowanych przez użytkownika typach tabel. na przykład model.GetObjects (DacQueryScopes.UserDefined, ModelSchema.TableType); Próba uzyskania SqlDataType nie działa dla nich, ponieważ DataType nie jest obsługiwany na typ "TableTypeColumn". Założę się, że typy tabel definiowane przez użytkownika dziedziczą po prostu od zwykłego TableType. – Davos

+1

Witaj Davos, traktujemy klasy metadanych Tabela i TableType jako całkowicie oddzielne, więc musisz użyć innego zapytania dla TableType. Powinieneś być w stanie użyć GetReferenced (TableTypeColumn.DataType), aby znaleźć typ danych.Jak zauważyłeś, nie ma dziedziczenia między tymi dwoma typami - cały stos relacji od Table-> Column i TableType-> TableTypeColumn jest inny. –

+0

Dziękuję jeszcze raz, myślę, że mam go teraz :) \t \t List > tvpcols = tvp.GetReferenced() \t \t \t \t \t \t \t \t \t \t \t .gdzie (c = > c.ObjectType.Name == "TableTypeColumn") \t \t \t \t \t \t \t \t \t \t \t .Select (C => Tuple.Cre metylu (c.Name.Parts.Last(), c.GetReferenced (TableTypeColumn.DataType) .Last(). GetProperty (DataType.SqlDataType) .ToString())) \t \t \t \t \t \t \t \t \t \t \t \t \t \t .ToList(); – Davos

Powiązane problemy