2013-08-01 16 views
11

Chúng tôi đang tìm cách nâng cấp dbproj của chúng tôi lên sqlproj để chúng tôi có thể trỏ nó vào cơ sở dữ liệu SQL 2012 mới. Chúng tôi có một chương trình tại thời điểm này đọc tệp .dbschema xml để tìm tất cả các bảng và cột và truy xuất thông tin từ chúng. Chúng tôi sử dụng dữ liệu này để xây dựng các lớp tùy chỉnh của riêng chúng tôi.Cách di chuyển một dacpac

Tệp sqlproj mới giờ đây tạo ra một dacpac mà chúng tôi muốn can thiệp để lấy dữ liệu mà chúng tôi cần. Tôi đã viết những điều sau đây để thử và đi qua dacpac và nhận được những thông tin mà tôi cần:

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); 
          } 
         } 
        } 
       } 
      } 
     } 
    } 
} 

Tôi không có ý tưởng nếu tôi đang làm điều này một cách đúng đắn, hoặc nếu có một/cách dễ dàng hơn tốt hơn nhiều . Tôi không chắc chắn nên tìm kiếm gì trên Google/S.E. và không thể tìm thấy bất kỳ ví dụ nào.

Tôi có thể thấy rằng cột biến có một thành viên không phải là công khai được gọi là ContextObject là một Microsoft.Data.Tools.Schema.Sql.SchemaModel.SqlSimpleColumn. Nếu tôi có thể truy cập đối tượng này thì tôi sẽ có thể lấy tất cả thông tin tôi cần từ nó. Bảng cũng có một ContextObject tương tự sẽ giúp tôi.

Dù sao, hiện tại, điều này sẽ mở dacpac và truy xuất tất cả tên bảng và cột. Một ví dụ về dữ liệu tôi nhận được là:

[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 

Về cơ bản, tôi muốn làm một trong các cách sau:

  1. Truy cập ContextObject để có được một Microsoft.Data.Tools.Schema.Sql .SchemaModel. * Đối tượng HOẶC
  2. lấy giá trị tài sản và siêu dữ liệu từ tài sản ObjectType HOẶC
  3. Bắt đầu từ đầu với một cách dễ dàng hơn để có được thông tin này ra

Chúng ta cần để có được thông tin ra ngoài như các loại cột, howif nó nullable, và quy mô và độ chính xác của một cột

Trả lời

1

Cách mà chúng tôi đã tìm thấy để làm điều đó là để tìm tài sản trong loại đối tượng sử dụng LINQ, và sau đó sử dụng phương pháp GetProperty để lấy giá trị:

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

này vẫn không có cảm giác như lựa chọn tốt nhất, vì vậy nếu ai đó có một câu trả lời tốt hơn xin vui lòng gửi nó.

4

Vì vậy, có một nhóm siêu dữ liệu được xác định đầy đủ mà bạn có thể sử dụng khi truy vấn mô hình. Điều này đơn giản hơn là dựa vào LINQ và cần kiểm tra tên chuỗi của mỗi thuộc tính. Xem ví dụ TableColumn các lớp học. Tôi đã cập nhật ví dụ của bạn cho thấy cách chúng được sử dụng:

// 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

Điều này rất hữu ích. Thật không may cho tôi hỗ trợ tương tự dường như không tồn tại trên các loại bảng do người dùng định nghĩa. ví dụ. model.GetObjects (DacQueryScopes.UserDefined, ModelSchema.TableType); Cố gắng để có được SqlDataType không làm việc cho những vì DataType không được hỗ trợ trên loại "TableTypeColumn". Tôi đã giả định rằng các kiểu bảng do người dùng định nghĩa sẽ thừa hưởng từ TableType bình thường. – Davos

+1

Xin chào Davos, chúng tôi coi các lớp siêu dữ liệu Bảng và TableType là hoàn toàn riêng biệt, do đó bạn cần phải sử dụng truy vấn khác cho TableType. Bạn sẽ có thể sử dụng GetReferenced (TableTypeColumn.DataType) để tìm kiểu dữ liệu.Khi bạn nhận thấy không có sự thừa kế giữa hai loại - toàn bộ ngăn xếp mối quan hệ từ Bảng-> Cột và Bảng loại-> TableTypeColumn là khác nhau. –

+0

Cảm ơn bạn một lần nữa, tôi nghĩ rằng tôi đã nhận nó bây giờ :) \t \t List > tvpcols = tvp.GetReferenced() \t \t \t \t \t \t \t \t \t \t \t .Where (c = > c.ObjectType.Name == "TableTypeColumn") \t \t \t \t \t \t \t \t \t \t \t .Chọn (c => Tuple.Cre ăn (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