Dynamic database reference in SSDT (dacpac) project - sql-server-data-tools

Is there a way where the database references in a SQL Server Database project (Dacpac) can be derived at run time?
We're building a product which uses Dacpac to deploy database objects.
Our product implementation teams also use Dacpac projects by adding database reference to the product Dacpac file and then adding their own additional objects to the project.
The problem we're facing is - every time the implementation needs to point to a newer product release version, the parent dacpac references in the implementation dacpac have to be changed manually to refer to the new file path of the new product dacpac (in the newer release). We've mutiple implementation teams and multiple database projects in each implementation.
Is there any way the database references (*.dacpac) in a database project can be derived at run time using a variable or parameter or something of that sort?

My understanding of your question is as follows:
You have a SSDT database project (see example image below), that has a database reference (similar to #1 below) with stored procedures and other db objects that access the reference database (similar to file #2 and code #3). You've 'built' the solution resulting in a DACPac and now you want to take this DACPac and reference other databases at deploy-time. Hopefully I understood your question correctly.
If so, then you can use the Publish Profiles feature to achieve this (similar to #4 below).
The code for this can be seen in my notes from my SSDT talk github project.
If you look specifically at the demo04 solution file, you will see that I have a DEV_MJE.deploy.ps1 PowerShell file and a DEV_MJE2.deploy.ps1 file. These scripts run MSBuild to build the DACPac and then use SqlPackage to publish DEV_MJE.publish.xml or DEV_MJE2.publish.xml respectively. Note, if you run this example on your machine, you'll need to add MSBuild.exe and SqlPackage.exe to your path, as well as modifying the TargetConnectionString in the xml files to an existing development database.
As an example of how this works...When I use the Publish Profile DEV_MJE.publish.xml, the resulting GetDataFromAnotherTable.sql file contains:
SELECT [SomeData] FROM [AnotherDb_MJE].[dbo].[AnotherTable]
Whereas when I use DEV_MJE2.publish.xml the resulting GetDataFromAnotherTable.sql file contains:
SELECT [SomeData] FROM [AnotherDb_MJE2].[dbo].[AnotherTable]
Notice the database reference in the second has changed to AnotherDb_MJE2.
For a good description of how Publish Profiles relate to DACPacs and SSDT Database Projects, see this web page. It also contains information on alternative ways to deploy beyond SqlPackage.exe.
Something else to consider
Note, that using file paths to version control a DACPac is not really the best practice. Consider the DACPac artifact as similar to a .Net DLL. It is the biproduct of a build.
As such, a better approach is to use NuGet and tools like Octopus Deploy to store, track, and deploy DACPacs. See the stackoverflow answer for a good description of how this works.
Hope that this helps,
Michael

Thanks for the followup comment, I think what you are trying to do is when you write and deploy your code be able to use different dacpacs depending on the project?
Each implementation team might have a different version of the shared dacpac deployed so you can't just put the files in a shared location and call the dacpac "Product_Latest.dacpac" or something, so everyone always gets the latest version.
".sqlproj" files are standard msbuild scripts and references can be managed using msbuild properties so you can technically change the reference at runtime. If you edit your .sqlproj file and add a property in the first <PropertyGroup> tag, I used:
<ProdDacpacVersion Condition="'$(ProdDacpacVersion)' == ''">v1</ProdDacpacVersion>
v1 is the unique name for the version folder - you just need something to identify the dacpac you want.
I put the property just after TargetDatabaseSet and IncludeCompositeObjects.
If you then find the reference to the dacpac and instead of
<ArtifactReference Include="..\..\..\..\..\Desktop\prod\v1\Database2.dacpac">
<HintPath>..\..\..\..\..\Desktop\prod\v1\Database2.dacpac</HintPath>
<SuppressMissingDependenciesErrors>False</SuppressMissingDependenciesErrors>
</ArtifactReference>
Use the property from above:
<ArtifactReference Include="..\..\..\..\..\Desktop\prod\$(ProdDacpacVersion)\Database2.dacpac">
<HintPath>..\..\..\..\..\Desktop\prod\$(ProdDacpacVersion)\Database2.dacpac</HintPath>
<SuppressMissingDependenciesErrors>False</SuppressMissingDependenciesErrors>
</ArtifactReference>
Then the reference will use the property to get the path of the dacpac. There are a few ways you can set the property, you could edit the .sqlproj file when you want to take a new version of read the property from a file or environment variable or something (i'll leave the msbuild fun to you!).
I would, as a standard, everytime the reference was changed either reload the project or restart visual studio - it won't take long and it will save lots of cursing :)
When you deploy the dacpac's, the deploy looks in the same folder for references first so just make sure you copy the right one into the bin folder when you deploy.

Related

Unable to compile SSDT Database Project with a view that has fully qualified name of table in view definition

We have a SQL 2019 database where all table names are fully qualified in views starting with the database name. We do NOT have the option of avoiding the fully qualified reference as the view definition is auto-generated (otherwise I would simply not fully qualify them). When views are defined by referencing tables within the same database as the view, the SSDT project complains that it has an unresolved reference.
Visual Studio does not allow adding a database reference to itself. The only way I can get it to compile is to create a DACPAC of the same database and then add that as a reference along with removing the database variable ($Name).
Is there any other method of providing fully qualified table names in views without having to create a DACPAC in SSDT project?
Only way I'm aware of would be to take the view code out of the project and handle in post-deploy scripts. This is done by design, because the database name may not be what was defined in the original code.
You can't use 3-4 part naming in SSDT normally. You can workaround this by using variables in the code. So let's say, that you have [localhost].[reports].[dbo].[your_table] you'll need to use [$(ReportServer)].[$(ReportDatabase)].[dbo].[your_table].
I have a DacPac project containing objects which use three part naming to refer to the containing database (hundreds of instances such as [thisDb].[dbo].[obj]* exist). I need compare and update this database, but the db project fails to build due to 200+ sql71561 errors.
I did not want to remove the unnecessary database name part or switch to using a database name variable. To successfully build (or compare, and then update) a database using three part naming or fully qualified naming to refer to itself, there is a way I found to pacify visual studio. It's not what I'd prefer, but it works.
Create a copy of the original db project.
In the copy db project, update all local database object references to use just two part names ([dbo].[obj]) instead of three part names (I used find & replace).
Make sure the copy db project targets the same SQL server version and builds successfully.
Reference the copy db project from the original db project (whether via database variable, database name only, or dacpac).
The original db project can now build because its references can be resolved. You'll end up with a dacpac for both the original and the copy, but at least the errors are gone and it compiles.

What is Newtonsoft.Json.xml? [duplicate]

I have developed a lot of class library projects in VS 2012 to be used in Windows Forms and Web forms applications.
The question is simple. Do I need to deploy the DLL file itself together with the XML file that is created?
For example, the class library project is called DataWare. Upon building, I got 5 files in Release folder (this project reference Entity Framework):
DataWare.dll
DataWare.pdb
DataWare.dll.config
EntityFramework.dll
EntityFramework.xml
I know that ".pdb" file contains debugging information, so there is no need to deploy. The ".config" file is not taken into account. Instead the App.config or Web.config are.
Regarding this, I think I have to deploy just DataWare.dll and EntityFramework.dll.
However, the main doubt is if I need to deploy EntityFramework.xml as well.
Regards
Jaime
The XML file contains the doc comments for the public types & members in the assembly.
You only need it if you want Visual Studio to show documentation in IntelliSense.
If you're deploying a consumer-facing app (as opposed to a developer-facing reusable library), you do not need it.
No, in most cases you do not need it. If there is an external DLL that needs to be copied local and referenced using the config, then you might need to, but that is somewhat rare.

Cannot load source/destination schema; Either the file/type does not exist, or if a project dependency exists, the dependent project is not built

We are updating a BizTalk 2009 application that I inherited. I'm converting them into BizTalk 2013 R2.
I get the following reasonably famous error, when I try to re-compile
Exception Caught: Cannot load source/destination schema: MyCompany.Schema.AppConfig.
Either the file/type does not exist, or if a project dependency exists, the dependent project is not built.
There are only two posts in SOF related to this error:
Biztalk Map Destination Schema Imports Multiple Schemas
Reference trouble with BizTalk schema project in Visual Studio 2008
and only a few meaningful posts in elsewhere.
The solution has 4 projects organized as follows:
Common (contains an 1 schema AppConfig.xsd file)
Orchestration (1 Orchestration file)
Schema (references an ASMX web service)
Map (1 map file, references Schema and Common Projects)
The Map project attempts to translate an source message of type AppConfig to the type AppConfigBE which is one of the Complex Types in the Web Service.
I keep getting the compile time error above.
Tried all of the following, as recommended in the two SOF posts, and a few other posts on MSDN forums, but none of it worked.
Tried alternating Copy Local on the Maps project (From true to false, and vice-versa)
Tried Replacing schema on source and destination on the map file
Schemas are referenced using fully qualified .Net type name
Tried referencing the .dll as opposed to the Schema and Common projects.
Updated the web reference; also removed and re-added the web references
Is there a solution/hot fix etc for this? Any other suggestions I can try?
UPDATE 1:
We had to call Microsoft for help; the engineer took my project file to try on their computers; he said they too had the same problem and as a fix, recommended to set the Build Action property of the .BTM map file to None instead of BTSCompile. After this, the project builds successfully. He said to test the project with this build and let them know. What I'm not sure is, what are consequences of this? Many topics on Build Action refers to the schema files, not the map files in a BTS project. What is the standard Build Action for Map files?
One more item is to clear any Assemblies from the GAC or re-GAC them with a Post-Build script.
I ran into the same problem. I needed to add
using Microsoft.XLANGs.BaseTypes;
using Microsoft.BizTalk.XLANGs.BTXEngine;
[assembly: Microsoft.XLANGs.BaseTypes.BizTalkAssemblyAttribute(typeof(BTXService))]
to the AssemblyInfo.cs into the project.

Best practice for using entity framework for post deployment database changes

I am working on a ASP.NET Web Forms project which is expected to experience lots of database changes even after deployment.
Our preference was to use Entity Framework 5, and the Database First design paradigm. However, since we have to make lots of changes to the database even after deployment, if I use database first approach, then every time I update my database, I will have to delete my entire model and regenerate it. Is there any best practices to make this process less painful?
You should use Code First, so that you can use Migrations.
More specifically I'd use manual Migrations.
With manual Migrations you can create Migrations at any point in time. A migration has the following information:
a snapshot of the current model
a set of "instructions" to upgrade from the previous migration
a set of "instructions" to downgrade to the previous migration
Apart from the necessary Migrations, you should add a new Migration when you deploy your app. For example, you can create a migration called "Version 1.0", when you deploy the version 1.0 of your app.
When you finish each new stable version, you simply add a new migration, for it, like "Version 1.1" or "Version 1.2".
The interesting part of migrations shows up when you have a deployed application version and you need to upgrade (or downgrade) to a new version.
There are commands that let you upgrade (or downgrade) a DB from one particular version
to another particular version. You can do it directly specifying a connection to the DB, or create a SQL script which will apply the changes to the DB. For example, if you deployed the version 1.0 in a customer server, and you need to upgrade the software to version 1.2, you can do this:
Update-Database -SourceMigration "Version 1.0" -TargetMigration "Version 1.2"
-Script
This will create a SQL script which can be run on the DB to upgrade from version 1.0 to 1.2.
If you need help about any of the Migrations commands, simply type:
get-help Update-Database -full
(Update-Database is a command name, you can specify any other like Add-Migration)
It's possible that you need to specify the project where the model is in, the connection string name, the name of the project with the .config file or some other things, depending on the specified parameters, and the structure of the projects in your solution.
To get more info on migrations, read MSDN EF Code First Migration.
NOTE ADDED IN EDITION: there is a new DB initializer that can automatically migrate to the latest version when the application runs. I've worked in a real application, and it works like a charm.
ALTERNATIVE SSDT
If you don't want to follow the advice, you can use SQL Server Data Tools (which can be installed inside VS, or work as an independente application, depending on the version you're using).
The idea of this tool is that you can compare projects (which are DB schema snapshots) to existing DBs, and generate the scripts to change the DB to match the schema in the project. (In fact you can compare any combination ofr project and DB)
If you keep versions of your project in a CVS you can even check the changes from one verison of the project to other version of the project.
NOTE ADDED IN EDITION: a SSDT project is a set of scripts that can build the whole DB, including all the objects in its schema. You can create it from an existing DB or viceversa. Then you can keep comparing any combination of DBs and SSDT projects, as soruce or target, and create an apply the scripts neccesary to change each particular object which has changes. (The scripts are created to change the target so that it looks like the source, but you can swap source and target easyly)
This is an alternative solution, but Migrations are much more powerful because you can customize them, for example to fill a "master table" when creating it, to set the initial value of a new column, and so on. If you use SSTD you'll have to do all of that by hand, and carefully keep track of it. So I highly recommend using Migrations.

Database using Sqlite in C# windows phone 8

I have doubt regarding windows phone 8 application development. The database using sqlite for windows phone 8 is pre-loaded into the application or it should be created dynamically at the time of installation in windows phone..? and if it is pre-loaded then how to create the database.db file..?? and also if it is dynamically created, what is the procedure to create dynamically...??
I would say, pre-loaded into the application is the very common way.
Take a look at this article, I think the steps to accomplish your task are quite the same: http://wp.qmatteoq.com/import-an-already-existing-sqlite-database-in-a-windows-8-application/
The first step is to copy your database in to the Visual Studio project and, from the Properties window, set the Build action to Content.
Once you’ve done this operation, you’ll be able to access to the files embedded in your project thanks to the Package.Current.InstalledLocation object that is available in the Windows.ApplicationModel namespace.
The InstalledLocation’s type is StorageFolder, which is the base class of all the folders mapping in WinRT: for this reason, it exposes all the standard methods to interact with the storage, like getting a file or a folder. This way we can use the GetFileAsync method to get a reference to the database embedded into the project and, after that, using the CopyAsync method we can copy it into the local storage of the application. We can copy it in the root of the local storage (like in the following example) or in a specific folder, by getting a reference to it first using the GetFolderAsync method.
For those who are not able to work with sqlite I would like to suggest them to follow this link : http://dotnetslackers.com/articles/silverlight/Windows-Phone-7-Native-Database-Programming-via-Sqlite-Client-for-Windows-Phone.aspx and when you are dumping the data into the project .. you just need to change the properties of the "database1.sqlite" i.e. Build Action = resource . Thats all you need to do ..

Resources