Skip to content

Commit d147e9a

Browse files
authored
Query: Cosmos: Generate enum literal/parameter correctly (#23448)
Resolves #20404
1 parent 312867c commit d147e9a

File tree

4 files changed

+42
-50
lines changed

4 files changed

+42
-50
lines changed

Diff for: src/EFCore.Cosmos/Query/Internal/QuerySqlGenerator.cs

+15
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,12 @@ protected override Expression VisitSqlConstant(SqlConstantExpression sqlConstant
341341

342342
private JToken GenerateJToken(object value, CoreTypeMapping typeMapping)
343343
{
344+
if (!(AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue20404", out var enabled)
345+
&& enabled))
346+
{
347+
value = ConvertUnderlyingEnumValueToEnum(value, typeMapping.ClrType);
348+
}
349+
344350
var converter = typeMapping.Converter;
345351
if (converter != null)
346352
{
@@ -355,6 +361,15 @@ private JToken GenerateJToken(object value, CoreTypeMapping typeMapping)
355361
return (value as JToken) ?? JToken.FromObject(value, CosmosClientWrapper.Serializer);
356362
}
357363

364+
// Enum when compared to constant will always have value of integral type
365+
// when enum would contain convert node. We remove the convert node but we also
366+
// need to convert the integral value to enum value.
367+
// This allows us to use converter on enum value or print enum value directly if supported by provider
368+
private object ConvertUnderlyingEnumValueToEnum(object value, Type clrType)
369+
=> value?.GetType().IsInteger() == true && clrType.UnwrapNullableType().IsEnum
370+
? Enum.ToObject(clrType.UnwrapNullableType(), value)
371+
: value;
372+
358373
/// <summary>
359374
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
360375
/// the same compatibility standards as public APIs. It may be changed or removed without notice in

Diff for: test/EFCore.Cosmos.FunctionalTests/BuiltInDataTypesCosmosTest.cs

+1-25
Original file line numberDiff line numberDiff line change
@@ -30,30 +30,6 @@ public override Task Can_filter_projection_with_captured_enum_variable(bool asyn
3030
return base.Can_filter_projection_with_captured_enum_variable(async);
3131
}
3232

33-
[ConditionalFact(Skip = "Issue #16919")]
34-
public override void Can_query_using_any_data_type()
35-
{
36-
base.Can_query_using_any_data_type();
37-
}
38-
39-
[ConditionalFact(Skip = "Issue #16919")]
40-
public override void Can_query_using_any_data_type_nullable_shadow()
41-
{
42-
base.Can_query_using_any_data_type_nullable_shadow();
43-
}
44-
45-
[ConditionalFact(Skip = "Issue #16919")]
46-
public override void Can_query_using_any_data_type_shadow()
47-
{
48-
base.Can_query_using_any_data_type_shadow();
49-
}
50-
51-
[ConditionalFact(Skip = "Issue #16919")]
52-
public override void Can_query_using_any_nullable_data_type()
53-
{
54-
base.Can_query_using_any_nullable_data_type();
55-
}
56-
5733
[ConditionalFact(Skip = "Issue #16919")]
5834
public override void Can_query_using_any_nullable_data_type_as_literal()
5935
{
@@ -66,7 +42,7 @@ public override void Can_query_with_null_parameters_using_any_nullable_data_type
6642
base.Can_query_with_null_parameters_using_any_nullable_data_type();
6743
}
6844

69-
[ConditionalFact(Skip = "Issue #16919")]
45+
[ConditionalFact(Skip = "Issue #16920")]
7046
public override void Can_insert_and_read_back_with_string_key()
7147
{
7248
base.Can_insert_and_read_back_with_string_key();

Diff for: test/EFCore.Cosmos.FunctionalTests/CustomConvertersCosmosTest.cs

+1-25
Original file line numberDiff line numberDiff line change
@@ -35,30 +35,6 @@ public override Task Can_filter_projection_with_captured_enum_variable(bool asyn
3535
return base.Can_filter_projection_with_captured_enum_variable(async);
3636
}
3737

38-
[ConditionalFact(Skip = "Issue #16919")]
39-
public override void Can_query_using_any_data_type()
40-
{
41-
base.Can_query_using_any_data_type();
42-
}
43-
44-
[ConditionalFact(Skip = "Issue #16919")]
45-
public override void Can_query_using_any_data_type_nullable_shadow()
46-
{
47-
base.Can_query_using_any_data_type_nullable_shadow();
48-
}
49-
50-
[ConditionalFact(Skip = "Issue #16919")]
51-
public override void Can_query_using_any_data_type_shadow()
52-
{
53-
base.Can_query_using_any_data_type_shadow();
54-
}
55-
56-
[ConditionalFact(Skip = "Issue #16919")]
57-
public override void Can_query_using_any_nullable_data_type()
58-
{
59-
base.Can_query_using_any_nullable_data_type();
60-
}
61-
6238
[ConditionalFact(Skip = "Issue #16919")]
6339
public override void Can_query_using_any_nullable_data_type_as_literal()
6440
{
@@ -71,7 +47,7 @@ public override void Can_query_with_null_parameters_using_any_nullable_data_type
7147
base.Can_query_with_null_parameters_using_any_nullable_data_type();
7248
}
7349

74-
[ConditionalFact(Skip = "Issue #16919")]
50+
[ConditionalFact(Skip = "Issue #16920")]
7551
public override void Can_insert_and_read_back_with_string_key()
7652
{
7753
base.Can_insert_and_read_back_with_string_key();

Diff for: test/EFCore.Specification.Tests/BuiltInDataTypesTestBase.cs

+25
Original file line numberDiff line numberDiff line change
@@ -2015,6 +2015,31 @@ public virtual void Can_read_back_bool_mapped_as_int_through_navigation()
20152015
}
20162016
}
20172017

2018+
[ConditionalFact]
2019+
public virtual void Can_compare_enum_to_constant()
2020+
{
2021+
using var context = CreateContext();
2022+
var query = context.Set<AnimalIdentification>()
2023+
.Where(a => a.Method == IdentificationMethod.EarTag)
2024+
.ToList();
2025+
2026+
var result = Assert.Single(query);
2027+
Assert.Equal(IdentificationMethod.EarTag, result.Method);
2028+
}
2029+
2030+
[ConditionalFact]
2031+
public virtual void Can_compare_enum_to_parameter()
2032+
{
2033+
var method = IdentificationMethod.EarTag;
2034+
using var context = CreateContext();
2035+
var query = context.Set<AnimalIdentification>()
2036+
.Where(a => a.Method == method)
2037+
.ToList();
2038+
2039+
var result = Assert.Single(query);
2040+
Assert.Equal(IdentificationMethod.EarTag, result.Method);
2041+
}
2042+
20182043
public abstract class BuiltInDataTypesFixtureBase : SharedStoreFixtureBase<PoolableDbContext>
20192044
{
20202045
protected override string StoreName { get; } = "BuiltInDataTypes";

0 commit comments

Comments
 (0)