Skip to content

Commit 79d37f9

Browse files
committed
2 parents cab272a + 3de7e8f commit 79d37f9

File tree

45 files changed

+798
-206
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+798
-206
lines changed

.github/workflows/TestCosmos.yaml

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
name: Test Cosmos
2+
3+
on:
4+
pull_request:
5+
branches:
6+
- master
7+
8+
jobs:
9+
build:
10+
runs-on: windows-latest
11+
12+
steps:
13+
- name: Start Cosmos Emulator
14+
run: |
15+
Import-Module "$env:ProgramFiles\Azure Cosmos DB Emulator\PSModules\Microsoft.Azure.CosmosDB.Emulator"
16+
Start-CosmosDbEmulator
17+
18+
- name: Checkout
19+
uses: actions/checkout@v2
20+
21+
- name: Restore
22+
run: restore.cmd
23+
shell: cmd
24+
25+
- name: Test on Cosmos
26+
run: .dotnet\dotnet test test\EFCore.Cosmos.FunctionalTests

eng/Version.Details.xml

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,9 @@
6363
</Dependency>
6464
</ProductDependencies>
6565
<ToolsetDependencies>
66-
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.19608.1">
66+
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="5.0.0-beta.19615.1">
6767
<Uri>https://github.com/dotnet/arcade</Uri>
68-
<Sha>71ce4c736b882e6112b395a0e92313be5dcb4328</Sha>
68+
<Sha>77698ebba1ab096ad9580a5d9ebefe0499ba00ce</Sha>
6969
</Dependency>
7070
</ToolsetDependencies>
7171
</Dependencies>

eng/common/tools.ps1

+25-3
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ function Exec-Process([string]$command, [string]$commandArgs) {
9898
}
9999
}
100100

101-
function InitializeDotNetCli([bool]$install) {
101+
function InitializeDotNetCli([bool]$install, [bool]$createSdkLocationFile) {
102102
if (Test-Path variable:global:_DotNetInstallDir) {
103103
return $global:_DotNetInstallDir
104104
}
@@ -146,6 +146,22 @@ function InitializeDotNetCli([bool]$install) {
146146
}
147147

148148
$env:DOTNET_INSTALL_DIR = $dotnetRoot
149+
150+
if ($createSdkLocationFile) {
151+
# Create a temporary file under the toolset dir and rename it to sdk.txt to avoid races.
152+
do {
153+
$sdkCacheFileTemp = Join-Path $ToolsetDir $([System.IO.Path]::GetRandomFileName())
154+
}
155+
until (!(Test-Path $sdkCacheFileTemp))
156+
Set-Content -Path $sdkCacheFileTemp -Value $dotnetRoot
157+
158+
try {
159+
Rename-Item -Force -Path $sdkCacheFileTemp 'sdk.txt'
160+
} catch {
161+
# Somebody beat us
162+
Remove-Item -Path $sdkCacheFileTemp
163+
}
164+
}
149165
}
150166

151167
# Add dotnet to PATH. This prevents any bare invocation of dotnet in custom
@@ -216,7 +232,10 @@ function InstallDotNet([string] $dotnetRoot,
216232
}
217233
catch {
218234
Write-PipelineTelemetryError -Category 'InitializeToolset' -Message "Failed to install dotnet runtime '$runtime' from custom location '$runtimeSourceFeed'."
235+
ExitWithExitCode 1
219236
}
237+
} else {
238+
ExitWithExitCode 1
220239
}
221240
}
222241
}
@@ -274,8 +293,11 @@ function InitializeVisualStudioMSBuild([bool]$install, [object]$vsRequirements =
274293
$vsMajorVersion = $vsMinVersion.Major
275294
$xcopyMSBuildVersion = "$vsMajorVersion.$($vsMinVersion.Minor).0-alpha"
276295
}
277-
278-
$vsInstallDir = InitializeXCopyMSBuild $xcopyMSBuildVersion $install
296+
297+
$vsInstallDir = $null
298+
if ($xcopyMSBuildVersion.Trim() -ine "none") {
299+
$vsInstallDir = InitializeXCopyMSBuild $xcopyMSBuildVersion $install
300+
}
279301
if ($vsInstallDir -eq $null) {
280302
throw 'Unable to find Visual Studio that has required version and components installed'
281303
}

eng/common/tools.sh

+2
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,8 @@ function InstallDotNet {
211211
Write-PipelineTelemetryError -category 'InitializeToolset' "Failed to install dotnet SDK from custom location '$runtimeSourceFeed' (exit code '$exit_code')."
212212
ExitWithExitCode $exit_code
213213
}
214+
else
215+
ExitWithExitCode $exit_code
214216
fi
215217
fi
216218
}

