<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Drew Skwiers-Koballa</title>
    <description>The latest articles on Forem by Drew Skwiers-Koballa (@drewsk).</description>
    <link>https://forem.com/drewsk</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F359135%2F6dd136bc-676e-4444-91ba-3c3df35d9be0.JPG</url>
      <title>Forem: Drew Skwiers-Koballa</title>
      <link>https://forem.com/drewsk</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/drewsk"/>
    <language>en</language>
    <item>
      <title>Code analysis with SQL projects</title>
      <dc:creator>Drew Skwiers-Koballa</dc:creator>
      <pubDate>Wed, 22 Jan 2025 00:09:08 +0000</pubDate>
      <link>https://forem.com/drewsk/code-analysis-with-sql-projects-4cjm</link>
      <guid>https://forem.com/drewsk/code-analysis-with-sql-projects-4cjm</guid>
      <description>&lt;p&gt;SQL projects are a development capability for SQL Server and Azure SQL where your database objects are stored as code with integrations for CI/CD capabilities like code quality checks and dynamically calculated deployments. This article walks/runs through the fundamentals of code analysis with SQL projects and how it is useful both for local development and as a CI check. &lt;/p&gt;

&lt;h2&gt;
  
  
  ⏸️ Before you get started
&lt;/h2&gt;

&lt;p&gt;In a previous article, &lt;a href="https://dev.to/drewsk/sql-database-projects-intro-52hg"&gt;"SQL database projects intro"&lt;/a&gt;, we created a SQL project with 2 tables and a stored procedure.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;dbo.Product (table)&lt;/li&gt;
&lt;li&gt;dbo.ProductOrder (table)&lt;/li&gt;
&lt;li&gt;dbo.GetProductInfo (stored procedure)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;SQL database projects are built on top of the .NET SDK - you don't need to know .NET development to use them - but you do need the &lt;a href="https://dotnet.microsoft.com/download" rel="noopener noreferrer"&gt;.NET 8 or higher SDK&lt;/a&gt; installed.&lt;/p&gt;

&lt;p&gt;Want to quickly check if you have the .NET SDK installed?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet &lt;span class="nt"&gt;--list-sdks&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ▶️ With the .NET SDK installed and a sample project created like the one from the intro article, you're ready to go.
&lt;/h3&gt;

&lt;h2&gt;
  
  
  📝 Create a new view
&lt;/h2&gt;

&lt;p&gt;Add a new view &lt;code&gt;[dbo].[All Products]&lt;/code&gt; in a &lt;em&gt;.sql&lt;/em&gt; file (&lt;code&gt;dbo.AllProducts.sql&lt;/code&gt;) in a new folder &lt;code&gt;Views&lt;/code&gt; under project folder.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;VIEW&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="k"&gt;All&lt;/span&gt; &lt;span class="n"&gt;Products&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt;
&lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Build the SQL project, verifying the object references and our SQL syntax is correct.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🛠️ Check our code quality
&lt;/h2&gt;

&lt;p&gt;While &lt;code&gt;SELECT *&lt;/code&gt; seems like a nice shortcut to reference all potential columns, it comes with risks of schema drift, inadvertently clogging up I/O with extra data, and more. In general - your code is more fragile in ways that aren't easily observed.&lt;/p&gt;

