首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何遍历dacpac

如何遍历dacpac
EN

Stack Overflow用户
提问于 2013-08-01 00:51:41
回答 2查看 4K关注 0票数 12

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

新的sqlproj文件现在产生一个dacpac,我们想要插入它来获取我们需要的数据。我写了以下文章,试图遍历dacpac并获得我需要的信息:

代码语言:javascript
复制
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/S.E上搜索什么,也找不到任何例子。

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

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

代码语言:javascript
复制
[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.*对象或
  2. 从ObjectType属性或
  3. 从零开始,用一种更简单的方法获取这些信息。

我们需要获取信息,例如列类型,如果它是可空的,以及列的规模和精度

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-08-05 02:21:06

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

代码语言:javascript
复制
bool isNullable = (bool)column.GetProperty(column.ObjectType.Properties.Where(p => p.Name == "Nullable").First());

这仍然不是最好的选择,所以如果其他人有一个更好的答案,请张贴它。

票数 1
EN

Stack Overflow用户

发布于 2013-12-14 21:27:37

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

代码语言:javascript
复制
// 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);
    }
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17983499

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档