global.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@
1212
"version": "3.1.100"
1313
},
1414
"msbuild-sdks": {
15-
"Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.19608.1"
15+
"Microsoft.DotNet.Arcade.Sdk": "5.0.0-beta.19615.1"
1616
}
1717
}

src/EFCore.Cosmos/Query/Internal/ContainsTranslator.cs

+12-5
Original file line numberDiff line numberDiff line change
@@ -39,20 +39,27 @@ public ContainsTranslator([NotNull] ISqlExpressionFactory sqlExpressionFactory)
3939
public virtual SqlExpression Translate(SqlExpression instance, MethodInfo method, IReadOnlyList<SqlExpression> arguments)
4040
{
4141
if (method.IsGenericMethod
42-
&& method.GetGenericMethodDefinition().Equals(EnumerableMethods.Contains))
42+
&& method.GetGenericMethodDefinition().Equals(EnumerableMethods.Contains)
43+
&& ValidateValues(arguments[0]))
4344
{
4445
return _sqlExpressionFactory.In(arguments[1], arguments[0], false);
4546
}
4647

47-
if ((method.DeclaringType.GetInterfaces().Contains(typeof(IList))
48-
|| method.DeclaringType.IsGenericType
49-
&& method.DeclaringType.GetGenericTypeDefinition() == typeof(ICollection<>))
50-
&& string.Equals(method.Name, nameof(IList.Contains)))
48+
if (method.Name == nameof(IList.Contains)
49+
&& arguments.Count == 1
50+
&& method.DeclaringType.GetInterfaces().Append(method.DeclaringType).Any(
51+
t => t == typeof(IList)
52+
|| (t.IsGenericType
53+
&& t.GetGenericTypeDefinition() == typeof(ICollection<>)))
54+
&& ValidateValues(instance))
5155
{
5256
return _sqlExpressionFactory.In(arguments[0], instance, false);
5357
}
5458

5559
return null;
5660
}
61+
62+
private bool ValidateValues(SqlExpression values)
63+
=> values is SqlConstantExpression || values is SqlParameterExpression;
5764
}
5865
}

src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.QueryingEnumerable.cs

+47-25
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,25 @@
44
using System;
55
using System.Collections;
66
using System.Collections.Generic;
7+
using System.Text;
78
using System.Threading;
89
using System.Threading.Tasks;
10+
using Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal;
911
using Microsoft.EntityFrameworkCore.Diagnostics;
1012
using Microsoft.EntityFrameworkCore.Query;
1113
using Newtonsoft.Json.Linq;
1214