&lt;p&gt;This is where SQL code analysis comes in handy, because it will check the database model created from our SQL project for detectable issues. We can run code analysis on our SQL project as a 1-off analysis with an extra property on the project build &lt;code&gt;/p:RunSqlCodeAnalysis=true&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet build /p:RunSqlCodeAnalysis&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now instead of the build succeeding with no warnings, we have two warnings:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;warning SR0011: Microsoft.Rules.Data : Object name(All Products) contains special characters.&lt;/li&gt;
&lt;li&gt;warning SR0001 Microsoft.Rules.Data : The shape of the result set produced by a SELECT * statement will change if the underlying table or view structure changes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Getting ongoing analysis of our SQL code quality provides a quick feedback loop even before we send the code into a git repository. We can enable code analysis to run by default on every project build by incorporating that property into the project file itself with &lt;code&gt;&amp;lt;RunSqlCodeAnalysis&amp;gt;&lt;/code&gt;. A sample project file with the code analysis setting added would look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;Project&lt;/span&gt; &lt;span class="na"&gt;DefaultTargets=&lt;/span&gt;&lt;span class="s"&gt;"Build"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;Sdk&lt;/span&gt; &lt;span class="na"&gt;Name=&lt;/span&gt;&lt;span class="s"&gt;"Microsoft.Build.Sql"&lt;/span&gt; &lt;span class="na"&gt;Version=&lt;/span&gt;&lt;span class="s"&gt;"1.0.0-rc1"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;Name&amp;gt;&lt;/span&gt;ProductsTutorial&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;/Name
&lt;span class="nt"&gt;&amp;lt;DSP&amp;gt;&lt;/span&gt;Microsoft.Data.Tools.Schema.Sql.Sql160DatabaseSchemaProvider&lt;span class="nt"&gt;&amp;lt;/DSP&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;ModelCollation&amp;gt;&lt;/span&gt;1033, CI&lt;span class="nt"&gt;&amp;lt;/ModelCollation&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;RunSqlCodeAnalysis&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/RunSqlCodeAnalysis&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/Project&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🚧 Choose errors and warnings
&lt;/h2&gt;

&lt;p&gt;Some code issues are worse than others - they might have a high impact or be difficult to change in the future. For these kinds of issues we can elevate the warning to an error that will cause our build to fail.&lt;/p&gt;

&lt;p&gt;In our current project we're getting a warning that the object name &lt;code&gt;[dbo].[All Products]&lt;/code&gt; contains a special character (the space). Before I fix this issue I want to make sure that these kinds of mistakes don't get ignored in the future.&lt;/p&gt;

&lt;p&gt;The project property &lt;code&gt;&amp;lt;SqlCodeAnalysisRules&amp;gt;&lt;/code&gt; can be used to exclude a rule completely or elevate a rule from a warning to an error. When choosing errors and warnings, the project property is a semicolon separated list with three settings available for each rule:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;elevate a rule from warning to error with &lt;code&gt;+!&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;no entry for the rule results in the rule throwing a warning&lt;/li&gt;
&lt;li&gt;demote a rule to no warning with &lt;code&gt;-&lt;/code&gt; (disable)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The setting per rule is prefixed to the rule name. Let's turn the object name warning into an error message since names can be more difficult to change down the road. Right below the property &lt;code&gt;&amp;lt;RunSqlCodeAnalysis&amp;gt;&lt;/code&gt; in our project file we add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;SqlCodeAnalysisRules&amp;gt;&lt;/span&gt;+!Microsoft.Rules.Data.SR0011;&lt;span class="nt"&gt;&amp;lt;/SqlCodeAnalysisRules&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we build our project again using &lt;code&gt;dotnet build&lt;/code&gt; we recieve one error and one warning:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;error SR0011: Microsoft.Rules.Data : Object name(All Products) contains special characters.&lt;/li&gt;
&lt;li&gt;warning SR0001 Microsoft.Rules.Data : The shape of the result set produced by a SELECT * statement will change if the underlying table or view structure changes.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;⚠️ Note that when the build fails, the build artifact (&lt;code&gt;.dacpac&lt;/code&gt; file) isn't updated. You need a successful build for your database model to be ready for deployment.&lt;/p&gt;

&lt;h3&gt;
  
  
  ✏️ Fix the view name
&lt;/h3&gt;

&lt;p&gt;Using the information in the error message, including the filename and line number, we'll fix the build error resulting from our modification to the code analysis warnings and errors. We should edit the view definition in &lt;code&gt;dbo.AllProducts.sql&lt;/code&gt; to have a name without spaces, like &lt;code&gt;[dbo].[AllProducts]&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Once the view name is fixed, verify that your project now builds with a single warning message for SR0001 (&lt;code&gt;SELECT *&lt;/code&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  📍 Supress a specific code analysis finding
&lt;/h3&gt;

&lt;p&gt;Code analysis rules provide a structure for evaluating your code, but at the end of the day its your project and you may have a reason for contradicting best practices. Instead of completely disabling a rule with the &lt;code&gt;&amp;lt;SqlCodeAnalysisRules&amp;gt;&lt;/code&gt; project property, we can use the &lt;code&gt;StaticCodeAnalysis.SuppressMessages.xml&lt;/code&gt; file to suppress a specific rule for a specific file.&lt;/p&gt;

&lt;p&gt;Create a new file next to the SQL project file named &lt;code&gt;StaticCodeAnalysis.SuppressMessages.xml&lt;/code&gt;. In this file we add an entry for the view file and the &lt;code&gt;SELECT *&lt;/code&gt; rule.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8" ?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;StaticCodeAnalysis&lt;/span&gt; &lt;span class="na"&gt;version=&lt;/span&gt;&lt;span class="s"&gt;"2"&lt;/span&gt; &lt;span class="na"&gt;xmlns=&lt;/span&gt;&lt;span class="s"&gt;"urn:Microsoft.Data.Tools.Schema.StaticCodeAnalysis"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;SuppressedFile&lt;/span&gt; &lt;span class="na"&gt;FilePath=&lt;/span&gt;&lt;span class="s"&gt;"Views/dbo.AllProducts.sql"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;SuppressedRule&lt;/span&gt; &lt;span class="na"&gt;Category=&lt;/span&gt;&lt;span class="s"&gt;"Microsoft.Rules.Data"&lt;/span&gt; &lt;span class="na"&gt;RuleId=&lt;/span&gt;&lt;span class="s"&gt;"SR0001"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/SuppressedFile&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/StaticCodeAnalysis&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we use &lt;code&gt;SELECT *&lt;/code&gt; in other files of our project the warning will appear for those instances, but we've specified that &lt;code&gt;SELECT *&lt;/code&gt; is allowed in our view &lt;code&gt;dbo.AllProducts&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Running &lt;code&gt;dotnet build&lt;/code&gt; with this message suppression XML file in the project will result in no warnings being shown for our project now.&lt;/p&gt;

&lt;h2&gt;
  
  
  🧩 (optional) Incorporate additional code analysis rules
&lt;/h2&gt;

&lt;p&gt;The small set of code analysis rules included with SQL projects are helpful, but there are quite a few community projects &lt;a href="https://learn.microsoft.com/sql/tools/sql-database-projects/concepts/code-analysis-extensibility" rel="noopener noreferrer"&gt;extending&lt;/a&gt; the code analysis rules. Incorporating these custom code analysis rulesets into your SQL project code analysis is quickly accomplished through package references.&lt;/p&gt;

&lt;p&gt;A package reference is an entry in the SQL project file to a NuGet feed, like the community &lt;strong&gt;TSQLSmells&lt;/strong&gt; on NuGet.org - &lt;a href="https://www.nuget.org/packages/ErikEJ.DacFX.TSQLSmellSCA" rel="noopener noreferrer"&gt;https://www.nuget.org/packages/ErikEJ.DacFX.TSQLSmellSCA&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;We don't even need to manualy edit the &lt;code&gt;.sqlproj&lt;/code&gt; because the .NET tooling has a terminal command to add packages:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet add package ErikEJ.DacFX.TSQLSmellSCA &lt;span class="nt"&gt;--version&lt;/span&gt; 1.1.2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we run &lt;code&gt;dotnet build&lt;/code&gt; again, the build succeeds but we now have two new warnings!&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;warning SML005: Smells : Avoid use of 'Select *'&lt;/li&gt;
&lt;li&gt;warning SML030: Smells : Include SET NOCOUNT ON inside stored procedures&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;While adding the custom rules to your SQL project takes just a few moments, the developers that work on the rulesets have invested countless hours of their time and share with the community. Remember to contribute to the projects that benefit your work as you are able.&lt;/p&gt;

&lt;h2&gt;
  
  
  🚀 (optional) Add a GitHub continuous integration (CI) pipeline
&lt;/h2&gt;

&lt;p&gt;If we've pushed our project to a GitHub repository, we can utilize GitHub Actions to check our project for code analysis findings. This is a great way to automate watching for code smells in databases.&lt;/p&gt;

