Skip to content

Commit efbc08b

Browse files
[rc2] Fix Cosmos enum discriminator handling (#36770)
Fixes #36329 Fixes #34852 Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com>
1 parent 38a40a6 commit efbc08b

File tree

2 files changed

+83
-2
lines changed

2 files changed

+83
-2
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ protected override Expression VisitExtension(Expression node)
193193
if (_discriminatorHandled
194194
&& scalarAccessExpression.PropertyName == _discriminatorJsonPropertyName)
195195
{
196-
var comparer = _entityType.FindDiscriminatorProperty()!.GetProviderValueComparer();
196+
var comparer = _entityType.FindDiscriminatorProperty()!.GetValueComparer();
197197
var discriminatorValues = _entityType.GetDerivedTypesInclusive().Select(e => e.GetDiscriminatorValue()).ToList();
198198
if (discriminatorValues.Count == sqlExpressions.Length)
199199
{
@@ -272,7 +272,7 @@ void ProcessPropertyComparison(string propertyName, SqlExpression propertyValue,
272272
&& propertyValue is SqlConstantExpression { Value: { } specifiedDiscriminatorValue }
273273
&& _entityType.FindDiscriminatorProperty() is { } discriminatorProperty
274274
&& _entityType.GetDiscriminatorValue() is { } entityDiscriminatorValue
275-
&& discriminatorProperty.GetProviderValueComparer().Equals(specifiedDiscriminatorValue, entityDiscriminatorValue))
275+
&& discriminatorProperty.GetValueComparer().Equals(specifiedDiscriminatorValue, entityDiscriminatorValue))
276276
{
277277
// This is the case where there is a single leaf node with a discriminator value. We always know this value,
278278
// so the query never needs to drop out of ReadItem because of it.

test/EFCore.Cosmos.FunctionalTests/Query/AdHocMiscellaneousQueryCosmosTest.cs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.ComponentModel.DataAnnotations.Schema;
55
using Microsoft.EntityFrameworkCore.Cosmos.Storage.Internal;
6+
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
67

78
namespace Microsoft.EntityFrameworkCore.Query;
89

@@ -305,6 +306,86 @@ public class Product
305306

306307
#endregion 35094
307308

309+
#region 36329
310+
311+
[ConditionalFact]
312+
public virtual async Task Enum_discriminator_with_value_converter_on_derived_dbset()
313+
{
314+
var contextFactory = await InitializeAsync<EnumDiscriminatorContext36329>(
315+
onModelCreating: OnModelCreating36329,
316+
seed: Seed36329);
317+
318+
await using var context = contextFactory.CreateContext();
319+
320+
// This should not throw an InvalidCastException
321+
var dog = await context.Dogs.SingleAsync(x => x.Id == "123");
322+
Assert.Equal("Rover", dog.Name);
323+
Assert.Equal(PetType36329.Dog, dog.PetType);
324+
}
325+
326+
public void OnModelCreating36329(ModelBuilder modelBuilder)
327+
{
328+
modelBuilder.Entity<Pet36329>()
329+
.ToContainer(nameof(Pet36329))
330+
.HasPartitionKey(x => x.Id)
331+
.HasKey(x => x.Id);
332+
333+
modelBuilder.Entity<Pet36329>().Property(e => e.PetType)
334+
.HasConversion(new EnumToStringConverter<PetType36329>());
335+
336+
modelBuilder.Entity<Pet36329>()
337+
.HasDiscriminator(x => x.PetType)
338+
.HasValue<Dog36329>(PetType36329.Dog);
339+
340+
modelBuilder.Entity<Dog36329>()
341+
.HasBaseType<Pet36329>();
342+
}
343+
344+
protected async Task Seed36329(EnumDiscriminatorContext36329 context)
345+
{
346+
var dog = new Dog36329
347+
{
348+
Id = "123",
349+
Name = "Rover",
350+
PetType = PetType36329.Dog,
351+
DogProperty = "test"
352+
};
353+
354+
await context.Dogs.AddAsync(dog);
355+
await context.SaveChangesAsync();
356+
}
357+
358+
public class EnumDiscriminatorContext36329 : DbContext
359+
{
360+
public EnumDiscriminatorContext36329(DbContextOptions options)
361+
: base(options)
362+
{
363+
}
364+
365+
public DbSet<Dog36329> Dogs { get; set; }
366+
public DbSet<Pet36329> Pets { get; set; }
367+
}
368+
369+
public abstract record Pet36329
370+
{
371+
public string Id { get; set; }
372+
public PetType36329 PetType { get; set; }
373+
public string Name { get; set; }
374+
}
375+
376+
public record Dog36329 : Pet36329
377+
{
378+
public string DogProperty { get; set; }
379+
}
380+
381+
public enum PetType36329
382+
{
383+
Dog,
384+
Cat
385+
}
386+
387+
#endregion 36329
388+
308389
protected override string StoreName
309390
=> "AdHocMiscellaneousQueryTests";
310391

0 commit comments

Comments
 (0)