簡體   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