&lt;p&gt;The pipeline definitions are stored in a &lt;code&gt;.github/workflows&lt;/code&gt; folder. Create a new file &lt;code&gt;code-analysis.yml&lt;/code&gt; in the &lt;code&gt;.github/workflows&lt;/code&gt; folder.  An example pipeline definition is shown below to get you started, but your branching strategy and code review process may vary.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/code-analysis.yml&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run code analysis on SQL project&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;pull_request&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;branches&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;main&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build-with-analysis&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;

    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v4&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Setup .NET&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-dotnet@v4&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;dotnet-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;8.0.x&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build with code analysis&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;dotnet build -warnaserror ProductsTutorial.sqlproj /p:RunSqlCodeAnalysis=true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this workflow we've added &lt;em&gt;yet another&lt;/em&gt; flag to &lt;code&gt;dotnet build&lt;/code&gt; so that all code analysis warnings are elevated to errors. This is useful when you are using code analysis as an optional check. If you're using code analysis as a required check (highly suggested) selecting specific rules to throw errors instead via the &lt;code&gt;SqlCodeAnalysisRules&lt;/code&gt; project property is a better approach.&lt;/p&gt;

&lt;p&gt;Guess what!? Your code analysis CI check is also doing the basic model validation for the database - ensuring you're not referencing objects that don't exist and the SQL syntax is valid. That's a win-win.&lt;/p&gt;

&lt;h2&gt;
  
  
  📚 Learn more
&lt;/h2&gt;

&lt;p&gt;The tooling ecosystem around SQL projects includes VS Code, Visual Studio, and the SqlPackage CLI. Here are some additional resources to learn more about SQL projects for development and deployment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aka.ms/sqlprojects" rel="noopener noreferrer"&gt;Microsoft.Build.Sql projects documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aka.ms/sqlprojects-samples" rel="noopener noreferrer"&gt;SQL projects CI/CD sample repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aka.ms/sqlpackage-ref" rel="noopener noreferrer"&gt;SqlPackage for command line deployments&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  DEV.TO posts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/drewsk/sql-database-projects-intro-52hg"&gt;SQL database projects intro&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>sql</category>
      <category>database</category>
      <category>codequality</category>
    </item>
    <item>
      <title>SQL database projects intro</title>
      <dc:creator>Drew Skwiers-Koballa</dc:creator>
      <pubDate>Fri, 13 Dec 2024 22:42:21 +0000</pubDate>
      <link>https://forem.com/drewsk/sql-database-projects-intro-52hg</link>
      <guid>https://forem.com/drewsk/sql-database-projects-intro-52hg</guid>
      <description>&lt;p&gt;SQL projects are a development capability for SQL Server and Azure SQL where your database objects are stored as code with integrations for CI/CD capabilities like code quality checks and dynamically calculated deployments. This article walks/runs through creating a new SQL project and deploying it to a database from the command line and any text editor. The tooling ecosystem around SQL projects includes VS Code, Visual Studio, and the SqlPackage CLI. Learn more about all of this at the &lt;a href="https://aka.ms/sqlprojects" rel="noopener noreferrer"&gt;Microsoft.Build.Sql projects documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  ⏸️ Before you get started
&lt;/h2&gt;

&lt;p&gt;SQL database projects are built on top of the .NET SDK - you don't need to know .NET development to use them - but you do need the &lt;a href="https://dotnet.microsoft.com/download" rel="noopener noreferrer"&gt;.NET 8 or higher SDK&lt;/a&gt; installed.&lt;/p&gt;

&lt;p&gt;Want to quickly check if you have the .NET SDK installed?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet &lt;span class="nt"&gt;--list-sdks&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The SqlPackage CLI is an indespensible part of database deployments because it will automatically calculate the actual scripts necessary to modify a new or existing database to match the contents of your SQL project. SqlPackage is available for Windows, macOS, and Linux all as a .NET tool, so you can install it quickly in a single command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet tool &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-g&lt;/span&gt; microsoft.sqlpackage
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  ▶️ With the .NET SDK and the SqlPackage CLI both installed, you're ready to go.
&lt;/h3&gt;

&lt;h2&gt;
  
  
  📁 Create a SQL project
&lt;/h2&gt;

