Invoke EntityDeploy build task programmatically

后端 未结 2 1397
名媛妹妹
名媛妹妹 2021-02-14 19:11

I\'m using Roslyn to compile, emit and run C# source code. However, I\'ve run into a limitation when faced with projects that use EntityFramework.

It seems that simply e

相关标签:
2条回答
  • 2021-02-14 19:49

    I'm not familiar with EntityDeploy, but I'll give some information that I've gathered that might help you.

    If you look at the targets file you can see that there's an EntityDeploy target which relies on EntityDeploy, EntityDeploySplit, EntityDeploySetLogicalNames and EntityClean tasks.

    When the EntityDeploy target is called with list of .edmx files the following happens:

    1. EntityDeploySplit is invoked, it reads the .edmx files and determines whether the results from processing each one should be embedded in the target assembly or placed alongside.
    2. EntityDeploy is called on NonEmbeddingItems from 1., it splits the .edmx files and places the result in OutputPath
    3. EntityDeploy is called on EmbeddingItems from 1., it splits the .edmx files and places the result in EntityDeployIntermediateResourcePath
    4. EntityDeploySetLogicalNames is called on the files in EntityDeployIntermediateResourcePath to set the metadata LogicalName on each file to the logical name to be used for embedding (It's just the relative path to the file from EntityDeployIntermediateResourcePath with slashes replaced by dots)
    5. EntityClean is called to remove the intermediate files

    I haven't tried this, but it should be possible to call these in sequence to get the expected behavior using the Engine class:

     // Instantiate a new Engine object
     Engine engine = new Engine();
    
     // Point to the path that contains the .NET Framework 2.0 CLR and tools
     engine.BinPath = System.Environment.GetFolderPath(System.Environment.SpecialFolder.System)
    + @"\..\Microsoft.NET\Framework\v2.0.50727";
     var entityDeploySplitTask = new EntityDeploySplit();
     entityDeploySplitTask.Sources = new ITaskItem[] 
     {
       new TaskItem("Model.edmx")// path to .edmx file from .csproj
     };
     entityDeploySplitTask.BuildEngine = engine;
     entityDeploySplitTask.Execute();
    
     var entityDeployTask = new EntityDeploy();
     entityDeployTask.Sources = entityDeploySplitTask.NonEmbeddingItems
     entityDeployTask.OutputPath = "."; // path to the assembly output folder
     entityDeployTask.BuildEngine = engine;
     entityDeployTask.Execute();
    
     var entityDeployTask2 = new EntityDeploy();
     entityDeployTask2.Sources = entityDeploySplitTask.EmbeddingItems
     entityDeployTask2.OutputPath = "C:\Temp"; // path to an intermediate folder
     entityDeployTask2.BuildEngine = engine;
     entityDeployTask2.Execute();
    
     var entityDeploySetLogicalTask = new EntityDeploySetLogicalNames();
     entityDeploySetLogicalTask.Sources = Directory.EnumerateFiles("C:\Temp", "*.*", SearchOption.AllDirectories)
         .Select(f => new TaskItem(f)).ToArray();
     entityDeploySetLogicalTask.ResourceOutputPath = "C:\Temp"; // path to the intermediate folder
     entityDeploySetLogicalTask.BuildEngine = engine;
     entityDeploySetLogicalTask.Execute();
    
     foreach(var resourceFile in entityDeploySetLogicalTask.ResourcesToEmbed)
     {
        var fileName = resourceFile.GetMetadata("Identity");
        var logicalName = resourceFile.GetMetadata("LogicalName");
        //TODO: Embed filename using logicalName in the output assembly
        //You can embed them as normal resources by passing /resource to csc.exe
        //eg. /resource:obj\Debug\edmxResourcesToEmbed\Models\SampleEF.csdl,Models.SampleEF.csdl
     }
    
     //TODO: call EntityClean or just remove all files from the intermediate directory
    
    0 讨论(0)
  • 2021-02-14 19:55

    Try the following:

    var mockObject = new Mock<IBuildEngine>();
    IBuildEngine engine = mockObject.Object;
    
    var entityDeployTask = new EntityDeploy();
    entityDeployTask.Sources = new ITaskItem[] 
    {
      new TaskItem(@"path to edmx\Model1.edmx")
    };
    entityDeployTask.OutputPath = @"C:\";
    entityDeployTask.BuildEngine = engine;
    entityDeployTask.Execute();
    

    The output path doesn't seem to be picked up, but if it's empty then an error is logged. You can see this if you implement your own IBuildEngine and log the errors. The result of the process will be three files next to the edmx: "Model1.ssdl", "Model1.csdl", "Model1.msdl". These files need to be passed to CSC as embedded resources, at least that's what the original targets file seems to do.

    Hope it helps, and at least gets you started.

    0 讨论(0)
提交回复
热议问题