繁体   English   中英

如何在Visual Studio 2013中自动化Package Manager控制台

[英]How to automate Package Manager Console in Visual Studio 2013

我的具体问题是如何在Entity Framework的构建过程中自动执行“添加迁移”。 在研究这个问题时,似乎最常见的方法是自动化这些步骤

  1. 在Visual Studio 2013中打开解决方案
  2. 在程序包管理器控制台中执行“Add-Migration blahblah”(最有可能通过加载项vsextention)
  3. 关闭解决方案

这个初始方法基于我自己的研究和这个问题 ,最终在Add-Migration背后的powershell脚本需要相当多的设置才能运行。 Visual Studio在创建程序包管理器控制台并使DTE对象可用时自动执行该设置。 我宁愿不尝试在Visual Studio之外复制该设置。

解决方案的一个可能途径是未解决的堆栈溢出问题

在研究NuGet API时,它似乎没有“发送此文本,它将像在控制台中键入的那样运行”。 我不清楚Visual Studio与NuGet之间的界限,所以我不确定这是否会存在。

我能够通过软件包管理器控制台中的“$ dte.Windows”命令找到“Pacakage Manager Console”,但在VS 2013窗口中,该集合为我提供了“Microsoft.VisualStudio.Platform.WindowManagement.DTE”对象。 .WindowBase”。 如果有一种方式填充文本,我想我需要把它变成一个NuGetConsole.Implementation.PowerConsoleToolWindow“通过查看源代码我不清楚文本是如何填充但我不熟悉我的内容我看到了。

最糟糕的情况是,我会回过头来尝试按照这个问题来填充密钥,但是不愿意这样做,因为这会使构建过程周围的自动化大大复杂化。

所有这些都说,

  1. 是否可以通过代码将命令流式传输到Visual Studio中的Package Manager控制台,该控制台已完全初始化并且能够支持实体框架“add-migration”命令?

感谢您提出任何建议,建议,帮助,非滥用,

约翰

对我有用的方法是从EntityFramework.Powershell项目中的AddMigrationCommand.cs开始跟踪实体框架代码,找到EntityFramework项目的钩子,然后使这些钩子工作,这样就没有Powershell依赖。

你可以得到像......

    public static void RunIt(EnvDTE.Project project, Type dbContext, Assembly migrationAssembly, string migrationDirectory,
        string migrationsNamespace, string contextKey, string migrationName)
    {
        DbMigrationsConfiguration migrationsConfiguration = new DbMigrationsConfiguration();
        migrationsConfiguration.AutomaticMigrationDataLossAllowed = false;
        migrationsConfiguration.AutomaticMigrationsEnabled = false;
        migrationsConfiguration.CodeGenerator = new CSharpMigrationCodeGenerator(); //same as default
        migrationsConfiguration.ContextType = dbContext; //data
        migrationsConfiguration.ContextKey = contextKey;
        migrationsConfiguration.MigrationsAssembly = migrationAssembly;
        migrationsConfiguration.MigrationsDirectory = migrationDirectory;
        migrationsConfiguration.MigrationsNamespace = migrationsNamespace;

        System.Data.Entity.Infrastructure.DbConnectionInfo dbi = new System.Data.Entity.Infrastructure.DbConnectionInfo("DataContext");
        migrationsConfiguration.TargetDatabase = dbi;

        MigrationScaffolder ms = new MigrationScaffolder(migrationsConfiguration);

        ScaffoldedMigration sf = ms.Scaffold(migrationName, false);

    }

您可以使用此问题到达dte对象,并从那里找到要传递给调用的项目对象。

这是对约翰答案的更新,我要感谢“困难部分”,但这里有一个完整的例子,它创建了一个迁移并将迁移添加到提供的项目(之前必须构建项目),与Add-Migration InitialBase -IgnoreChanges相同 - Add-Migration InitialBase -IgnoreChanges将:

public void ScaffoldedMigration(EnvDTE.Project project)
{
    var migrationsNamespace = project.Properties.Cast<Property>()
         .First(p => p.Name == "RootNamespace").Value.ToString() + ".Migrations";

    var assemblyName = project.Properties.Cast<Property>()
                           .First(p => p.Name == "AssemblyName").Value.ToString();
    var rootPath = Path.GetDirectoryName(project.FullName);
    var assemblyPath = Path.Combine(rootPath, "bin", assemblyName + ".dll");
    var migrationAssembly = Assembly.Load(File.ReadAllBytes(assemblyPath));
    Type dbContext = null;
    foreach(var type in migrationAssembly.GetTypes())
    {
        if(type.IsSubclassOf(typeof(DbContext)))
        {
            dbContext = type;
            break;
        }
    }

    var migrationsConfiguration = new DbMigrationsConfiguration()
        {
            AutomaticMigrationDataLossAllowed = false,
            AutomaticMigrationsEnabled = false,
            CodeGenerator = new CSharpMigrationCodeGenerator(),
            ContextType = dbContext,
            ContextKey = migrationsNamespace + ".Configuration",
            MigrationsAssembly = migrationAssembly,
            MigrationsDirectory = "Migrations",
            MigrationsNamespace = migrationsNamespace
        };

    var dbi = new System.Data.Entity.Infrastructure
                     .DbConnectionInfo("ConnectionString", "System.Data.SqlClient");
    migrationsConfiguration.TargetDatabase = dbi;

    var scaffolder = new MigrationScaffolder(migrationsConfiguration);
    ScaffoldedMigration migration = scaffolder.Scaffold("InitialBase", true);

    var migrationFile = Path.Combine(rootPath, migration.Directory,
                            migration.MigrationId + ".cs");
    File.WriteAllText(migrationFile, migration.UserCode);
    var migrationItem = project.ProjectItems.AddFromFile(migrationFile);

    var designerFile = Path.Combine(rootPath, migration.Directory,
                           migration.MigrationId + ".Designer.cs");
    File.WriteAllText(designerFile, migration.DesignerCode);
    var designerItem = project.ProjectItems.AddFromFile(migrationFile);
    foreach(Property prop in designerItem.Properties)
    {
        if (prop.Name == "DependentUpon")
            prop.Value = Path.GetFileName(migrationFile);
    }

    var resxFile = Path.Combine(rootPath, migration.Directory,
                       migration.MigrationId + ".resx");
    using (ResXResourceWriter resx = new ResXResourceWriter(resxFile))
    {
        foreach (var kvp in migration.Resources)
            resx.AddResource(kvp.Key, kvp.Value);
    }
    var resxItem = project.ProjectItems.AddFromFile(resxFile);
    foreach (Property prop in resxItem.Properties)
    {
        if (prop.Name == "DependentUpon")
            prop.Value = Path.GetFileName(migrationFile);
    }
}

我在项目模板的IWizard实现中执行此操作,我使用IgnoreChanges运行迁移,因为它与基础项目共享。 如果要包含更改scaffolder.Scaffold("InitialBase", true)更改为scaffolder.Scaffold("InitialBase", false)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM