Search code examples
.netvisual-studiomsbuildnugetcsproj

Is there a correct way to reference a sqlproj project from a csproj project using Directory.Build.Props?


I am implementing a new solution which is dependent on a number of "content only" NuGet packages. These include a number of assemblies and dacpacs which I need to reference.

My intention was to have a SDK-style csproj which references all of the packages using PackageReference elements. I then planned on using Directory.Build.Props to give all of the other projects in my solution a reference to this project so it would be built first (and all of my dependencies would be available at the start of the build).

This worked, but at the point I added sqlproj's to consume the dacpacs I started hitting complications (I had already added a number of SDK-style csproj files to my solution, which all worked as I had expected).

When having a sqlproj file reference an SDK-style csproj file I found Visual Studio would hang on start up (a known bug documented here).

I then tried replacing this project with a traditional csproj file. Below I have snippets from my Directory.Build.Props that I had tried to automatically create the references from my csproj's and sqproj's to my project responsible for restoring NuGet packages.

The following failed to work because the NuGet.Restore project (which is now a traditional csproj gets a cyclical reference as it does not seem to adhere to the condition):-

  <ItemGroup Condition=" '$(MSBuildProjectName)'!='NuGet.Restore' ">
    <ProjectReference Include="$(MSBuildThisFileDirectory)NuGet.Restore.csproj" />
  </ItemGroup>

The following resolves the cyclical reference but the sqlproj's fail to load in Visual Studio with the error "Cannot modify an evaluated object originating in an imported file":-

  <Choose>
    <When Condition=" '$(MSBuildProjectName)'!='NuGet.Restore' ">
      <ItemGroup>
        <ProjectReference Include="$(MSBuildThisFileDirectory)NuGet.Restore.csproj" />
      </ItemGroup>
    </When>
  </Choose>

Is there any other way I can make the reference from a sqlproj to a csproj (traditional or SDK-style) work with MSBuild and Visual Studio by flexing Directory.Build.props?

As far as I am aware, the only way I can ensure MSBuild will run my restore project first is to make every other project reference it.

I am approaching the point where the only viable option is going to be to have a separate pre-build script that must be manually run to retrieve the NuGet packages before running our solution build (what I had been hoping to avoid).


Solution

  • I have a workaround / solution for this, keeping my restore project as a traditional csproj. I've amended the condition so it excludes the sqlproj projects and then added the reference to my NuGet restore manually to each of the sqlproj files:-

     <Choose>
        <When Condition=" '$(MSBuildProjectName)'!='NuGet.Restore' AND '$(MSBuildProjectExtension)'!='.sqlproj' ">
          <ItemGroup>
            <ProjectReference Include="$(MSBuildThisFileDirectory)NuGet.Restore.csproj" />
          </ItemGroup>
        </When>
      </Choose>
    

    (This may not be suitable for everyone, but as we do not expect to add any further sqlproj projects in the future this hopefully won't cause us any maintenance headaches!)