1315
namespace Microsoft.EntityFrameworkCore.Cosmos.Query.Internal
1416
{
17+
/// <summary>
18+
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
19+
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
20+
/// any release. You should only use it directly in your code with extreme caution and knowing that
21+
/// doing so can result in application failures when updating to a new Entity Framework Core release.
22+
/// </summary>
1523
public partial class CosmosShapedQueryCompilingExpressionVisitor
1624
{
17-
private sealed class QueryingEnumerable<T> : IEnumerable<T>, IAsyncEnumerable<T>
25+
private sealed class QueryingEnumerable<T> : IEnumerable<T>, IAsyncEnumerable<T>, IQueryingEnumerable
1826
{
1927
private readonly CosmosQueryContext _cosmosQueryContext;
2028
private readonly ISqlExpressionFactory _sqlExpressionFactory;
@@ -48,26 +56,44 @@ public IAsyncEnumerator<T> GetAsyncEnumerator(CancellationToken cancellationToke
4856
public IEnumerator<T> GetEnumerator() => new Enumerator(this);
4957
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
5058

59+
private CosmosSqlQuery GenerateQuery()
60+
=> _querySqlGeneratorFactory.Create().GetSqlQuery(
61+
(SelectExpression)new InExpressionValuesExpandingExpressionVisitor(
62+
_sqlExpressionFactory,
63+
_cosmosQueryContext.ParameterValues)
64+
.Visit(_selectExpression),
65+
_cosmosQueryContext.ParameterValues);
66+
67+
public string ToQueryString()
68+
{
69+
var sqlQuery = GenerateQuery();
70+
if (sqlQuery.Parameters.Count == 0)
71+
{
72+
return sqlQuery.Query;
73+
}
74+
75+
var builder = new StringBuilder();
76+
foreach (var parameter in sqlQuery.Parameters)
77+
{
78+
builder
79+
.Append("-- ")
80+
.Append(parameter.Name)
81+
.Append("='")
82+
.Append(parameter.Value)
83+
.AppendLine("'");
84+
}
85+
86+
return builder.Append(sqlQuery.Query).ToString();
87+
}
88+
5189
private sealed class Enumerator : IEnumerator<T>
5290
{
91+
private readonly QueryingEnumerable<T> _queryingEnumerable;
5392
private IEnumerator<JObject> _enumerator;
54-
private readonly CosmosQueryContext _cosmosQueryContext;
55-
private readonly SelectExpression _selectExpression;
56-
private readonly Func<QueryContext, JObject, T> _shaper;
57-
private readonly ISqlExpressionFactory _sqlExpressionFactory;
58-
private readonly IQuerySqlGeneratorFactory _querySqlGeneratorFactory;
59-
private readonly Type _contextType;
60-
private readonly IDiagnosticsLogger<DbLoggerCategory.Query> _logger;
6193

6294
public Enumerator(QueryingEnumerable<T> queryingEnumerable)
6395
{
64-
_cosmosQueryContext = queryingEnumerable._cosmosQueryContext;
65-
_shaper = queryingEnumerable._shaper;
66-
_selectExpression = queryingEnumerable._selectExpression;
67-
_sqlExpressionFactory = queryingEnumerable._sqlExpressionFactory;
68-
_querySqlGeneratorFactory = queryingEnumerable._querySqlGeneratorFactory;
69-
_contextType = queryingEnumerable._contextType;
70-
_logger = queryingEnumerable._logger;
96+
_queryingEnumerable = queryingEnumerable;
7197
}
7298

7399
public T Current { get; private set; }
@@ -78,19 +104,15 @@ public bool MoveNext()
78104
{
79105
try
80106
{
81-
using (_cosmosQueryContext.ConcurrencyDetector.EnterCriticalSection())
107+
using (_queryingEnumerable._cosmosQueryContext.ConcurrencyDetector.EnterCriticalSection())
82108
{
83109
if (_enumerator == null)
84110
{
85-
var selectExpression = (SelectExpression)new InExpressionValuesExpandingExpressionVisitor(
86-
_sqlExpressionFactory, _cosmosQueryContext.ParameterValues).Visit(_selectExpression);
87-
88-
var sqlQuery = _querySqlGeneratorFactory.Create().GetSqlQuery(
89-
selectExpression, _cosmosQueryContext.ParameterValues);
111+
var sqlQuery = _queryingEnumerable.GenerateQuery();
90112

91-
_enumerator = _cosmosQueryContext.CosmosClient
113+
_enumerator = _queryingEnumerable._cosmosQueryContext.CosmosClient
92114
.ExecuteSqlQuery(
93-
_selectExpression.Container,
115+
_queryingEnumerable._selectExpression.Container,
94116
sqlQuery)
95117
.GetEnumerator();
96118
}
@@ -99,15 +121,15 @@ public bool MoveNext()
99121

100122
Current
101123
= hasNext
102-
? _shaper(_cosmosQueryContext, _enumerator.Current)
124+
? _queryingEnumerable._shaper(_queryingEnumerable._cosmosQueryContext, _enumerator.Current)
103125
: default;
104126

105127
return hasNext;
106128
}
107129
}
108130
catch (Exception exception)
109131
{
110-
_logger.QueryIterationFailed(_contextType, exception);
132+
_queryingEnumerable._logger.QueryIterationFailed(_queryingEnumerable._contextType, exception);
111133

112134
throw;
113135
}

src/EFCore.Cosmos/Query/Internal/SqlExpressionFactory.cs

+6-7
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,10 @@ public SqlExpressionFactory([NotNull] ITypeMappingSource typeMappingSource)
4646
/// </summary>
4747
public virtual SqlExpression ApplyDefaultTypeMapping(SqlExpression sqlExpression)
4848
{
49-
if (sqlExpression == null
50-
|| sqlExpression.TypeMapping != null)
51-
{
52-
return sqlExpression;
53-
}
54-
55-
return ApplyTypeMapping(sqlExpression, _typeMappingSource.FindMapping(sqlExpression.Type));
49+
return sqlExpression == null
50+
|| sqlExpression.TypeMapping != null
51+
? sqlExpression
52+
: ApplyTypeMapping(sqlExpression, _typeMappingSource.FindMapping(sqlExpression.Type));
5653
}
5754

5855
/// <summary>
@@ -69,7 +66,9 @@ public virtual SqlExpression ApplyTypeMapping(SqlExpression sqlExpression, CoreT
6966
return sqlExpression;
7067
}
7168

69+
#pragma warning disable IDE0066 // Convert switch statement to expression
7270
switch (sqlExpression)
71+
#pragma warning restore IDE0066 // Convert switch statement to expression
7372
{
7473
case SqlConditionalExpression sqlConditionalExpression:
7574
return ApplyTypeMappingOnSqlConditional(sqlConditionalExpression, typeMapping);

src/EFCore.InMemory/Properties/InMemoryStrings.Designer.cs

+7-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)