diff --git a/NuGet.config b/NuGet.config index 77f95a770bd..44fe13eda10 100644 --- a/NuGet.config +++ b/NuGet.config @@ -4,12 +4,7 @@ - - - - - - + @@ -24,12 +19,7 @@ - - - - - - + diff --git a/azure-pipelines-public.yml b/azure-pipelines-public.yml index f4436166dc3..f7421f55839 100644 --- a/azure-pipelines-public.yml +++ b/azure-pipelines-public.yml @@ -269,12 +269,12 @@ stages: value: $(_BuildConfig) - ${{ if eq(variables['System.TeamProject'], 'public') }}: - name: HelixTargetQueues - value: OSX.1100.Amd64.Open;(Ubuntu.2004.Amd64.SqlServer)Ubuntu.2004.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-20.04-helix-sqlserver-amd64 + value: Windows.10.Amd64.Open;OSX.1200.Amd64.Open;Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-20.04-helix-sqlserver-amd64 - name: _HelixAccessToken value: '' # Needed for public queues - ${{ if ne(variables['System.TeamProject'], 'public') }}: - name: HelixTargetQueues - value: OSX.1100.Amd64;(Ubuntu.2004.Amd64.SqlServer)Ubuntu.2004.Amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-20.04-helix-sqlserver-amd64 + value: Windows.10.Amd64;OSX.1200.Amd64;Ubuntu.2204.Amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-20.04-helix-sqlserver-amd64 - name: _HelixAccessToken value: $(HelixApiAccessToken) # Needed for internal queues steps: @@ -299,7 +299,7 @@ stages: env: HelixAccessToken: $(_HelixAccessToken) SYSTEM_ACCESSTOKEN: $(System.AccessToken) # We need to set this env var to publish helix results to Azure Dev Ops - MSSQL_SA_PASSWORD: "Password12!" + MSSQL_SA_PASSWORD: "PLACEHOLDER" COMPlus_EnableWriteXorExecute: 0 # Work-around for https://github.com/dotnet/runtime/issues/70758 DotNetBuildsInternalReadSasToken: $(dotnetbuilds-internal-container-read-token) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index b12ed89c253..6629d18b98f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -208,7 +208,7 @@ extends: - name: _HelixBuildConfig value: $(_BuildConfig) - name: HelixTargetQueues - value: OSX.1100.Amd64;(Ubuntu.2004.Amd64.SqlServer)Ubuntu.2004.Amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-20.04-helix-sqlserver-amd64 + value: Windows.10.Amd64;OSX.1200.Amd64;Ubuntu.2204.Amd64@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-20.04-helix-sqlserver-amd64 - name: _HelixAccessToken # Needed for internal queues value: $(HelixApiAccessToken) @@ -244,7 +244,7 @@ extends: HelixAccessToken: $(_HelixAccessToken) # We need to set this env var to publish helix results to Azure Dev Ops SYSTEM_ACCESSTOKEN: $(System.AccessToken) - MSSQL_SA_PASSWORD: "Password12!" + MSSQL_SA_PASSWORD: "PLACEHOLDER" # Work-around for https://github.com/dotnet/runtime/issues/70758 COMPlus_EnableWriteXorExecute: 0 DotNetBuildsInternalReadSasToken: $(dotnetbuilds-internal-container-read-token) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index a243a361997..98b29b6e167 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -1,9 +1,9 @@ - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 5535e31a712343a63f5d7d796cd874e563e5ac14 + 81cabf2857a01351e5ab578947c7403a5b128ad1 https://dev.azure.com/dnceng/internal/_git/dotnet-runtime @@ -13,60 +13,60 @@ https://dev.azure.com/dnceng/internal/_git/dotnet-runtime 5535e31a712343a63f5d7d796cd874e563e5ac14 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 5535e31a712343a63f5d7d796cd874e563e5ac14 + 81cabf2857a01351e5ab578947c7403a5b128ad1 https://dev.azure.com/dnceng/internal/_git/dotnet-runtime 5535e31a712343a63f5d7d796cd874e563e5ac14 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 5535e31a712343a63f5d7d796cd874e563e5ac14 + 81cabf2857a01351e5ab578947c7403a5b128ad1 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 2aade6beb02ea367fd97c4070a4198802fe61c03 + 81cabf2857a01351e5ab578947c7403a5b128ad1 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 08338fcaa5c9b9a8190abb99222fed12aaba956c + 81cabf2857a01351e5ab578947c7403a5b128ad1 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 5535e31a712343a63f5d7d796cd874e563e5ac14 + 81cabf2857a01351e5ab578947c7403a5b128ad1 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 2aade6beb02ea367fd97c4070a4198802fe61c03 + 81cabf2857a01351e5ab578947c7403a5b128ad1 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 08338fcaa5c9b9a8190abb99222fed12aaba956c + 81cabf2857a01351e5ab578947c7403a5b128ad1 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 08338fcaa5c9b9a8190abb99222fed12aaba956c + 81cabf2857a01351e5ab578947c7403a5b128ad1 - + https://dev.azure.com/dnceng/internal/_git/dotnet-runtime - 08338fcaa5c9b9a8190abb99222fed12aaba956c + 81cabf2857a01351e5ab578947c7403a5b128ad1 - + https://github.com/dotnet/arcade - c9efa535175049eb9cba06cae1f8c3d5dbe768a9 + 80264e60280e2815e7d65871081ccac04a32445c - + https://github.com/dotnet/arcade - c9efa535175049eb9cba06cae1f8c3d5dbe768a9 + 80264e60280e2815e7d65871081ccac04a32445c - + https://github.com/dotnet/arcade - c9efa535175049eb9cba06cae1f8c3d5dbe768a9 + 80264e60280e2815e7d65871081ccac04a32445c diff --git a/eng/Versions.props b/eng/Versions.props index d9054f1c116..8198b752055 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -1,6 +1,6 @@ - 8.0.8 + 8.0.10 servicing @@ -17,22 +17,22 @@ False - 8.0.0 + 8.0.1 8.0.0 8.0.0 8.0.0 - 8.0.0 - 8.0.0 - 8.0.1 - 8.0.8-servicing.24366.12 - 8.0.0 - 8.0.4 - 8.0.8 - 8.0.8 - 8.0.8-servicing.24366.12 + 8.0.1 + 8.0.1 + 8.0.2 + 8.0.10-servicing.24466.10 + 8.0.1 + 8.0.5 + 8.0.10 + 8.0.10 + 8.0.10-servicing.24466.10 - 8.0.0-beta.24360.5 + 8.0.0-beta.24426.2 diff --git a/eng/common/sdl/NuGet.config b/eng/common/sdl/NuGet.config index 3849bdb3cf5..5bfbb02ef04 100644 --- a/eng/common/sdl/NuGet.config +++ b/eng/common/sdl/NuGet.config @@ -5,11 +5,11 @@ - + - + diff --git a/eng/common/sdl/execute-all-sdl-tools.ps1 b/eng/common/sdl/execute-all-sdl-tools.ps1 index 4715d75e974..81ded5b7f47 100644 --- a/eng/common/sdl/execute-all-sdl-tools.ps1 +++ b/eng/common/sdl/execute-all-sdl-tools.ps1 @@ -6,7 +6,6 @@ Param( [string] $BranchName=$env:BUILD_SOURCEBRANCH, # Optional: name of branch or version of gdn settings; defaults to master [string] $SourceDirectory=$env:BUILD_SOURCESDIRECTORY, # Required: the directory where source files are located [string] $ArtifactsDirectory = (Join-Path $env:BUILD_ARTIFACTSTAGINGDIRECTORY ('artifacts')), # Required: the directory where build artifacts are located - [string] $AzureDevOpsAccessToken, # Required: access token for dnceng; should be provided via KeyVault # Optional: list of SDL tools to run on source code. See 'configure-sdl-tool.ps1' for tools list # format. @@ -75,7 +74,7 @@ try { } Exec-BlockVerbosely { - & $(Join-Path $PSScriptRoot 'init-sdl.ps1') -GuardianCliLocation $guardianCliLocation -Repository $RepoName -BranchName $BranchName -WorkingDirectory $workingDirectory -AzureDevOpsAccessToken $AzureDevOpsAccessToken -GuardianLoggerLevel $GuardianLoggerLevel + & $(Join-Path $PSScriptRoot 'init-sdl.ps1') -GuardianCliLocation $guardianCliLocation -Repository $RepoName -BranchName $BranchName -WorkingDirectory $workingDirectory -GuardianLoggerLevel $GuardianLoggerLevel } $gdnFolder = Join-Path $workingDirectory '.gdn' @@ -104,7 +103,6 @@ try { -TargetDirectory $targetDirectory ` -GdnFolder $gdnFolder ` -ToolsList $tools ` - -AzureDevOpsAccessToken $AzureDevOpsAccessToken ` -GuardianLoggerLevel $GuardianLoggerLevel ` -CrScanAdditionalRunConfigParams $CrScanAdditionalRunConfigParams ` -PoliCheckAdditionalRunConfigParams $PoliCheckAdditionalRunConfigParams ` diff --git a/eng/common/sdl/init-sdl.ps1 b/eng/common/sdl/init-sdl.ps1 index 3ac1d92b370..588ff8e22fb 100644 --- a/eng/common/sdl/init-sdl.ps1 +++ b/eng/common/sdl/init-sdl.ps1 @@ -3,7 +3,6 @@ Param( [string] $Repository, [string] $BranchName='master', [string] $WorkingDirectory, - [string] $AzureDevOpsAccessToken, [string] $GuardianLoggerLevel='Standard' ) @@ -21,14 +20,7 @@ $ci = $true # Don't display the console progress UI - it's a huge perf hit $ProgressPreference = 'SilentlyContinue' -# Construct basic auth from AzDO access token; construct URI to the repository's gdn folder stored in that repository; construct location of zip file -$encodedPat = [Convert]::ToBase64String([System.Text.Encoding]::ASCII.GetBytes(":$AzureDevOpsAccessToken")) -$escapedRepository = [Uri]::EscapeDataString("/$Repository/$BranchName/.gdn") -$uri = "https://dev.azure.com/dnceng/internal/_apis/git/repositories/sdl-tool-cfg/Items?path=$escapedRepository&versionDescriptor[versionOptions]=0&`$format=zip&api-version=5.0" -$zipFile = "$WorkingDirectory/gdn.zip" - Add-Type -AssemblyName System.IO.Compression.FileSystem -$gdnFolder = (Join-Path $WorkingDirectory '.gdn') try { # if the folder does not exist, we'll do a guardian init and push it to the remote repository diff --git a/eng/common/sdl/sdl.ps1 b/eng/common/sdl/sdl.ps1 index 648c5068d7d..7fe603fe995 100644 --- a/eng/common/sdl/sdl.ps1 +++ b/eng/common/sdl/sdl.ps1 @@ -4,6 +4,8 @@ function Install-Gdn { [Parameter(Mandatory=$true)] [string]$Path, + [string]$Source = "https://pkgs.dev.azure.com/dnceng/_packaging/Guardian1ESPTUpstreamOrgFeed/nuget/v3/index.json", + # If omitted, install the latest version of Guardian, otherwise install that specific version. [string]$Version ) @@ -19,7 +21,7 @@ function Install-Gdn { $ci = $true . $PSScriptRoot\..\tools.ps1 - $argumentList = @("install", "Microsoft.Guardian.Cli", "-Source https://securitytools.pkgs.visualstudio.com/_packaging/Guardian/nuget/v3/index.json", "-OutputDirectory $Path", "-NonInteractive", "-NoCache") + $argumentList = @("install", "Microsoft.Guardian.Cli.win-x64", "-Source $Source", "-OutputDirectory $Path", "-NonInteractive", "-NoCache") if ($Version) { $argumentList += "-Version $Version" diff --git a/eng/common/templates-official/job/publish-build-assets.yml b/eng/common/templates-official/job/publish-build-assets.yml index ba3e7df8158..0117328800c 100644 --- a/eng/common/templates-official/job/publish-build-assets.yml +++ b/eng/common/templates-official/job/publish-build-assets.yml @@ -149,7 +149,7 @@ jobs: scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 arguments: -BuildId $(BARBuildId) -PublishingInfraVersion 3 - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' + -AzdoToken '$(System.AccessToken)' -WaitPublishingFinish true -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' diff --git a/eng/common/templates-official/post-build/post-build.yml b/eng/common/templates-official/post-build/post-build.yml index 0dfa387e7b7..b81b8770b34 100644 --- a/eng/common/templates-official/post-build/post-build.yml +++ b/eng/common/templates-official/post-build/post-build.yml @@ -281,7 +281,7 @@ stages: scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 arguments: -BuildId $(BARBuildId) -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' + -AzdoToken '$(System.AccessToken)' -WaitPublishingFinish true -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' diff --git a/eng/common/templates-official/steps/execute-sdl.yml b/eng/common/templates-official/steps/execute-sdl.yml index 07426fde05d..301d5c591eb 100644 --- a/eng/common/templates-official/steps/execute-sdl.yml +++ b/eng/common/templates-official/steps/execute-sdl.yml @@ -9,8 +9,6 @@ parameters: steps: - task: NuGetAuthenticate@1 - inputs: - nuGetServiceConnections: GuardianConnect - task: NuGetToolInstaller@1 displayName: 'Install NuGet.exe' diff --git a/eng/common/templates-official/steps/get-delegation-sas.yml b/eng/common/templates-official/steps/get-delegation-sas.yml index 8fea69b6240..c0e8f91317f 100644 --- a/eng/common/templates-official/steps/get-delegation-sas.yml +++ b/eng/common/templates-official/steps/get-delegation-sas.yml @@ -28,17 +28,12 @@ steps: # Calculate the expiration of the SAS token and convert to UTC $expiry = (Get-Date).AddHours(${{ parameters.expiryInHours }}).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") - # Temporarily work around a helix issue where SAS tokens with / in them will cause incorrect downloads - # of correlation payloads. - $sas = "" - do { - $sas = az storage container generate-sas --account-name ${{ parameters.storageAccount }} --name ${{ parameters.container }} --permissions ${{ parameters.permissions }} --expiry $expiry --auth-mode login --as-user -o tsv + $sas = az storage container generate-sas --account-name ${{ parameters.storageAccount }} --name ${{ parameters.container }} --permissions ${{ parameters.permissions }} --expiry $expiry --auth-mode login --as-user -o tsv - if ($LASTEXITCODE -ne 0) { - Write-Error "Failed to generate SAS token." - exit 1 - } - } while($sas.IndexOf('/') -ne -1) + if ($LASTEXITCODE -ne 0) { + Write-Error "Failed to generate SAS token." + exit 1 + } if ('${{ parameters.base64Encode }}' -eq 'true') { $sas = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($sas)) diff --git a/eng/common/templates-official/steps/get-federated-access-token.yml b/eng/common/templates-official/steps/get-federated-access-token.yml index e3786cef6df..55e33bd38f7 100644 --- a/eng/common/templates-official/steps/get-federated-access-token.yml +++ b/eng/common/templates-official/steps/get-federated-access-token.yml @@ -3,6 +3,12 @@ parameters: type: string - name: outputVariableName type: string +- name: stepName + type: string + default: 'getFederatedAccessToken' +- name: condition + type: string + default: '' # Resource to get a token for. Common values include: # - '499b84ac-1321-427f-aa17-267ca6975798' for Azure DevOps # - 'https://storage.azure.com/' for storage @@ -10,10 +16,16 @@ parameters: - name: resource type: string default: '499b84ac-1321-427f-aa17-267ca6975798' +- name: isStepOutputVariable + type: boolean + default: false steps: - task: AzureCLI@2 displayName: 'Getting federated access token for feeds' + name: ${{ parameters.stepName }} + ${{ if ne(parameters.condition, '') }}: + condition: ${{ parameters.condition }} inputs: azureSubscription: ${{ parameters.federatedServiceConnection }} scriptType: 'pscore' @@ -25,4 +37,4 @@ steps: exit 1 } Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value" - Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true]$accessToken" + Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true;isOutput=${{ parameters.isStepOutputVariable }}]$accessToken" \ No newline at end of file diff --git a/eng/common/templates/job/publish-build-assets.yml b/eng/common/templates/job/publish-build-assets.yml index 57a41f0a3e1..cc2b346ba8b 100644 --- a/eng/common/templates/job/publish-build-assets.yml +++ b/eng/common/templates/job/publish-build-assets.yml @@ -145,7 +145,7 @@ jobs: scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 arguments: -BuildId $(BARBuildId) -PublishingInfraVersion 3 - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' + -AzdoToken '$(System.AccessToken)' -WaitPublishingFinish true -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' diff --git a/eng/common/templates/post-build/post-build.yml b/eng/common/templates/post-build/post-build.yml index 2db4933468f..c3b6a3012fe 100644 --- a/eng/common/templates/post-build/post-build.yml +++ b/eng/common/templates/post-build/post-build.yml @@ -277,7 +277,7 @@ stages: scriptPath: $(Build.SourcesDirectory)/eng/common/post-build/publish-using-darc.ps1 arguments: -BuildId $(BARBuildId) -PublishingInfraVersion ${{ parameters.publishingInfraVersion }} - -AzdoToken '$(publishing-dnceng-devdiv-code-r-build-re)' + -AzdoToken '$(System.AccessToken)' -WaitPublishingFinish true -ArtifactsPublishingAdditionalParameters '${{ parameters.artifactsPublishingAdditionalParameters }}' -SymbolPublishingAdditionalParameters '${{ parameters.symbolPublishingAdditionalParameters }}' diff --git a/eng/common/templates/steps/execute-sdl.yml b/eng/common/templates/steps/execute-sdl.yml index 07426fde05d..fe0ebf8c904 100644 --- a/eng/common/templates/steps/execute-sdl.yml +++ b/eng/common/templates/steps/execute-sdl.yml @@ -9,8 +9,6 @@ parameters: steps: - task: NuGetAuthenticate@1 - inputs: - nuGetServiceConnections: GuardianConnect - task: NuGetToolInstaller@1 displayName: 'Install NuGet.exe' @@ -36,16 +34,19 @@ steps: displayName: Execute SDL (Overridden) continueOnError: ${{ parameters.sdlContinueOnError }} condition: ${{ parameters.condition }} + env: + GUARDIAN_DEFAULT_PACKAGE_SOURCE_SECRET: $(System.AccessToken) - ${{ if eq(parameters.overrideParameters, '') }}: - powershell: ${{ parameters.executeAllSdlToolsScript }} -GuardianCliLocation $(GuardianCliLocation) -NugetPackageDirectory $(Build.SourcesDirectory)\.packages - -AzureDevOpsAccessToken $(dn-bot-dotnet-build-rw-code-rw) ${{ parameters.additionalParameters }} displayName: Execute SDL continueOnError: ${{ parameters.sdlContinueOnError }} condition: ${{ parameters.condition }} + env: + GUARDIAN_DEFAULT_PACKAGE_SOURCE_SECRET: $(System.AccessToken) - ${{ if ne(parameters.publishGuardianDirectoryToPipeline, 'false') }}: # We want to publish the Guardian results and configuration for easy diagnosis. However, the diff --git a/eng/common/templates/steps/get-delegation-sas.yml b/eng/common/templates/steps/get-delegation-sas.yml index 8fea69b6240..c0e8f91317f 100644 --- a/eng/common/templates/steps/get-delegation-sas.yml +++ b/eng/common/templates/steps/get-delegation-sas.yml @@ -28,17 +28,12 @@ steps: # Calculate the expiration of the SAS token and convert to UTC $expiry = (Get-Date).AddHours(${{ parameters.expiryInHours }}).ToUniversalTime().ToString("yyyy-MM-ddTHH:mm:ssZ") - # Temporarily work around a helix issue where SAS tokens with / in them will cause incorrect downloads - # of correlation payloads. - $sas = "" - do { - $sas = az storage container generate-sas --account-name ${{ parameters.storageAccount }} --name ${{ parameters.container }} --permissions ${{ parameters.permissions }} --expiry $expiry --auth-mode login --as-user -o tsv + $sas = az storage container generate-sas --account-name ${{ parameters.storageAccount }} --name ${{ parameters.container }} --permissions ${{ parameters.permissions }} --expiry $expiry --auth-mode login --as-user -o tsv - if ($LASTEXITCODE -ne 0) { - Write-Error "Failed to generate SAS token." - exit 1 - } - } while($sas.IndexOf('/') -ne -1) + if ($LASTEXITCODE -ne 0) { + Write-Error "Failed to generate SAS token." + exit 1 + } if ('${{ parameters.base64Encode }}' -eq 'true') { $sas = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($sas)) diff --git a/eng/common/templates/steps/get-federated-access-token.yml b/eng/common/templates/steps/get-federated-access-token.yml index c8c49cc0e8f..55e33bd38f7 100644 --- a/eng/common/templates/steps/get-federated-access-token.yml +++ b/eng/common/templates/steps/get-federated-access-token.yml @@ -3,6 +3,12 @@ parameters: type: string - name: outputVariableName type: string +- name: stepName + type: string + default: 'getFederatedAccessToken' +- name: condition + type: string + default: '' # Resource to get a token for. Common values include: # - '499b84ac-1321-427f-aa17-267ca6975798' for Azure DevOps # - 'https://storage.azure.com/' for storage @@ -10,10 +16,16 @@ parameters: - name: resource type: string default: '499b84ac-1321-427f-aa17-267ca6975798' +- name: isStepOutputVariable + type: boolean + default: false steps: - task: AzureCLI@2 displayName: 'Getting federated access token for feeds' + name: ${{ parameters.stepName }} + ${{ if ne(parameters.condition, '') }}: + condition: ${{ parameters.condition }} inputs: azureSubscription: ${{ parameters.federatedServiceConnection }} scriptType: 'pscore' @@ -25,4 +37,4 @@ steps: exit 1 } Write-Host "Setting '${{ parameters.outputVariableName }}' with the access token value" - Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true]$accessToken" \ No newline at end of file + Write-Host "##vso[task.setvariable variable=${{ parameters.outputVariableName }};issecret=true;isOutput=${{ parameters.isStepOutputVariable }}]$accessToken" \ No newline at end of file diff --git a/eng/common/templates/steps/telemetry-start.yml b/eng/common/templates/steps/telemetry-start.yml index 32c01ef0b55..6abbcb33a67 100644 --- a/eng/common/templates/steps/telemetry-start.yml +++ b/eng/common/templates/steps/telemetry-start.yml @@ -8,7 +8,7 @@ parameters: steps: - ${{ if and(eq(parameters.runAsPublic, 'false'), not(eq(variables['System.TeamProject'], 'public'))) }}: - - task: AzureKeyVault@1 + - task: AzureKeyVault@2 inputs: azureSubscription: 'HelixProd_KeyVault' KeyVaultName: HelixProdKV diff --git a/eng/helix.proj b/eng/helix.proj index c0f654f9467..acec0077401 100644 --- a/eng/helix.proj +++ b/eng/helix.proj @@ -17,11 +17,11 @@ - Windows.10.Amd64.Open;OSX.1200.Amd64.Open;Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-18.04-helix-sqlserver-amd64 + Windows.10.Amd64.Open;OSX.1200.Amd64.Open;Ubuntu.2204.Amd64.Open@mcr.microsoft.com/dotnet-buildtools/prereqs:ubuntu-20.04-helix-sqlserver-amd64 false efcore/localbuild/ t001 - Password12! + PLACEHOLDER diff --git a/global.json b/global.json index 23f3045067d..528c6ba8045 100644 --- a/global.json +++ b/global.json @@ -1,11 +1,11 @@ { "sdk": { - "version": "8.0.101", + "version": "8.0.108", "allowPrerelease": true, "rollForward": "latestMajor" }, "tools": { - "dotnet": "8.0.101", + "dotnet": "8.0.108", "runtimes": { "dotnet": [ "$(MicrosoftNETCoreBrowserDebugHostTransportVersion)" @@ -13,7 +13,7 @@ } }, "msbuild-sdks": { - "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24360.5", - "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.24360.5" + "Microsoft.DotNet.Arcade.Sdk": "8.0.0-beta.24426.2", + "Microsoft.DotNet.Helix.Sdk": "8.0.0-beta.24426.2" } } diff --git a/src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs b/src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs index 8f7cc37bd56..78dd77f4f3a 100644 --- a/src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs +++ b/src/EFCore.Cosmos/Storage/Internal/CosmosTypeMappingSource.cs @@ -3,6 +3,7 @@ using System.Collections.ObjectModel; using Microsoft.EntityFrameworkCore.Cosmos.ChangeTracking.Internal; +using Microsoft.EntityFrameworkCore.Storage.Json; using Newtonsoft.Json.Linq; namespace Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal; @@ -17,6 +18,9 @@ public class CosmosTypeMappingSource : TypeMappingSource { private readonly Dictionary _clrTypeMappings; + internal static readonly bool UseOldBehavior33704 = + AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue33704", out var enabled33704) && enabled33704; + /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in @@ -69,6 +73,26 @@ public CosmosTypeMappingSource(TypeMappingSourceDependencies dependencies) return null; } + /// + protected override bool TryFindJsonCollectionMapping( + TypeMappingInfo mappingInfo, + Type modelClrType, + Type? providerClrType, + ref CoreTypeMapping? elementMapping, + out ValueComparer? elementComparer, + out JsonValueReaderWriter? collectionReaderWriter) + { + if (UseOldBehavior33704) + { + return base.TryFindJsonCollectionMapping( + mappingInfo, modelClrType, providerClrType, ref elementMapping, out elementComparer, out collectionReaderWriter); + } + + elementComparer = null; + collectionReaderWriter = null; + return false; + } + private CoreTypeMapping? FindCollectionMapping(in TypeMappingInfo mappingInfo) { var clrType = mappingInfo.ClrType!; diff --git a/src/EFCore/Metadata/Conventions/ElementTypeChangedConvention.cs b/src/EFCore/Metadata/Conventions/ElementTypeChangedConvention.cs index 3e40ea9269e..7f1f12b35a5 100644 --- a/src/EFCore/Metadata/Conventions/ElementTypeChangedConvention.cs +++ b/src/EFCore/Metadata/Conventions/ElementTypeChangedConvention.cs @@ -9,11 +9,15 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions; /// /// See Model building conventions for more information and examples. /// -public class ElementTypeChangedConvention : IPropertyElementTypeChangedConvention, IForeignKeyAddedConvention +public class ElementTypeChangedConvention : + IPropertyElementTypeChangedConvention, IForeignKeyAddedConvention, IForeignKeyPropertiesChangedConvention { internal static readonly bool UseOldBehavior32411 = AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue32411", out var enabled32411) && enabled32411; + internal static readonly bool UseOldBehavior33704 = + AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue33704", out var enabled33704) && enabled33704; + /// /// Creates a new instance of . /// @@ -50,6 +54,23 @@ public void ProcessPropertyElementTypeChanged( /// public void ProcessForeignKeyAdded( IConventionForeignKeyBuilder foreignKeyBuilder, IConventionContext context) + => ProcessForeignKey(foreignKeyBuilder); + + /// + public void ProcessForeignKeyPropertiesChanged( + IConventionForeignKeyBuilder relationshipBuilder, + IReadOnlyList oldDependentProperties, + IConventionKey oldPrincipalKey, + IConventionContext> context) + { + if (relationshipBuilder.Metadata.IsInModel + && !UseOldBehavior33704) + { + ProcessForeignKey(relationshipBuilder); + } + } + + private static void ProcessForeignKey(IConventionForeignKeyBuilder foreignKeyBuilder) { var foreignKeyProperties = foreignKeyBuilder.Metadata.Properties; var principalKeyProperties = foreignKeyBuilder.Metadata.PrincipalKey.Properties; diff --git a/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs b/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs index 63443cb2bef..e3e43e88dff 100644 --- a/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs +++ b/src/EFCore/Metadata/Internal/InternalPropertyBuilder.cs @@ -802,6 +802,14 @@ public virtual bool CanSetProviderValueComparer( { Metadata.SetValueConverter((Type?)null, configurationSource); } + + if (elementType == null + && CanSetConversion((Type?)null, configurationSource) + && !ElementTypeChangedConvention.UseOldBehavior33704) + { + Metadata.RemoveAnnotation(CoreAnnotationNames.ValueConverter); + } + return new InternalElementTypeBuilder(Metadata.GetElementType()!, ModelBuilder); } diff --git a/src/EFCore/Metadata/Internal/InternalTypeBaseBuilder.cs b/src/EFCore/Metadata/Internal/InternalTypeBaseBuilder.cs index b9ab85070bb..24333f89885 100644 --- a/src/EFCore/Metadata/Internal/InternalTypeBaseBuilder.cs +++ b/src/EFCore/Metadata/Internal/InternalTypeBaseBuilder.cs @@ -15,6 +15,9 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Internal; public abstract class InternalTypeBaseBuilder : AnnotatableBuilder, IConventionTypeBaseBuilder { + private static readonly bool UseOldBehavior34201 = + AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue34201", out var enabled34201) && enabled34201; + /// /// This is an internal API that supports the Entity Framework Core infrastructure and not subject to /// the same compatibility standards as public APIs. It may be changed or removed without notice in @@ -204,6 +207,7 @@ public static bool IsCompatible(MemberInfo? newMemberInfo, PropertyBase existing || (memberInfo is PropertyInfo propertyInfo && propertyInfo.IsIndexerProperty())) { if (existingProperty.GetTypeConfigurationSource() is ConfigurationSource existingTypeConfigurationSource + && (typeConfigurationSource != null || UseOldBehavior34201) && !typeConfigurationSource.Overrides(existingTypeConfigurationSource)) { return null; diff --git a/test/EFCore.Cosmos.Tests/ModelBuilding/CosmosModelBuilderGenericTest.cs b/test/EFCore.Cosmos.Tests/ModelBuilding/CosmosModelBuilderGenericTest.cs index a528c3d2df6..4a1fd8ecb06 100644 --- a/test/EFCore.Cosmos.Tests/ModelBuilding/CosmosModelBuilderGenericTest.cs +++ b/test/EFCore.Cosmos.Tests/ModelBuilding/CosmosModelBuilderGenericTest.cs @@ -13,181 +13,181 @@ public class CosmosGenericNonRelationship : GenericNonRelationship { public override void Can_set_composite_key_for_primitive_collection_on_an_entity_with_fields() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(EntityWithFields), "CollectionCompanyId"), + CoreStrings.PropertyNotMapped("int[]", nameof(EntityWithFields), "CollectionCompanyId"), Assert.Throws( () => base.Can_set_composite_key_for_primitive_collection_on_an_entity_with_fields()).Message); public override void Access_mode_can_be_overridden_at_entity_and_primitive_collection_levels() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Down"), + CoreStrings.PropertyNotMapped("ObservableCollection", nameof(CollectionQuarks), "Down"), Assert.Throws( () => base.Access_mode_can_be_overridden_at_entity_and_primitive_collection_levels()).Message); public override void Can_set_custom_value_generator_for_primitive_collections() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Bottom"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Bottom"), Assert.Throws( () => base.Can_set_custom_value_generator_for_primitive_collections()).Message); public override void Can_set_element_type_annotation() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(Customer), "Notes"), + CoreStrings.PropertyNotMapped("List", nameof(Customer), "Notes"), Assert.Throws( () => base.Can_set_element_type_annotation()).Message); public override void Can_set_max_length_for_primitive_collections() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Bottom"), + CoreStrings.PropertyNotMapped("string[]", nameof(CollectionQuarks), "Bottom"), Assert.Throws( () => base.Can_set_max_length_for_primitive_collections()).Message); public override void Can_set_primitive_collection_annotation() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(Customer), "Notes"), + CoreStrings.PropertyNotMapped("List", nameof(Customer), "Notes"), Assert.Throws( () => base.Can_set_primitive_collection_annotation()).Message); public override void Can_set_primitive_collection_annotation_by_type() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(Customer), "Notes"), + CoreStrings.PropertyNotMapped("List", nameof(Customer), "Notes"), Assert.Throws( () => base.Can_set_primitive_collection_annotation_by_type()).Message); public override void Can_set_primitive_collection_annotation_when_no_clr_property() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(Customer), "Notes"), + CoreStrings.PropertyNotMapped("List", nameof(Customer), "Notes"), Assert.Throws( () => base.Can_set_primitive_collection_annotation_when_no_clr_property()).Message); public override void Can_set_sentinel_for_primitive_collections() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Bottom"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Bottom"), Assert.Throws( () => base.Can_set_sentinel_for_primitive_collections()).Message); public override void Can_set_unicode_for_primitive_collections() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Bottom"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Bottom"), Assert.Throws( () => base.Can_set_unicode_for_primitive_collections()).Message); public override void Element_types_are_nullable_by_default_if_the_type_is_nullable() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Element_types_are_nullable_by_default_if_the_type_is_nullable()).Message); public override void Element_types_can_be_made_required() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Element_types_can_be_made_required()).Message); public override void Element_types_can_have_custom_type_value_converter_type_set() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("int[]", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Element_types_can_have_custom_type_value_converter_type_set()).Message); public override void Element_types_can_have_max_length() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Element_types_can_have_max_length()).Message); public override void Element_types_can_have_non_generic_value_converter_set() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("int[]", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Element_types_can_have_non_generic_value_converter_set()).Message); public override void Element_types_can_have_precision_and_scale() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Element_types_can_have_precision_and_scale()).Message); public override void Element_types_can_have_provider_type_set() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Element_types_can_have_provider_type_set()).Message); public override void Element_types_can_have_unicode_set() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Element_types_can_have_unicode_set()).Message); public override void Element_types_have_default_precision_and_scale() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Element_types_have_default_precision_and_scale()).Message); public override void Element_types_have_default_unicode() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Element_types_have_default_unicode()).Message); public override void Element_types_have_no_max_length_by_default() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Element_types_have_no_max_length_by_default()).Message); public override void Primitive_collections_are_required_by_default_only_if_CLR_type_is_nullable() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Primitive_collections_are_required_by_default_only_if_CLR_type_is_nullable()).Message); public override void Primitive_collections_can_be_made_optional() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Primitive_collections_can_be_made_optional()).Message); public override void Primitive_collections_can_be_made_required() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Primitive_collections_can_be_made_required()).Message); public override void Primitive_collections_can_be_set_to_generate_values_on_Add() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Bottom"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Bottom"), Assert.Throws( () => base.Primitive_collections_can_be_set_to_generate_values_on_Add()).Message); public override void Primitive_collections_can_have_access_mode_set() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("ObservableCollection", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Primitive_collections_can_have_access_mode_set()).Message); public override void Primitive_collections_can_have_field_set() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Down"), + CoreStrings.PropertyNotMapped("ObservableCollection", nameof(CollectionQuarks), "Down"), Assert.Throws( () => base.Primitive_collections_can_have_field_set()).Message); public override void Primitive_collections_can_have_value_converter_set() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Primitive_collections_can_have_value_converter_set()).Message); public override void Primitive_collections_specified_by_string_are_shadow_properties_unless_already_known_to_be_CLR_properties() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("ObservableCollection", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Primitive_collections_specified_by_string_are_shadow_properties_unless_already_known_to_be_CLR_properties()).Message); public override void Value_converter_type_on_primitive_collection_is_checked() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Up"), + CoreStrings.PropertyNotMapped("ObservableCollection", nameof(CollectionQuarks), "Up"), Assert.Throws( () => base.Value_converter_type_on_primitive_collection_is_checked()).Message); @@ -425,7 +425,7 @@ public virtual void No_alternate_key_is_created_if_id_is_partition_key() public override void Primitive_collections_can_be_made_concurrency_tokens() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", nameof(CollectionQuarks), "Charm"), Assert.Throws( () => base.Primitive_collections_can_be_made_concurrency_tokens()).Message); @@ -437,97 +437,97 @@ public class CosmosGenericComplexType : GenericComplexType { public override void Access_mode_can_be_overridden_at_entity_and_property_levels() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Down"), + CoreStrings.PropertyNotMapped("ObservableCollection", "ComplexProperties.CollectionQuarks#CollectionQuarks", "Down"), Assert.Throws( () => base.Access_mode_can_be_overridden_at_entity_and_property_levels()).Message); public override void Can_add_shadow_primitive_collections_when_they_have_been_ignored() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(Customer), "Shadow"), + CoreStrings.PropertyNotMapped("string[]", "ComplexProperties.Customer#Customer", "Shadow"), Assert.Throws( () => base.Can_add_shadow_primitive_collections_when_they_have_been_ignored()).Message); public override void Can_call_PrimitiveCollection_on_a_field() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(EntityWithFields), "CollectionId"), + CoreStrings.PropertyNotMapped("long[]", "ComplexProperties.EntityWithFields#EntityWithFields", "CollectionId"), Assert.Throws( () => base.Can_call_PrimitiveCollection_on_a_field()).Message); public override void Can_set_custom_value_generator_for_primitive_collections() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Bottom"), + CoreStrings.PropertyNotMapped("List", "ComplexProperties.CollectionQuarks#CollectionQuarks", "Bottom"), Assert.Throws( () => base.Can_set_custom_value_generator_for_primitive_collections()).Message); public override void Can_set_max_length_for_primitive_collections() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Bottom"), + CoreStrings.PropertyNotMapped("string[]", "ComplexProperties.CollectionQuarks#CollectionQuarks", "Bottom"), Assert.Throws( () => base.Can_set_max_length_for_primitive_collections()).Message); public override void Can_set_primitive_collection_annotation_when_no_clr_property() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(Customer), "Ints"), + CoreStrings.PropertyNotMapped("int[]", "ComplexProperties.Customer#Customer", "Ints"), Assert.Throws( () => base.Can_set_primitive_collection_annotation_when_no_clr_property()).Message); public override void Can_set_sentinel_for_primitive_collections() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Bottom"), + CoreStrings.PropertyNotMapped("List", "ComplexProperties.CollectionQuarks#CollectionQuarks", "Bottom"), Assert.Throws( () => base.Can_set_sentinel_for_primitive_collections()).Message); public override void Can_set_unicode_for_primitive_collections() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Bottom"), + CoreStrings.PropertyNotMapped("List", "ComplexProperties.CollectionQuarks#CollectionQuarks", "Bottom"), Assert.Throws( () => base.Can_set_unicode_for_primitive_collections()).Message); public override void Primitive_collections_are_required_by_default_only_if_CLR_type_is_nullable() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", "ComplexProperties.CollectionQuarks#CollectionQuarks", "Charm"), Assert.Throws( () => base.Primitive_collections_are_required_by_default_only_if_CLR_type_is_nullable()).Message); public override void Primitive_collections_can_be_made_concurrency_tokens() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", "ComplexProperties.CollectionQuarks#CollectionQuarks", "Charm"), Assert.Throws( () => base.Primitive_collections_can_be_made_concurrency_tokens()).Message); public override void Primitive_collections_can_be_made_optional() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", "ComplexProperties.CollectionQuarks#CollectionQuarks", "Charm"), Assert.Throws( () => base.Primitive_collections_can_be_made_optional()).Message); public override void Primitive_collections_can_be_made_required() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("List", "ComplexProperties.CollectionQuarks#CollectionQuarks", "Charm"), Assert.Throws( () => base.Primitive_collections_can_be_made_required()).Message); public override void Primitive_collections_can_be_set_to_generate_values_on_Add() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Bottom"), + CoreStrings.PropertyNotMapped("List", "ComplexProperties.CollectionQuarks#CollectionQuarks", "Bottom"), Assert.Throws( () => base.Primitive_collections_can_be_set_to_generate_values_on_Add()).Message); public override void Primitive_collections_can_have_field_set() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Down"), + CoreStrings.PropertyNotMapped("ObservableCollection", "ComplexProperties.CollectionQuarks#CollectionQuarks", "Down"), Assert.Throws( () => base.Primitive_collections_can_have_field_set()).Message); public override void Primitive_collections_specified_by_string_are_shadow_properties_unless_already_known_to_be_CLR_properties() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Charm"), + CoreStrings.PropertyNotMapped("ObservableCollection", "ComplexProperties.CollectionQuarks#CollectionQuarks", "Charm"), Assert.Throws( () => base.Primitive_collections_specified_by_string_are_shadow_properties_unless_already_known_to_be_CLR_properties()).Message); public override void Properties_can_have_access_mode_set() => Assert.Equal( - CosmosStrings.PrimitiveCollectionsNotSupported(nameof(CollectionQuarks), "Down"), + CoreStrings.PropertyNotMapped("ObservableCollection", "ComplexProperties.CollectionQuarks#CollectionQuarks", "Down"), Assert.Throws( () => base.Properties_can_have_access_mode_set()).Message); diff --git a/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs b/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs index b0f732c5b56..aa91709aaec 100644 --- a/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs +++ b/test/EFCore.Relational.Tests/Migrations/Internal/MigrationsModelDifferTest.cs @@ -8646,7 +8646,7 @@ public void Split_out_subtype_with_seed_data() x.Property("Name"); x.Property("Discriminator"); - x.HasDiscriminator("Discriminator") + x.HasDiscriminator() .HasValue(1) .HasValue(2); diff --git a/test/EFCore.Tests/ModelBuilding/OwnedTypesTestBase.cs b/test/EFCore.Tests/ModelBuilding/OwnedTypesTestBase.cs index 095825c8dd0..fa421eb73b7 100644 --- a/test/EFCore.Tests/ModelBuilding/OwnedTypesTestBase.cs +++ b/test/EFCore.Tests/ModelBuilding/OwnedTypesTestBase.cs @@ -1076,11 +1076,12 @@ public virtual void Can_map_derived_of_owned_type_first() } [ConditionalFact] - public virtual void Can_configure_relationship_with_PK_ValueConverter() + public virtual void Can_configure_relationship_with_PK_ValueConverter_shadow_FK() { var modelBuilder = CreateModelBuilder(); - modelBuilder.Entity().Property(x => x.Id) + modelBuilder.Entity() + .Property(x => x.Id) .HasConversion(x => x.Id, x => new CustomId { Id = x }); modelBuilder.Entity() @@ -1089,8 +1090,7 @@ public virtual void Can_configure_relationship_with_PK_ValueConverter() modelBuilder.Entity() .OwnsOne(q => q.Value) - .Property(x => x.CategoryId) - .HasConversion(x => x.Id, x => new CustomId { Id = x }); + .Property(x => x.CategoryId); var model = modelBuilder.FinalizeModel(); @@ -1106,14 +1106,45 @@ public virtual void Can_configure_relationship_with_PK_ValueConverter() var category = model.FindEntityType(typeof(ValueCategory)); Assert.Null(category.FindProperty("TempId")); - var barNavigation = owned.GetDeclaredNavigations().Single(n => !n.ForeignKey.IsOwnership); - Assert.Same(category, barNavigation.TargetEntityType); - var fkProperty = barNavigation.ForeignKey.Properties.Single(); + var categoryNavigation = owned.GetDeclaredNavigations().Single(n => !n.ForeignKey.IsOwnership); + Assert.Same(category, categoryNavigation.TargetEntityType); + var fkProperty = categoryNavigation.ForeignKey.Properties.Single(); Assert.Equal("CategoryId", fkProperty.Name); Assert.Equal(3, model.GetEntityTypes().Count()); } + [ConditionalFact] + public virtual void Can_configure_relationship_with_PK_ValueConverter() + { + var modelBuilder = CreateModelBuilder(); + + modelBuilder.Entity(eb => + { + eb.Property(x => x.Id) + .HasConversion(x => x.Id, x => new CustomId { Id = x }); + eb.OwnsOne(q => q.Value) + .WithOwner() + .HasForeignKey(q => q.CategoryId); + }); + + modelBuilder.Ignore(); + + var model = modelBuilder.FinalizeModel(); + + var result = model.FindEntityType(typeof(QueryResult)); + Assert.Null(result.FindProperty("TempId")); + + var owned = result.GetDeclaredNavigations().Single().TargetEntityType; + Assert.Null(owned.FindProperty("TempId")); + + var ownedPkProperty = owned.FindPrimaryKey().Properties.Single(); + Assert.NotNull(ownedPkProperty.GetValueConverter()); + + Assert.Empty(owned.GetDeclaredNavigations().Where(n => !n.ForeignKey.IsOwnership)); + Assert.Equal(2, model.GetEntityTypes().Count()); + } + [ConditionalFact] public virtual void Throws_on_FK_matching_two_relationships() { diff --git a/test/EFCore.Tests/ModelBuilding/TestModel.cs b/test/EFCore.Tests/ModelBuilding/TestModel.cs index 215ec576aaf..cc1a81e459e 100644 --- a/test/EFCore.Tests/ModelBuilding/TestModel.cs +++ b/test/EFCore.Tests/ModelBuilding/TestModel.cs @@ -3,6 +3,7 @@ #nullable enable +using System.Collections; using System.Collections.ObjectModel; using System.ComponentModel; using System.ComponentModel.DataAnnotations; @@ -809,9 +810,12 @@ protected class Value public ValueCategory? Category { get; set; } } - protected class CustomId + protected class CustomId : IEnumerable { public int Id { get; set; } + + public IEnumerator GetEnumerator() => throw new NotImplementedException(); + IEnumerator IEnumerable.GetEnumerator() => throw new NotImplementedException(); } protected class ValueCategory