Duplicate project reference in SSDT Database solution - visual-studio-2017

I am using tSQLt in a solution having multiple SQL Server Database projects in it. For each project, there is a .Test project which is referencing the original one and the tSQLt source.
Here is quick outline of the solution:
Solution
Project DB1
Project DB1.Test
Project DB2
Project DB2.Test
Project TSQLT
Where
Project DB2 depends on Project DB1
Project DB1.Test depends on DB1 and TSQLT (using the 'Same database' option)
Project DB2.Test depends on DB2 and TSQLT (using the 'Same database' option) and on DB1.Test (Same server, different database with a variable). since DB1.Test depends on DB1 and TSQLT, this project also depends on them (using the same variable used for DB1.Test).
The problem is that the reference to DB1.Test does not bring the TSQLT and DB1 objects when it is referenced from DB2.Test, so I get a huge list of warnings about unresolved references.
Warnings related to DB1 can be solved by referencing that project using the same variable as DB1.Test, but TSQLT is already referenced here and when I try to reference it twice, it leads to a "duplicate reference" error.
An obvious solution would be to make a copy of the TSQLT project in the solution, but honestly I just don't want to dupicate code.
Another would be to build that project using different configurations and simply reference the .dacpac files instead, but this feels like a hack.
We in theory could move the TSQLT project outside of the solution and have multiple copies of the dacpac file and reference those, however I am trying to keep everything in one place.
Currently we don't have NuGet repositories in place, so distributing code using NuGet packages to keep that part up-to-date does not work either.
I tried to reference it twice, but with different variable names, it still leads to the duplicate reference error.
I am aware, that unresolved reference errors in nested references scenario can be solved by adding all levels to the the project as a reference, but in this case one of the projects is used twice and duplicates are not allowed.
Is there any solution to either carry forward the references when there are nested references?
Or to have the local copy of the dacpac file generated during build saved using a custom (unique) name when it is copied from one project to another during build?
Please note that there are no circular references, just a project is used in multiple levels in the solution and without having the TSQLT reference in place for all instances, the build works just fine, just the warnings are annoying.
I am aware of the 'suppress warnings' option, but I would like to have them turned off. (This won't make the object magically appear in IntelliSense).
Turning the 'Local Copy' option on or off does not make any difference in behavior in this case.

I found a solution, which is still a bit smells like a hack, but working properly.
Build event
Add a post-build event to the common project:
Right click on the common project (TSQLT in this case)
Select Properties...
Go to the Build Events tab
Click on Edit Post-build...
Copy the following code into the editor window
Modify it to your needs
Save all when done (this will save the project and solution files)
copy "$(ProjectName).dacpac" "$(ProjectName)_DB1.dacpac" /Y
copy "$(ProjectName).dacpac" "$(ProjectName)_DB2.dacpac" /Y
This will create copies of the TSQLT.dacpac file in the output folder (TSQLT_DB1.dacpac and TSQLT_DB2.dacpac files will be created).
Make sure, that the build path for the dacpac file is using the $(ProjectName) variable, or use a hard-coded name and modify the build event accordingly.
Database reference
Reference these files as Data-tier application in the projects.
If you have multiple build configuration, open the .sqlproj file and edit it to have the build path dynamic:
<ArtifactReference Include="..\.build\$(Configuration)\TSQLT\TSQLT_DB1.dacpac">
<HintPath>..\.build\$(Configuration)\TSQLT\TSQLT_DB1.dacpac</HintPath>
<SuppressMissingDependenciesErrors>False</SuppressMissingDependenciesErrors>
<DatabaseSqlCmdVariable>DB1</DatabaseSqlCmdVariable>
<Private>False</Private>
</ArtifactReference>
<ArtifactReference Include="..\.build\$(Configuration)\TSQLT\TSQLT_DB2.dacpac">
<HintPath>..\.build\$(Configuration)\TSQLT\TSQLT_DB2.dacpac</HintPath>
<SuppressMissingDependenciesErrors>False</SuppressMissingDependenciesErrors>
<DatabaseSqlCmdVariable>DB2</DatabaseSqlCmdVariable>
<Private>False</Private>
</ArtifactReference>
Notice the $(Configuration) in the path. This method assumes, that the build configuration name is the same for all projects. (Basically we want the same thing here what you have in the build path(
Now you can remove the original project reference.
Build dependency
By removing the project reference, Visual Studio also removes the build dependency.
Right click on the solution
Select properties...
Go to Common Properties / Project Dependencies
Select the project from the drop-down list
Tick the checkbox in front of the referenced project
This ensures that building the current project will trigger the build of the referenced one (and that will run the post-build event).
Notes
I did update all projects in the solution which are using TSQLT to have artifact reference instead of project reference, this keeps the solution more consistent.
I did not change the reference to other projects, since I don't have this kind of issue with them.

Related

What is project reference in Visual Studio

there is a possibility to add an existing project as a "reference" to a solution in VS(talking about C++ now). As far as I understand it means that all the project files will be added to a solution and I can modify any properties and source code, and it will affect the original solution to which this project belongs. Do I have a correct understanding of it? Or is it something else?
I don't really get why we need it, if I need another project I can use it as a lib or DLL file, this reference thing seems to make things more complicated - if I do any changes to project properties I need to think how it will affect building another solution this project belongs to.
In Visual C++ "project-to-project" references within a solution really does two things:
If the referenced project is a static or DLL library, it's implicitly included in your referencing project's link statement.
The referenced project is considered a build-dependency for the referencing project so it will be built first.
That's pretty much it. If you want to include headers in the referenced project, you need to add it your AdditionalIncludes property for the referencing project.
For a DLL project, you can set a property on it to get it's DLL copied to your referencing project's build directory.
See Visual C++ Team Blog which was back in VS 2010 when it was first introduced.
There's a different model of code sharing called Shared Projects where the shared code is built in each referencing project--i.e. there's no shared binaries.

TFS Build 2015 - Using Globally Referred Files in Every Build

So, we are in this process of migrating XAML Builds to vNext (2015) Builds on TFS, and we are trying to "do things as clean as possible", since we had many, many customizations on the XAML builds that could be avoided and actually gave us problems along the way.
One major issue we are facing is with paths and "global files". Let me explain:
There are some files that, for commodity reasons, we have on a single place and every SLN file on that Collection refers them. Those files are such ones as Code Analysis RuleSets, Signing Files (SNK), etc. So the change is made in one place only and it affects every build.
Well, in XAML Builds we have a Build that runs with CI that downloads (Gets) those files, and since we hammered-in the same exact pathing for TFS and Machine (with a environment variable for the beginning of the path), the path is the same on the Developers and Build machines. However, this creates dependencies between builds and workspace issues.
My question here is, is there a configuration that I am missing that allows referring to files in other branches other than the build one? Since I’m trying to keep the build machines as “disposable” as possible, it’s running with an Agent Config Out of the Box: No custom paths, no hardwiring.
I already tried referring the files directly with their source control path, for example. The only options I’m seeing are either creating a PowerShell/CMD Script that downloads those files right into the same folder as the SLN or keeping it “as it is” and use relative paths putting a “Build” Build Step before the actual Build Step so it downloads the files to the server.
Isn’t there an “Elegant” way of doing this? Or is our methodology wrong from the get go?
You can add a Copy Files step to copy the files that the build needs:

Prevent BizTalk projects from invoking a full rebuild?

I'm on a BizTalk 2013 solution and I'm trying to grow into automated testing. However, when I try to run my tests after changing only the test project, or even just run the tests after changing nothing anywhere, I'm stuck building the same amount of projects that I build when I invoke a full rebuild on the project being tested. This eats up an enormous amount of time, and it's a death sentence for my ability to sell future investments into this type of thing.
Is this is a known deficiency with BizTalk, or with its interaction with MSBuild? Is it a known pitfall that I can repair on my end?
EDIT: After reviewing the "possible duplicate" thread, I believe this question to be similar, but distinct. The explanation from the thread highlights the mechanics by which MSBuild determines that a rebuild is necessary, but MSBuild is widely-used technology across all projects in Visual Studio and can differ significantly by project type based on that project type's specific targets import. I've edited the question title to reflect that I want to learn how to prevent this for BizTalk solutions rather than simply asking why it's happening (although knowing why is always helpful).
So, what you're seeing is not a problem with BizTalk (because BizTalk is perfect and wonderful and never has any problems ever...:).
It's actually a behavior of Visual Studio. To note, BizTalk Projects are just specialized c# Projects.
The best workaround, which I do all the time, is to uncheck the Build and Deploy options for Projects I'm not actively working with in the Solution Configuration. If the Project is not checked for Build, it will not build even when you choose Rebuild Solution.
One possible solution would be to reference not the projects, but the DLL files which are the result of the same - already compiled and built - projects.
This way, when building your test project, it would be built against these existing assemblies and hence would not take the time to rebuild those.
You have to make sure however that these DLLs are updated whenever the project behind them also updates. You could do this by rebuilding them, whenever necessary, in a separate Visual Studio instance.
It takes some practice and thinking to make sure you are building against the latest version, but it WILL save you a lot of time.
I've noticed this as well. Turning on diagnostic output on MSBuild, it turned out that the project settings .user files were being modified after the .pdb files. I've tried several ways of resolving this, including changing the modify date on the pdb file, setting the .user file to readonly, removing (renaming) the .user file, etc.
Unfortunately, the build task for BizTalk will overwrite/recreate/create new .user file after every build, and I haven't come up with a way to convince MSBuild that that it can just ignore the .user file being created as new. Due to that, I'd go with one of the other suggestions here.
Even creating an exclusive lock on the file so that MSBuild can't update it causes a rebuild, since then MSBuild thinks the build is dirty ("Project 'Schemas' is not up to date. Project dirty in MSBuild.")

VS2010: Add project reference in the properties sheet file

Our solution contains ~50 projects. There is a special one among them which has to be build almost first because almost every other project calls its executable. I know that through the Framework and References the build order can be defined by adding a reference to the project. Since I don't want to do it for every project and I want to ensure that every newly added project will reference the special one, my hope is that it is doable with the Properties Sheets
However, it seems that the Property Manager does not have option to modify the References for the .props files, at least I couldn't find it. Still, is there a way to do it?

TortoiseSVN and Visual Studio Express 2010

I'm using TotoiseSVN client and Assembla backend in a VS 2010 express project. We have issues with VS folders (or filters) dropping and files sometimes not being added to the project. I notice when I commit the .vcxproj and .vcxproj.filters files are never checked by default even though they should be changing. So I manually check them and told others to as well when they commit.
This can lead to issues if team member A checks out, only changes some code, while team member B has the project checked out and added files to the project. If team member B then commits BEFORE team member A, team member A's project file doesn't have the new files team member B added so now his project overwrites team members B's project file he checked in and now the new added files aren't in the project.
How do we get around this besides having amazing coordination?
CMake is perfect for this.
In case you haven't come across CMake, it allows you to create your entire project's build files in a separate directory to your source files, outside of svn altogether.
A single CMakeLists.txt file in your repository's root would replace all your current .vcxproj and .filters files.
I suspect what may be happening here is that the developers aren't saving the project files when adding new files to them. VS2008 did this by default, but I think that in VS2010 they aren't saved until you explicitly do File -> Save All. As a result it means that the changes are not getting committed. Once your devs do get in the habit of saving the project files before committing then SVN will in 99% of the time handle all the merges for you. The remaining 1% of the time is when someone has done some more major restructuring of the project file or two people have made conflicting changes to the build settings. In these cases you'd have to resolve them by hand.
SVN will never overwrite one person's changes with another, it will always try to merge. So if you're running into this problem it suggests that one person is somehow rolling back someone else's changes, or they don't have the option in Visual Studio set to reload files when changed externally: Tools -> Options -> Documents -> Detect when file is changed outside the environment.
An effective way of dealing with this problem is to set up a simple build server, eg with Jenkins that kicks off a build periodically after there have been some checkins. If the build fails then the person who checked in gets a mail to tell them they broke the build. You can also have a monitor that shows the build status which makes broken builds more visible to the whole team and hopefully encourages everyone to keep the build fixed.