如何穿越dacpac

我们希望将dbproj升级到sqlproj,以便我们可以将其指向新的SQL 2012数据库。 我们现在有一个程序读取.dbschema xml文件以查找所有表和列并从中检索信息。 我们使用这些数据来构建我们自己的自定义类。

新的sqlproj文件现在生成一个dacpac,我们想要进行干预以获取我们需要的数据。 我写了以下内容来尝试遍历dacpac并获取我需要的信息:

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

我不知道我是以正确的方式做这件事,还是有更好/更容易的方式。 我不确定在Google / SE上搜索什么,但找不到任何示例。

我可以看到变量列有一个名为ContextObject的非公共成员,它是一个Microsoft.Data.Tools.Schema.Sql.SchemaModel.SqlSimpleColumn。 如果我可以访问此对象,那么我将能够从中获取所需的所有信息。 表也​​有一个类似的ContextObject,它可以帮助我。

无论如何,目前这将打开dacpac并检索所有表和列名称。 我得到的数据的一个例子是:

 [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 

基本上,我想做以下其中一项:

  1. 访问ContextObject以获取Microsoft.Data.Tools.Schema.Sql.SchemaModel。*对象OR
  2. 从ObjectType属性OR获取属性和元数据的值
  3. 从头开始,以更简单的方式获取此信息

我们需要获取信息,例如列类型,如何它可以为空,以及列的比例和精度

因此,在查询模型时可以使用一组完全定义的元数据类。 这比依赖Linq并且需要测试每个属性的字符串名称更简单。 有关示例,请参阅表和列类。 我已经更新了您的示例,说明了如何使用它们:

 // 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(Column.Nullable); SqlDataType sdt = column.GetReferenced(Column.DataType).First().GetProperty(DataType.SqlDataType); } 

我们发现这样做的方法是使用Linq在对象类型中查找属性,然后使用GetProperty方法获取值:

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

这仍然不是最佳选择,所以如果其他人有更好的答案,请发布。