MSBuild & SQL Server Database Project: bind the de

2019-07-14 07:06发布

问题:

Visual Studio 2012. SQL Server Database Project.

Four build configurations were created in solution: Debug, DevDb, TestDb, LocalDb.

Three publish profiles were created in project: DevDb.publish.xml, TestDb.publish.xml, LocalDb.publish.xml

Pushing F5 button (!) I want to:

  • deploy project with connection string from project properties if build configuration is Debug.
  • publish project with connection string from the corresponding publish profiles if build configuration is DevDb, TestDb or LocalDb.

To do this I edit project (.sqlproj) xml, trying to catch a call of the Deploy target and replace the standart Deploy target with a custom behavior:

<Target Name="Deploy">     

    <!-- The first statment is for Debug configuration  -->

    <MSBuild Condition=" '$(Configuration)' == 'Debug' "
      Targets="Deploy"
      Projects="$(MSBuildProjectFile)"
      Properties="Configuration=$(Configuration);" 
    />

    <!-- The second statement is for DevDb, TestDb, LocalDb configurations  -->

    <MSBuild Condition=" '$(Configuration)' != 'Debug' "
      Targets="SqlPublish"
      Projects="$(MSBuildProjectFile)"
      Properties="SqlPublishProfilePath=$(Configuration).publish.xml;
                  Configuration=$(Configuration);"
    />       
 </Target> 

The second statement works fine and I get deployment to the right destination.

The problem is with the first statement - it produces a circular dependency.

error MSB4006: There is a circular dependency in the target dependency graph involving target "Deploy".

My question is: how to intersect (catch and replace) the standart target and if it's required to invoke the standart target again?

Or am I trying to reinvent the wheel and there is another way to do what I want? (What I want is described above under words "Pushing F5 button" :)

回答1:

I think I've got the solution.

So if we put such a PropertyGroup with Condition and a custom Target to the end of database project xml file:

<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">

    ----------- Skip -----------

  <PropertyGroup Condition=" '$(Configuration)' != 'Debug' and Exists('$(Configuration).publish.xml')">
    <DeployDependsOn>
      PublishDatabase
    </DeployDependsOn>
  </PropertyGroup>

  <Target Name="PublishDatabase"> <!-- Custom Target -->
    <Message 
        Text="Deploy is replaced with SqlPublish for configuration = $(Configuration)"
        Importance="high" />

    <MSBuild 
        Targets="SqlPublish" 
        Projects="$(MSBuildProjectFile)"
        Properties="SqlPublishProfilePath=$(Configuration).publish.xml;
                    Configuration=$(Configuration);" />
  </Target>
</Project>

we will get the following behaviour:

  • If the solution build configuration is differ from Debug and the publish profile *.publish.xml exists, then the Deploy target and operation will be replaced with SqlPublish target and this publish operation will get the required configuration such as connection string from the corresponding publish profile.
  • If the solution build configuration is Debug, then we preserve the standart Visual Studio behaviour when it take th connection string from the project properties.