From 80734c17baade6bd0d611ed3808e4d383ca6fa97 Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Tue, 2 Jun 2026 16:45:46 -0300
Subject: [PATCH 1/3] Use upper-bound version ranges for sibling package
dependencies
Compute [floor, ceiling) ranges for sibling packages so NuGet cannot
resolve an incompatible newer minor/major version at restore time.
- Directory.Packages.props: derive *VersionCeiling from *PackageVersion;
apply ranges to sibling PackageVersion items; add SniVersionRange
- SqlClient csproj: compute version range properties for nuspec expansion
- SqlClient nuspec: replace bare version tokens with range tokens
---
Directory.Packages.props | 41 +++++++++++++++----
.../src/Microsoft.Data.SqlClient.csproj | 10 ++++-
.../src/Microsoft.Data.SqlClient.nuspec | 30 +++++++-------
3 files changed, 56 insertions(+), 25 deletions(-)
diff --git a/Directory.Packages.props b/Directory.Packages.props
index a74caf225a..5aece05a0a 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -40,6 +40,31 @@
false
+
+
+
+ 6.0.2
+ [$(SniVersion), $(SniVersion.Split('.')[0]).$([MSBuild]::Add($(SniVersion.Split('.')[1]), 1)).0)
+
+
+
+ $(SqlServerPackageVersion.Split('.')[0]).$([MSBuild]::Add($(SqlServerPackageVersion.Split('.')[1]), 1)).0
+ $(LoggingPackageVersion.Split('.')[0]).$([MSBuild]::Add($(LoggingPackageVersion.Split('.')[1]), 1)).0
+ $(AbstractionsPackageVersion.Split('.')[0]).$([MSBuild]::Add($(AbstractionsPackageVersion.Split('.')[1]), 1)).0
+ $(SqlClientPackageVersion.Split('.')[0]).$([MSBuild]::Add($(SqlClientPackageVersion.Split('.')[1]), 1)).0
+ $(AzurePackageVersion.Split('.')[0]).$([MSBuild]::Add($(AzurePackageVersion.Split('.')[1]), 1)).0
+ $(AkvProviderPackageVersion.Split('.')[0]).$([MSBuild]::Add($(AkvProviderPackageVersion.Split('.')[1]), 1)).0
+
+
@@ -47,22 +72,22 @@
+ Version="[$(SqlServerPackageVersion), $(SqlServerVersionCeiling))" />
+ Version="[$(LoggingPackageVersion), $(LoggingVersionCeiling))" />
+ Version="[$(AbstractionsPackageVersion), $(AbstractionsVersionCeiling))" />
+ Version="[$(SqlClientPackageVersion), $(SqlClientVersionCeiling))" />
+ Version="[$(AzurePackageVersion), $(AzureVersionCeiling))" />
+ Version="[$(AkvProviderPackageVersion), $(AkvProviderVersionCeiling))" />
@@ -108,8 +133,8 @@
-
-
+
+
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
index e9b3ad2741..108e1b6ab6 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
@@ -207,9 +207,15 @@
-
+
- <_SqlClientPackNuspecExpandedText>$([System.IO.File]::ReadAllText('$(SqlClientPackNuspecTemplatePath)').Replace('$AbstractionsPackageVersion$','$(AbstractionsPackageVersion)').Replace('$LoggingPackageVersion$','$(LoggingPackageVersion)').Replace('$SqlServerPackageVersion$','$(SqlServerPackageVersion)'))
+
+ <_AbstractionsVersionRange>[$(AbstractionsPackageVersion), $(AbstractionsPackageVersion.Split('.')[0]).$([MSBuild]::Add($(AbstractionsPackageVersion.Split('.')[1]), 1)).0)
+ <_LoggingVersionRange>[$(LoggingPackageVersion), $(LoggingPackageVersion.Split('.')[0]).$([MSBuild]::Add($(LoggingPackageVersion.Split('.')[1]), 1)).0)
+ <_SqlServerVersionRange>[$(SqlServerPackageVersion), $(SqlServerPackageVersion.Split('.')[0]).$([MSBuild]::Add($(SqlServerPackageVersion.Split('.')[1]), 1)).0)
+
+
+ <_SqlClientPackNuspecExpandedText>$([System.IO.File]::ReadAllText('$(SqlClientPackNuspecTemplatePath)').Replace('$AbstractionsVersionRange$','$(_AbstractionsVersionRange)').Replace('$LoggingVersionRange$','$(_LoggingVersionRange)').Replace('$SqlServerVersionRange$','$(_SqlServerVersionRange)').Replace('$SniVersionRange$','$(SniVersionRange)'))
-
-
-
+
+
+
@@ -56,38 +56,38 @@
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
+
-
-
-
+
+
+
-
+
From 4794b4cced7e271fb26d64aa8ad7e5c56c7c08d3 Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Wed, 3 Jun 2026 14:36:43 -0300
Subject: [PATCH 2/3] CI: Pass ReferenceType and dependency versions to pack
jobs
The CI/PR pack jobs for Abstractions and Azure extensions were not
passing ReferenceType=Package to dotnet pack, causing the projects to
use ProjectReference mode for sibling dependencies. NuGet converts
ProjectReferences to bare version dependencies (no ranges), which
defeats the upper-bound version ranges defined in Directory.Packages.props.
Fix:
- pack-abstractions-package-ci-job: Add referenceType, loggingArtifactsName,
and loggingPackageVersion parameters. When referenceType=Package, download
Logging artifacts and pass ReferenceType + LoggingPackageVersion to dotnet
pack buildProperties.
- pack-azure-package-ci-job: Add loggingPackageVersion parameter. When
referenceType=Package, pass ReferenceType + dependency versions to dotnet
pack buildProperties.
- Wire the new parameters through build-abstractions-package-ci-stage.yml
and dotnet-sqlclient-ci-core.yml.
---
eng/pipelines/dotnet-sqlclient-ci-core.yml | 3 +
.../jobs/pack-abstractions-package-ci-job.yml | 67 ++++++++++++++++---
.../jobs/pack-azure-package-ci-job.yml | 43 +++++++++---
.../build-abstractions-package-ci-stage.yml | 27 ++++++++
.../stages/build-azure-package-ci-stage.yml | 2 +
5 files changed, 123 insertions(+), 19 deletions(-)
diff --git a/eng/pipelines/dotnet-sqlclient-ci-core.yml b/eng/pipelines/dotnet-sqlclient-ci-core.yml
index f5f2269494..1d766327e8 100644
--- a/eng/pipelines/dotnet-sqlclient-ci-core.yml
+++ b/eng/pipelines/dotnet-sqlclient-ci-core.yml
@@ -164,6 +164,9 @@ stages:
buildConfiguration: ${{ parameters.buildConfiguration }}
debug: ${{ parameters.debug }}
dotnetVerbosity: ${{ parameters.dotnetVerbosity }}
+ loggingArtifactsName: $(loggingArtifactsName)
+ loggingPackageVersion: $(loggingPackageVersion)
+ referenceType: ${{ parameters.referenceType }}
# When building Abstractions via packages, we must depend on the Logging
# package.
${{ if eq(parameters.referenceType, 'Package') }}:
diff --git a/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml b/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml
index aed7672618..b83ec3d062 100644
--- a/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml
+++ b/eng/pipelines/jobs/pack-abstractions-package-ci-job.yml
@@ -53,6 +53,30 @@ parameters:
- detailed
- diagnostic
+ # The name of the Logging pipeline artifacts to download.
+ #
+ # This is used when the referenceType is 'Package'.
+ - name: loggingArtifactsName
+ type: string
+ default: Logging.Artifacts
+
+ # The Logging package version to depend on.
+ #
+ # This is used when the referenceType is 'Package'.
+ - name: loggingPackageVersion
+ type: string
+ default: ''
+
+ # The C# project reference type to use when building and packing the packages.
+ - name: referenceType
+ type: string
+ default: Project
+ values:
+ # Reference sibling packages as NuGet packages.
+ - Package
+ # Reference sibling packages as C# projects.
+ - Project
+
jobs:
- job: pack_abstractions_package_job
@@ -102,21 +126,46 @@ jobs:
- pwsh: 'Get-ChildItem Env: | Sort-Object Name'
displayName: '[Debug] Print Environment Variables'
+ # For Package reference builds, we must first download the dependency
+ # package artifacts.
+ - ${{ if eq(parameters.referenceType, 'Package') }}:
+ - task: DownloadPipelineArtifact@2
+ displayName: Download Logging Package Artifacts
+ inputs:
+ artifactName: ${{ parameters.loggingArtifactsName }}
+ targetPath: $(Build.SourcesDirectory)/packages
+
# Install the .NET SDK.
- template: /eng/pipelines/steps/install-dotnet.yml@self
parameters:
debug: ${{ parameters.debug }}
# Create the NuGet packages.
- - task: DotNetCoreCLI@2
- displayName: Create NuGet Package
- inputs:
- command: pack
- packagesToPack: $(project)
- configurationToPack: ${{ parameters.buildConfiguration }}
- packDirectory: $(dotnetPackagesDir)
- verbosityToPack: ${{ parameters.dotnetVerbosity }}
- buildProperties: AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }};AbstractionsAssemblyFileVersion=${{ parameters.abstractionsAssemblyFileVersion }}
+ #
+ # When referenceType is Package, we must pass ReferenceType and the
+ # dependency version so that Directory.Packages.props applies version
+ # ranges to sibling package dependencies.
+ - ${{ if eq(parameters.referenceType, 'Package') }}:
+ - task: DotNetCoreCLI@2
+ displayName: Create NuGet Package
+ inputs:
+ command: pack
+ packagesToPack: $(project)
+ configurationToPack: ${{ parameters.buildConfiguration }}
+ packDirectory: $(dotnetPackagesDir)
+ verbosityToPack: ${{ parameters.dotnetVerbosity }}
+ buildProperties: AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }};AbstractionsAssemblyFileVersion=${{ parameters.abstractionsAssemblyFileVersion }};ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }}
+
+ - ${{ else }}:
+ - task: DotNetCoreCLI@2
+ displayName: Create NuGet Package
+ inputs:
+ command: pack
+ packagesToPack: $(project)
+ configurationToPack: ${{ parameters.buildConfiguration }}
+ packDirectory: $(dotnetPackagesDir)
+ verbosityToPack: ${{ parameters.dotnetVerbosity }}
+ buildProperties: AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }};AbstractionsAssemblyFileVersion=${{ parameters.abstractionsAssemblyFileVersion }}
# Publish the NuGet packages as a named pipeline artifact.
- task: PublishPipelineArtifact@1
diff --git a/eng/pipelines/jobs/pack-azure-package-ci-job.yml b/eng/pipelines/jobs/pack-azure-package-ci-job.yml
index 3b03dc0adc..8aac9a98cd 100644
--- a/eng/pipelines/jobs/pack-azure-package-ci-job.yml
+++ b/eng/pipelines/jobs/pack-azure-package-ci-job.yml
@@ -26,12 +26,19 @@ parameters:
type: string
default: Logging.Artifacts
- # The Abstractions package verion to depend on.
+ # The Abstractions package version to depend on.
#
# This is used when the referenceType is 'Package'.
- name: abstractionsPackageVersion
type: string
+ # The Logging package version to depend on.
+ #
+ # This is used when the referenceType is 'Package'.
+ - name: loggingPackageVersion
+ type: string
+ default: ''
+
# The name of the pipeline artifacts to publish.
- name: azureArtifactsName
type: string
@@ -151,15 +158,31 @@ jobs:
debug: ${{ parameters.debug }}
# Create the NuGet packages.
- - task: DotNetCoreCLI@2
- displayName: Create NuGet Package
- inputs:
- command: pack
- packagesToPack: $(project)
- configurationToPack: ${{ parameters.buildConfiguration }}
- packDirectory: $(dotnetPackagesDir)
- verbosityToPack: ${{ parameters.dotnetVerbosity }}
- buildProperties: AzurePackageVersion=${{ parameters.azurePackageVersion }};AzureAssemblyFileVersion=${{ parameters.azureAssemblyFileVersion }}
+ #
+ # When referenceType is Package, we must pass ReferenceType and the
+ # dependency versions so that Directory.Packages.props applies version
+ # ranges to sibling package dependencies.
+ - ${{ if eq(parameters.referenceType, 'Package') }}:
+ - task: DotNetCoreCLI@2
+ displayName: Create NuGet Package
+ inputs:
+ command: pack
+ packagesToPack: $(project)
+ configurationToPack: ${{ parameters.buildConfiguration }}
+ packDirectory: $(dotnetPackagesDir)
+ verbosityToPack: ${{ parameters.dotnetVerbosity }}
+ buildProperties: AzurePackageVersion=${{ parameters.azurePackageVersion }};AzureAssemblyFileVersion=${{ parameters.azureAssemblyFileVersion }};ReferenceType=Package;LoggingPackageVersion=${{ parameters.loggingPackageVersion }};AbstractionsPackageVersion=${{ parameters.abstractionsPackageVersion }}
+
+ - ${{ else }}:
+ - task: DotNetCoreCLI@2
+ displayName: Create NuGet Package
+ inputs:
+ command: pack
+ packagesToPack: $(project)
+ configurationToPack: ${{ parameters.buildConfiguration }}
+ packDirectory: $(dotnetPackagesDir)
+ verbosityToPack: ${{ parameters.dotnetVerbosity }}
+ buildProperties: AzurePackageVersion=${{ parameters.azurePackageVersion }};AzureAssemblyFileVersion=${{ parameters.azureAssemblyFileVersion }}
# Publish the NuGet packages as a named pipeline artifact.
- task: PublishPipelineArtifact@1
diff --git a/eng/pipelines/stages/build-abstractions-package-ci-stage.yml b/eng/pipelines/stages/build-abstractions-package-ci-stage.yml
index 6aae1703b8..8579b79caf 100644
--- a/eng/pipelines/stages/build-abstractions-package-ci-stage.yml
+++ b/eng/pipelines/stages/build-abstractions-package-ci-stage.yml
@@ -67,6 +67,30 @@ parameters:
- detailed
- diagnostic
+ # The name of the Logging pipeline artifacts to download.
+ #
+ # This is used when the referenceType is 'Package'.
+ - name: loggingArtifactsName
+ type: string
+ default: Logging.Artifacts
+
+ # The Logging package version to depend on.
+ #
+ # This is used when the referenceType is 'Package'.
+ - name: loggingPackageVersion
+ type: string
+ default: ''
+
+ # The C# project reference type to use when building and packing the packages.
+ - name: referenceType
+ type: string
+ default: Project
+ values:
+ # Reference sibling packages as NuGet packages.
+ - Package
+ # Reference sibling packages as C# projects.
+ - Project
+
stages:
- stage: build_abstractions_package_stage
@@ -141,3 +165,6 @@ stages:
- test_abstractions_package_job_windows
- test_abstractions_package_job_macos
dotnetVerbosity: ${{ parameters.dotnetVerbosity }}
+ loggingArtifactsName: ${{ parameters.loggingArtifactsName }}
+ loggingPackageVersion: ${{ parameters.loggingPackageVersion }}
+ referenceType: ${{ parameters.referenceType }}
diff --git a/eng/pipelines/stages/build-azure-package-ci-stage.yml b/eng/pipelines/stages/build-azure-package-ci-stage.yml
index 1da56a18ef..b3cf9073d5 100644
--- a/eng/pipelines/stages/build-azure-package-ci-stage.yml
+++ b/eng/pipelines/stages/build-azure-package-ci-stage.yml
@@ -331,4 +331,6 @@ stages:
- test_azure_package_job_windows_integration
- test_azure_package_job_macos
dotnetVerbosity: ${{ parameters.dotnetVerbosity }}
+ loggingArtifactsName: ${{ parameters.loggingArtifactsName }}
+ loggingPackageVersion: ${{ parameters.loggingPackageVersion }}
referenceType: ${{ parameters.referenceType }}
From 5060f1a0195bfa9590d04555f18cb6e74efb4729 Mon Sep 17 00:00:00 2001
From: Paul Medynski <31868385+paulmedynski@users.noreply.github.com>
Date: Thu, 4 Jun 2026 12:49:23 -0300
Subject: [PATCH 3/3] Trim version properties before Split('.') in range
computation
Address Copilot review feedback: guard against whitespace in version
values passed via -p: arguments by trimming before splitting.
- Directory.Packages.props: Add .Trim() before .Split('.') on all
*PackageVersion properties used in ceiling computation.
- Microsoft.Data.SqlClient.csproj: Use the already-computed
_*PackageVersionTrimmed properties as inputs to the range strings
instead of the raw *PackageVersion values.
---
Directory.Packages.props | 12 ++++++------
.../src/Microsoft.Data.SqlClient.csproj | 9 +++++----
2 files changed, 11 insertions(+), 10 deletions(-)
diff --git a/Directory.Packages.props b/Directory.Packages.props
index 5aece05a0a..5c25965af8 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -57,12 +57,12 @@
- $(SqlServerPackageVersion.Split('.')[0]).$([MSBuild]::Add($(SqlServerPackageVersion.Split('.')[1]), 1)).0
- $(LoggingPackageVersion.Split('.')[0]).$([MSBuild]::Add($(LoggingPackageVersion.Split('.')[1]), 1)).0
- $(AbstractionsPackageVersion.Split('.')[0]).$([MSBuild]::Add($(AbstractionsPackageVersion.Split('.')[1]), 1)).0
- $(SqlClientPackageVersion.Split('.')[0]).$([MSBuild]::Add($(SqlClientPackageVersion.Split('.')[1]), 1)).0
- $(AzurePackageVersion.Split('.')[0]).$([MSBuild]::Add($(AzurePackageVersion.Split('.')[1]), 1)).0
- $(AkvProviderPackageVersion.Split('.')[0]).$([MSBuild]::Add($(AkvProviderPackageVersion.Split('.')[1]), 1)).0
+ $(SqlServerPackageVersion.Trim().Split('.')[0]).$([MSBuild]::Add($(SqlServerPackageVersion.Trim().Split('.')[1]), 1)).0
+ $(LoggingPackageVersion.Trim().Split('.')[0]).$([MSBuild]::Add($(LoggingPackageVersion.Trim().Split('.')[1]), 1)).0
+ $(AbstractionsPackageVersion.Trim().Split('.')[0]).$([MSBuild]::Add($(AbstractionsPackageVersion.Trim().Split('.')[1]), 1)).0
+ $(SqlClientPackageVersion.Trim().Split('.')[0]).$([MSBuild]::Add($(SqlClientPackageVersion.Trim().Split('.')[1]), 1)).0
+ $(AzurePackageVersion.Trim().Split('.')[0]).$([MSBuild]::Add($(AzurePackageVersion.Trim().Split('.')[1]), 1)).0
+ $(AkvProviderPackageVersion.Trim().Split('.')[0]).$([MSBuild]::Add($(AkvProviderPackageVersion.Trim().Split('.')[1]), 1)).0
diff --git a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
index 108e1b6ab6..0d25d47a9f 100644
--- a/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
+++ b/src/Microsoft.Data.SqlClient/src/Microsoft.Data.SqlClient.csproj
@@ -209,10 +209,11 @@
-
- <_AbstractionsVersionRange>[$(AbstractionsPackageVersion), $(AbstractionsPackageVersion.Split('.')[0]).$([MSBuild]::Add($(AbstractionsPackageVersion.Split('.')[1]), 1)).0)
- <_LoggingVersionRange>[$(LoggingPackageVersion), $(LoggingPackageVersion.Split('.')[0]).$([MSBuild]::Add($(LoggingPackageVersion.Split('.')[1]), 1)).0)
- <_SqlServerVersionRange>[$(SqlServerPackageVersion), $(SqlServerPackageVersion.Split('.')[0]).$([MSBuild]::Add($(SqlServerPackageVersion.Split('.')[1]), 1)).0)
+
+ <_AbstractionsVersionRange>[$(_AbstractionsPackageVersionTrimmed), $(_AbstractionsPackageVersionTrimmed.Split('.')[0]).$([MSBuild]::Add($(_AbstractionsPackageVersionTrimmed.Split('.')[1]), 1)).0)
+ <_LoggingVersionRange>[$(_LoggingPackageVersionTrimmed), $(_LoggingPackageVersionTrimmed.Split('.')[0]).$([MSBuild]::Add($(_LoggingPackageVersionTrimmed.Split('.')[1]), 1)).0)
+ <_SqlServerVersionRange>[$(_SqlServerPackageVersionTrimmed), $(_SqlServerPackageVersionTrimmed.Split('.')[0]).$([MSBuild]::Add($(_SqlServerPackageVersionTrimmed.Split('.')[1]), 1)).0)
<_SqlClientPackNuspecExpandedText>$([System.IO.File]::ReadAllText('$(SqlClientPackNuspecTemplatePath)').Replace('$AbstractionsVersionRange$','$(_AbstractionsVersionRange)').Replace('$LoggingVersionRange$','$(_LoggingVersionRange)').Replace('$SqlServerVersionRange$','$(_SqlServerVersionRange)').Replace('$SniVersionRange$','$(SniVersionRange)'))