&lt;p&gt;We'll use the &lt;a href="https://www.nuget.org/packages/Microsoft.build.sql.templates" rel="noopener noreferrer"&gt;Microsoft.Build.Sql.Templates NuGet package&lt;/a&gt; to get started with a new SQL project.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new &lt;span class="nb"&gt;install &lt;/span&gt;Microsoft.Build.Sql.Templates
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a new SQL project using the &lt;code&gt;sqlproj&lt;/code&gt; template:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new sqlproj &lt;span class="nt"&gt;-n&lt;/span&gt; ProductsTutorial
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📝 Add a database object
&lt;/h2&gt;

&lt;p&gt;Add a new table &lt;code&gt;dbo.Product&lt;/code&gt; in a &lt;em&gt;.sql&lt;/em&gt; file (&lt;code&gt;dbo.Product.sql&lt;/code&gt;) alongside the project file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ProductID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;IDENTITY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ProductName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;nvarchar&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🛠️ Build the project
&lt;/h2&gt;

&lt;p&gt;The SQL project (&lt;code&gt;.sqlproj&lt;/code&gt;) is the source code for our database definition, and we would use a build artifact to deploy to a database instance (such as a local container or a SQL Server). &lt;br&gt;
Build the project to create a .dacpac file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  ✚ Add more database objects
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Add a stored procedure
&lt;/h3&gt;

&lt;p&gt;We're going to add a stored procedure to the project. Create a new file &lt;code&gt;dbo.GetProductInfo.sql&lt;/code&gt; alongside the project file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;PROCEDURE&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;GetProductInfo&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ProductID&lt;/span&gt; &lt;span class="nb"&gt;INT&lt;/span&gt;
&lt;span class="k"&gt;AS&lt;/span&gt;
&lt;span class="k"&gt;BEGIN&lt;/span&gt;
    &lt;span class="k"&gt;SELECT&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductID&lt;/span&gt;
        &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductName&lt;/span&gt;
        &lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;SUM&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;PO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Quantity&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;AS&lt;/span&gt; &lt;span class="n"&gt;TotalQuantity&lt;/span&gt;
    &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;
    &lt;span class="k"&gt;LEFT&lt;/span&gt; &lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductOrder&lt;/span&gt; &lt;span class="n"&gt;PO&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;PO&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductID&lt;/span&gt;
    &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductID&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;@&lt;/span&gt;&lt;span class="n"&gt;ProductID&lt;/span&gt;
    &lt;span class="k"&gt;GROUP&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ProductName&lt;/span&gt;
&lt;span class="k"&gt;END&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;🚧 We've added a stored procedure that references the &lt;code&gt;dbo.Product&lt;/code&gt; table we created earlier in addition to a table we haven't created yet (&lt;code&gt;dbo.ProductOrder&lt;/code&gt;). Running &lt;code&gt;dotnet build&lt;/code&gt; at this point returns build warnings about unresolved references. This is good - we want our development tooling to help us create valid SQL objects.&lt;/p&gt;

&lt;h3&gt;
  
  
  Adding the missing table
&lt;/h3&gt;

&lt;p&gt;Create a new file &lt;code&gt;dbo.ProductOrder.sql&lt;/code&gt; alongside the project file for the missing table &lt;code&gt;dbo.ProductOrder&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;ProductOrder&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ProductOrderID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;IDENTITY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ProductID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;FOREIGN&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt; &lt;span class="k"&gt;REFERENCES&lt;/span&gt; &lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ProductID&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;Quantity&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Organize the project
&lt;/h3&gt;

&lt;p&gt;We've been creating all our files in the same folder with the &lt;code&gt;.sqlproj&lt;/code&gt; file. This works, but it's not the best way to organize a project. A common approach is to group objects by schema and/or object type.&lt;/p&gt;

&lt;p&gt;Create a new folder &lt;code&gt;Tables&lt;/code&gt; and move the &lt;code&gt;dbo.Product.sql&lt;/code&gt; and &lt;code&gt;dbo.ProductOrder.sql&lt;/code&gt; files into it. Create a new folder &lt;code&gt;StoredProcedures&lt;/code&gt; and move the &lt;code&gt;dbo.GetProductInfo.sql&lt;/code&gt; file into it.&lt;/p&gt;

