c# - 如何从 Visual Studio 扩展获取 SSDT 数据库项目内存模型的引用?

标签 c# visual-studio visual-studio-extensions sql-server-data-tools envdte

我正在尝试为 Visual Studio 2013 编写一个简单的扩展,它应该能够列出该扩展的用户选择的 SQL Server 数据库项目中的所有表。为此,我需要访问数据库项目的内存模型。但我发现的唯一方法是将数据库项目生成的编译后的 .dacpac 文件加载到新的 TSqlModel 实例并查询它,但我宁愿能够使用“实时”内存中表示。我找到了 SSDT API 的教程:http://blogs.msdn.com/b/ssdt/archive/2013/12/23/dacfx-public-model-tutorial.aspx ,但没有示例如何连接到 Visual Studio 中的内存模型。我还找到了一个解决此问题的教程,方法是从当前解决方案中收集所有具有 .sql 扩展名的文件并将其内容添加到 TSqlModel 实例中,但这不是我喜欢的方式。

这样的事情可能吗?如果是这样,该怎么做?

谢谢你, 米哈尔

最佳答案

数据库项目目前不提供可访问模型的 Visual Studio 服务。不过,您可以通过 Hook 项目系统事件并使用 API 来建立您自己的模型来模拟这一点。 Dave Ballantyne 在 this blog post 中展示了执行此操作的静态方法。 。如果您想使其更加动态,您可以连接到项目事件,例如项目/文件添加、删除、更改等,并根据这些事件更新您的模型。这就是数据库项目内部发生的事情。请注意,您还应该使用 AddOrUpdateObjects API 调用,而不是他使用的 API 调用,因为这允许您在文件更改时更新文件:

    public void ProcessProjectModels()
    {
        var hostServiceProvider = (IServiceProvider)this.Host;
        var dte = (DTE)hostServiceProvider.GetService(typeof(DTE));

        using (TSqlModel model = new TSqlModel(SqlServerVersion.Sql110, new TSqlModelOptions { }))
        {
            foreach (Project project in dte.Solution)
            {
                IterateThroughProject(project.ProjectItems, model);
            }

            List<TSqlObject> allTables = GetAllTables(model);
            foreach (var table in allTables)
            {
                // Do processing 
            }
        }
    }

    public List<TSqlObject> GetAllTables(TSqlModel model)
    {
        List<TSqlObject> allTables = new List<TSqlObject>();

        var tables = model.GetObjects(DacQueryScopes.All, ModelSchema.Table);
        if (tables != null)
        {
            allTables.AddRange(tables);
        }
        return allTables;
    }

    private void IterateThroughProject(ProjectItems PrjItems, TSqlModel model)
    {
        foreach (ProjectItem PrjItem in PrjItems)
        {
            if (PrjItem.ProjectItems != null)
            {
                IterateThroughProject(PrjItem.ProjectItems, model);
            }
            if (//PrjItem.Object.GetType().ToString() == "Microsoft.VisualStudio.Data.Tools.Package.Project.DatabaseFileNode" && 
                PrjItem.Name.EndsWith(".sql", StringComparison.OrdinalIgnoreCase))
            {
                // This is a sql file and will be processed
                // Note: There should be a separate API to read the live contents of this item, to avoid the need to save it
                if (!PrjItem.Saved)
                {
                    PrjItem.Save();
                }
                StreamReader Reader = new StreamReader(PrjItem.FileNames[0]);

                string Script = Reader.ReadToEnd();
                model.AddOrUpdateObjects(Script, PrjItem.Name, null);
            }
        }
    }

注意:此功能没有内置支持的原因是,要正确执行此功能,项目应该提供只读模型(无法添加/更新脚本)或确保实际添加/更新对象调用影响项目中的相关脚本文件。如果您要对更改事件进行处理(正如项目系统支持的那样),它还应该支持事件通知。如果这对您有用(我可以想象在这种情况下会如此),那么打开 Connect bug 或在 Visual Studio 用户声音中提出它是让产品团队注意到这一点的方法。

关于c# - 如何从 Visual Studio 扩展获取 SSDT 数据库项目内存模型的引用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28551809/

相关文章:

c# - Java Socket.getInetAddress() 的 C# 等效项是什么?

c# - PING 的回复是否包含原始数据?

visual-studio - Visual Studio 中的字符串到函数名称

visual-studio - 安装 WinCE 5.0 Platform Builder SDK - 使用 Visual Studio 2012 或更高版本构建代码

c# - 使用命令筛选器在 Visual Studio 扩展中随机崩溃

visual-studio - Visual Studio 定期抛出异常

c# - 如何从 MS Outlook 2010 中检索抄送电子邮件地址?

c# - 如何使用 Windsor 容器注入(inject) Func<T,U>

visual-studio - WinForms 性能问题

c# - 如何获取 Visual Studio 2017 的当前主题