&lt;p&gt;When you run &lt;code&gt;dotnet build&lt;/code&gt; again, the build still succeeds. The build process automatically finds the &lt;code&gt;.sql&lt;/code&gt; files in the project folder and subfolders.&lt;/p&gt;

&lt;h3&gt;
  
  
  💡 Use your existing databases
&lt;/h3&gt;

&lt;p&gt;If you have an existing database, the command line tool SqlPackage can extract object definitions for the whole database.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;sqlpackage /Action:Extract /TargetFile:newfolderforfiles /SourceConnectionString:&lt;span class="s2"&gt;"Data Source=yourservername;Initial Catalog=yourdatabasename;Authentication=Active Directory Interactive"&lt;/span&gt; /p:ExtractTarget&lt;span class="o"&gt;=&lt;/span&gt;SchemaObjectType
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🛳️ Publish a SQL project
&lt;/h2&gt;

&lt;p&gt;Publish a SQL project to a database using the SqlPackage &lt;code&gt;publish&lt;/code&gt; command. Learn more about the &lt;code&gt;publish&lt;/code&gt; command in the &lt;a href="https://learn.microsoft.com/sql/tools/sqlpackage/sqlpackage-publish" rel="noopener noreferrer"&gt;SqlPackage documentation&lt;/a&gt;, where additional examples and details on the parameters are available.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# example publish to Azure SQL Database using SQL authentication and a connection string&lt;/span&gt;
SqlPackage /Action:Publish /SourceFile:&lt;span class="s2"&gt;"bin&lt;/span&gt;&lt;span class="se"&gt;\D&lt;/span&gt;&lt;span class="s2"&gt;ebug&lt;/span&gt;&lt;span class="se"&gt;\P&lt;/span&gt;&lt;span class="s2"&gt;roductsTutorial.dacpac"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    /TargetConnectionString:&lt;span class="s2"&gt;"Server=tcp:{yourserver}.database.windows.net,1433;Initial Catalog=ProductsTutorial;User ID=sqladmin;Password={your_password};Encrypt=True;TrustServerCertificate=False;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the publish command completes, you can connect to the database and view the objects that were created.&lt;/p&gt;

&lt;h3&gt;
  
  
  🧩 (optional) Update the project and publish again
&lt;/h3&gt;

&lt;p&gt;We can update the project by adding a new column to the &lt;code&gt;dbo.Product&lt;/code&gt; table. Open the existing &lt;code&gt;dbo.Product.sql&lt;/code&gt; file and add column for &lt;code&gt;ProductDescription&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The resulting file is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;dbo&lt;/span&gt;&lt;span class="p"&gt;].[&lt;/span&gt;&lt;span class="n"&gt;Product&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ProductID&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="k"&gt;IDENTITY&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ProductName&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;nvarchar&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="mi"&gt;200&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NOT&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;ProductDescription&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;nvarchar&lt;/span&gt;&lt;span class="p"&gt;](&lt;/span&gt;&lt;span class="mi"&gt;800&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;NULL&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we run &lt;code&gt;dotnet build&lt;/code&gt; again, the build succeeds and the &lt;code&gt;ProductsTutorial.dacpac&lt;/code&gt; file is updated.&lt;/p&gt;

&lt;p&gt;🪄 We can publish the updated project to the database using the same &lt;code&gt;publish&lt;/code&gt; command as before.  Running the publish command again will update the existing database schema automatically, there's no need to remove the database first or track the changes manually. &lt;/p&gt;

&lt;h2&gt;
  
  
  (optional) Check the project into source control
&lt;/h2&gt;

&lt;p&gt;One of the benefits of using SQL projects is that the database schema is stored in source control. This makes it easy to collaborate and to deploy changes using CI/CD practices.&lt;/p&gt;

&lt;p&gt;When we build the project, the .dacpac file and other artifacts are created in the &lt;code&gt;bin&lt;/code&gt; and &lt;code&gt;obj&lt;/code&gt; folders. We can keep these folders out of source control by adding them to the &lt;code&gt;.gitignore&lt;/code&gt; file or by using the default &lt;code&gt;.gitignore&lt;/code&gt; for .NET.&lt;/p&gt;

&lt;p&gt;The default &lt;code&gt;.gitignore&lt;/code&gt; for .NET projects can be created by running the following command in the project folder:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;dotnet new gitignore
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once you've committed the project to source control, you can push it to a GitHub/remote repository.  You can do this from your IDE or from the command line using the following commands:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Commit the project to source control&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git init
git add &lt;span class="nb"&gt;.&lt;/span&gt;
git commit &lt;span class="nt"&gt;-m&lt;/span&gt; &lt;span class="s2"&gt;"new project"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Push the project to a GitHub repository&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;git remote add origin https://github.com/&lt;span class="o"&gt;{&lt;/span&gt;yourusername&lt;span class="o"&gt;}&lt;/span&gt;/&lt;span class="o"&gt;{&lt;/span&gt;yourrepository&lt;span class="o"&gt;}&lt;/span&gt;.git
git branch &lt;span class="nt"&gt;-M&lt;/span&gt; main
git push &lt;span class="nt"&gt;-u&lt;/span&gt; origin main
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  🚀 (optional) Add a GitHub build/deploy pipeline
&lt;/h2&gt;

&lt;p&gt;If we've pushed our project to a GitHub repository, we can utilize GitHub Actions to build and deploy our project to a database. This is a great way to automate the deployment of database changes.&lt;/p&gt;

&lt;p&gt;The pipeline definitions are stored in a &lt;code&gt;.github/workflows&lt;/code&gt; folder. Create a new file &lt;code&gt;build-and-deploy.yml&lt;/code&gt; in the &lt;code&gt;.github/workflows&lt;/code&gt; folder.  We'll use &lt;a href="https://github.com/azure/sql-action" rel="noopener noreferrer"&gt;sql-action&lt;/a&gt; to handle building the SQL project and publishing it to a database. It is recommended you check out the &lt;a href="https://github.com/azure/sql-action" rel="noopener noreferrer"&gt;sql-action documentation&lt;/a&gt; for more information on how to use it, but an example pipeline definition is shown below to get you started.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The example pipeline definition below uses a &lt;a href="https://docs.github.com/actions/reference/encrypted-secrets" rel="noopener noreferrer"&gt;GitHub secret&lt;/a&gt; to store the connection string as &lt;code&gt;SQL_CONNECTION_STRING&lt;/code&gt;.&lt;/em&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="c1"&gt;# .github/workflows/build-and-deploy.yml&lt;/span&gt;
&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build and deploy SQL project&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ubuntu-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v3&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;azure/sql-action@v2.3&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;        
        &lt;span class="na"&gt;connection-string&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.SQL_CONNECTION_STRING }}&lt;/span&gt;
        &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;./ProductsTutorial.sqlproj'&lt;/span&gt;
        &lt;span class="na"&gt;action&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;publish'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  📚 Learn more
&lt;/h2&gt;

&lt;p&gt;Wow, you made it to the end!  Here are some additional resources to learn more about SQL projects for development and deployment:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://aka.ms/sqlprojects" rel="noopener noreferrer"&gt;Microsoft.Build.Sql projects documentation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aka.ms/sqlprojects-samples" rel="noopener noreferrer"&gt;SQL projects CI/CD sample repository&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aka.ms/sqlpackage-ref" rel="noopener noreferrer"&gt;SqlPackage for command line deployments&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  DEV.TO posts
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/drewsk/code-analysis-with-sql-projects-4cjm"&gt;Code analysis with SQL projects&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>sql</category>
      <category>database</category>
      <category>development</category>
    </item>
    <item>
      <title>Connecting to SQL Server on macOS from a Windows VM</title>
      <dc:creator>Drew Skwiers-Koballa</dc:creator>
      <pubDate>Mon, 15 Jan 2024 20:00:00 +0000</pubDate>
      <link>https://forem.com/drewsk/connecting-to-sql-server-on-macos-from-a-windows-vm-16hf</link>
      <guid>https://forem.com/drewsk/connecting-to-sql-server-on-macos-from-a-windows-vm-16hf</guid>
      <description>&lt;p&gt;There are a few instances where you want to run SQL Server on macOS and interact with it from a windows VM. As someone that works within the world of SQL Server/Azure SQL, the use of SQL Server Management Studio (SSMS) comes to mind immediately - for the tasks you can't complete in Azure Data Studio on macOS directly. Another adjacent (and generally unfortunate scenario) is when work with .NET Framework is required, and for that, you &lt;em&gt;need&lt;/em&gt; Windows. This article will step through the network information needed to connect from a Windows VM on macOS to a SQL Server container.&lt;/p&gt;

&lt;h2&gt;
  
  
  A few basics
&lt;/h2&gt;

&lt;p&gt;There are a few instances where you want to run SQL Server on macOS and interact with it from a windows VM. As someone that works within the world of SQL Server/Azure SQL, the use of SQL Server Management Studio (SSMS) comes to mind immediately - for the tasks you can't complete in Azure Data Studio on macOS directly. Another adjacent (and generally unfortunate scenario) is when work with .NET Framework is required, and for that, you &lt;em&gt;need&lt;/em&gt; Windows. This article will step through the network information needed to connect from a Windows VM on macOS to a SQL Server container.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsjp91obq5w5h1lt1yamo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsjp91obq5w5h1lt1yamo.png" width="800" height="356"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  VM networking
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://kb.parallels.com/4948" rel="noopener noreferrer"&gt;Shared networking&lt;/a&gt; is the recommended (and default) network setting in Parallels. In this network layout, your macOS machine is automatically sharing its network connection with the VM and this is usually sufficient for VM use. The other insight we need to connect between macOS and the Windows VM is knowledge of the &lt;em&gt;virtual subnet&lt;/em&gt; (network) between the macOS host and the VM.&lt;/p&gt;

&lt;p&gt;The fastest way I've found to get my network info for the VM is within the VM itself, using &lt;code&gt;ipconfig&lt;/code&gt; from Windows terminal. From its output, I note the VM's IP address and its gateway address. On my machine, the VM has the address &lt;strong&gt;10.211.55.3&lt;/strong&gt; and the gateway is &lt;strong&gt;10.211.55.1&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fau6zwd01nopuhkki6tse.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fau6zwd01nopuhkki6tse.png" width="660" height="558"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Conceptually, our macOS machine is playing 2 roles in the VM network - both the gateway and as a participant in the network. The SQL Server container running on our macOS host is available to the Windows VM at the IP address assigned to our host as a participant in the network.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbls7e8yndk29o6mwby0e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbls7e8yndk29o6mwby0e.png" width="800" height="400"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Since the gateway address is x.x.x.1 and the VM is assigned x.x.x.3, I'm going to make an educated guess that my host machine is available at x.x.x.2. All that IP address information I gathered by running &lt;code&gt;ipconfig&lt;/code&gt; from the Windows VM.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test the connection
&lt;/h2&gt;

&lt;p&gt;Using any SQL client application on the Windows VM will allow me to test the connectivity to the SQL container. This moment is a good one to fire up &lt;a href="https://aka.ms/ssms" rel="noopener noreferrer"&gt;SSMS&lt;/a&gt; in the VM. I'll use the address &lt;strong&gt;10.211.55.2&lt;/strong&gt; as my SQL server address.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg7ojdt4v2dywqjgmkqej.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fg7ojdt4v2dywqjgmkqej.png" width="496" height="328"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa15tm04lsk0yvo4be98s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa15tm04lsk0yvo4be98s.png" width="404" height="388"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you encounter difficulties gaining connectivity, you may need to adjust firewall settings in macOS. If your firewall is enabled, use the &lt;strong&gt;Options&lt;/strong&gt; button to allow specific connections.&lt;/p&gt;

&lt;h2&gt;
  
  
  Recap
&lt;/h2&gt;

&lt;p&gt;While there's a lot of the development process that you can accomplish from just about any machine, there are still some specific instances where you need that Windows VM. With the default shared network setting, your macOS host has an address assigned to it that you can determine and use to connect from the Windows VM to a container running on macOS. In the setup on my machine, the Windows VM was assigned &lt;strong&gt;10.211.55.3&lt;/strong&gt; and the macOS host (and SQL Server container) was available at &lt;strong&gt;10.211.55.2&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>macos</category>
      <category>sqlserver</category>
      <category>parallels</category>
    </item>
  </channel>
</rss>
