From 4034ebb784e5a86947b63f47364312459f480510 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Jun 2026 17:22:58 +0000 Subject: [PATCH 01/23] Initial plan From 5df419dc55a6500f31481343782a508f24af2058 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Jun 2026 17:35:19 +0000 Subject: [PATCH 02/23] Sanitize lifted constant variable names in precompiled query generation + test Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../Internal/PrecompiledQueryCodeGenerator.cs | 48 +++++++++++++++++-- ...AdHocPrecompiledQueryRelationalTestBase.cs | 29 +++++++++++ 2 files changed, 73 insertions(+), 4 deletions(-) diff --git a/src/EFCore.Design/Query/Internal/PrecompiledQueryCodeGenerator.cs b/src/EFCore.Design/Query/Internal/PrecompiledQueryCodeGenerator.cs index fa488ff6f90..e04490d4daa 100644 --- a/src/EFCore.Design/Query/Internal/PrecompiledQueryCodeGenerator.cs +++ b/src/EFCore.Design/Query/Internal/PrecompiledQueryCodeGenerator.cs @@ -975,12 +975,52 @@ private void GenerateQueryExecutor( var queryExecutorAfterLiftingExpression = _liftableConstantProcessor.LiftConstants(queryExecutor, materializerLiftableConstantContext, variableNames); - foreach (var liftedConstant in _liftableConstantProcessor.LiftedConstants) + // Lifted constant variable names are partly derived from model metadata (e.g. property names), which may not be valid C# + // identifiers (shadow properties can be given arbitrary names). Sanitize any such names and replace the corresponding + // parameters across all the lifted constant expressions and the query executor. + var liftedConstants = _liftableConstantProcessor.LiftedConstants; + var sanitizedNames = new string[liftedConstants.Count]; + var liftedConstantExpressions = new Expression[liftedConstants.Count]; + List? originalParameters = null; + List? sanitizedParameters = null; + for (var i = 0; i < liftedConstants.Count; i++) + { + var (parameter, expression) = liftedConstants[i]; + liftedConstantExpressions[i] = expression; + + var sanitizedName = SanitizeIdentifierName(parameter.Name ?? "unknown"); + if (sanitizedName != parameter.Name) + { + var baseName = sanitizedName; + for (var j = 0; variableNames.Contains(sanitizedName); j++) + { + sanitizedName = baseName + j; + } + + (originalParameters ??= []).Add(parameter); + (sanitizedParameters ??= []).Add(Expression.Parameter(parameter.Type, sanitizedName)); + } + + variableNames.Add(sanitizedName); + sanitizedNames[i] = sanitizedName; + } + + if (originalParameters is not null) + { + var replacer = new ReplacingExpressionVisitor(originalParameters, sanitizedParameters!); + queryExecutorAfterLiftingExpression = replacer.Visit(queryExecutorAfterLiftingExpression); + + for (var i = 0; i < liftedConstantExpressions.Length; i++) + { + liftedConstantExpressions[i] = replacer.Visit(liftedConstantExpressions[i]); + } + } + + for (var i = 0; i < liftedConstants.Count; i++) { var variableValueSyntax = _linqToCSharpTranslator.TranslateExpression( - liftedConstant.Expression, _constantReplacements, _memberAccessReplacements, namespaces, unsafeAccessors); - // code.AppendLine($"{liftedConstant.Parameter.Type.Name} {liftedConstant.Parameter.Name} = {variableValueSyntax.NormalizeWhitespace().ToFullString()};"); - code.AppendLine($"var {liftedConstant.Parameter.Name} = {variableValueSyntax.NormalizeWhitespace().ToFullString()};"); + liftedConstantExpressions[i], _constantReplacements, _memberAccessReplacements, namespaces, unsafeAccessors); + code.AppendLine($"var {sanitizedNames[i]} = {variableValueSyntax.NormalizeWhitespace().ToFullString()};"); } var queryExecutorSyntaxTree = diff --git a/test/EFCore.Relational.Specification.Tests/Query/AdHocPrecompiledQueryRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/AdHocPrecompiledQueryRelationalTestBase.cs index 865ab6f8b86..79fba24c6cf 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/AdHocPrecompiledQueryRelationalTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/AdHocPrecompiledQueryRelationalTestBase.cs @@ -387,6 +387,35 @@ public class InvalidNameNestedEntity public string Name2 { get; set; } = ""; } + [Fact] + public virtual async Task Invalid_identifier_shadow_property_name() + { + var contextFactory = await InitializeNonSharedTest(); + var options = contextFactory.GetOptions(); + + await Test( + """ +await using var context = new AdHocPrecompiledQueryRelationalTestBase.InvalidShadowNameContext(dbContextOptions); +var entities = await context.Entities.ToListAsync(); +""", + typeof(InvalidShadowNameContext), + options); + } + + public class InvalidShadowNameContext(DbContextOptions options) : DbContext(options) + { + public DbSet Entities { get; set; } = null!; + + protected override void OnModelCreating(ModelBuilder modelBuilder) + => modelBuilder.Entity() + .Property("NOT VALID !!!1").HasConversion(x => 0, x => ""); + } + + public class InvalidShadowNameEntity + { + public Guid Id { get; set; } + } + #endregion protected TestSqlLoggerFactory TestSqlLoggerFactory From 975fab3f0632abf5f00a1daf1c2d20038f8003ca Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Jun 2026 17:50:22 +0000 Subject: [PATCH 03/23] Add warning for shadow property names that are not valid C# identifiers Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- src/EFCore/Diagnostics/CoreEventId.cs | 15 +++++ .../Diagnostics/CoreLoggerExtensions.cs | 34 ++++++++++ src/EFCore/Diagnostics/LoggingDefinitions.cs | 9 +++ src/EFCore/EFCore.baseline.json | 6 ++ src/EFCore/Infrastructure/ModelValidator.cs | 65 +++++++++++++++++++ src/EFCore/Properties/CoreStrings.Designer.cs | 25 +++++++ src/EFCore/Properties/CoreStrings.resx | 4 ++ ...AdHocPrecompiledQueryRelationalTestBase.cs | 3 +- .../Infrastructure/ModelValidatorTest.cs | 34 ++++++++++ 9 files changed, 194 insertions(+), 1 deletion(-) diff --git a/src/EFCore/Diagnostics/CoreEventId.cs b/src/EFCore/Diagnostics/CoreEventId.cs index e68acbf39c9..0a4e8f45bf9 100644 --- a/src/EFCore/Diagnostics/CoreEventId.cs +++ b/src/EFCore/Diagnostics/CoreEventId.cs @@ -129,6 +129,7 @@ private enum Id NoEntityTypeConfigurationsWarning = CoreBaseId + 632, AccidentalEntityType = CoreBaseId + 633, AccidentalComplexPropertyCollection = CoreBaseId + 634, + ShadowPropertyNameNotValidIdentifierWarning = CoreBaseId + 635, // ChangeTracking events DetectChangesStarting = CoreBaseId + 800, @@ -750,6 +751,20 @@ private static EventId MakeModelValidationId(Id id) /// public static readonly EventId AccidentalComplexPropertyCollection = MakeModelValidationId(Id.AccidentalComplexPropertyCollection); + /// + /// A shadow property has a name that is not a valid C# identifier, which prevents it from being used in precompiled queries. + /// + /// + /// + /// This event is in the category. + /// + /// + /// This event uses the payload when used with a . + /// + /// + public static readonly EventId ShadowPropertyNameNotValidIdentifierWarning = + MakeModelValidationId(Id.ShadowPropertyNameNotValidIdentifierWarning); + /// /// The on the collection navigation property was ignored. /// diff --git a/src/EFCore/Diagnostics/CoreLoggerExtensions.cs b/src/EFCore/Diagnostics/CoreLoggerExtensions.cs index 3b76077e276..79e201f5fe1 100644 --- a/src/EFCore/Diagnostics/CoreLoggerExtensions.cs +++ b/src/EFCore/Diagnostics/CoreLoggerExtensions.cs @@ -1432,6 +1432,40 @@ private static string ShadowPropertyCreated(EventDefinitionBase definition, Even return d.GenerateMessage(p.Property.DeclaringType.DisplayName(), p.Property.Name); } + /// + /// Logs for the event. + /// + /// The diagnostics logger to use. + /// The property. + public static void ShadowPropertyNameNotValidIdentifierWarning( + this IDiagnosticsLogger diagnostics, + IProperty property) + { + var definition = CoreResources.LogShadowPropertyNameNotValidIdentifier(diagnostics); + + if (diagnostics.ShouldLog(definition)) + { + definition.Log(diagnostics, property.DeclaringType.DisplayName(), property.Name); + } + + if (diagnostics.NeedsEventData(definition, out var diagnosticSourceEnabled, out var simpleLogEnabled)) + { + var eventData = new PropertyEventData( + definition, + ShadowPropertyNameNotValidIdentifier, + property); + + diagnostics.DispatchEventData(definition, eventData, diagnosticSourceEnabled, simpleLogEnabled); + } + } + + private static string ShadowPropertyNameNotValidIdentifier(EventDefinitionBase definition, EventData payload) + { + var d = (EventDefinition)definition; + var p = (PropertyEventData)payload; + return d.GenerateMessage(p.Property.DeclaringType.DisplayName(), p.Property.Name); + } + /// /// Logs for the event. /// diff --git a/src/EFCore/Diagnostics/LoggingDefinitions.cs b/src/EFCore/Diagnostics/LoggingDefinitions.cs index 55133e004e3..d0498c902df 100644 --- a/src/EFCore/Diagnostics/LoggingDefinitions.cs +++ b/src/EFCore/Diagnostics/LoggingDefinitions.cs @@ -825,4 +825,13 @@ public abstract class LoggingDefinitions /// [EntityFrameworkInternal] public EventDefinitionBase? LogQueryCompilationStarting; + + /// + /// 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 + /// any release. You should only use it directly in your code with extreme caution and knowing that + /// doing so can result in application failures when updating to a new Entity Framework Core release. + /// + [EntityFrameworkInternal] + public EventDefinitionBase? LogShadowPropertyNameNotValidIdentifier; } diff --git a/src/EFCore/EFCore.baseline.json b/src/EFCore/EFCore.baseline.json index 7c9812b71e2..23cc7464300 100644 --- a/src/EFCore/EFCore.baseline.json +++ b/src/EFCore/EFCore.baseline.json @@ -3092,6 +3092,9 @@ { "Member": "static readonly Microsoft.Extensions.Logging.EventId ShadowPropertyCreated" }, + { + "Member": "static readonly Microsoft.Extensions.Logging.EventId ShadowPropertyNameNotValidIdentifierWarning" + }, { "Member": "static readonly Microsoft.Extensions.Logging.EventId SkipCollectionChangeDetected" }, @@ -3355,6 +3358,9 @@ { "Member": "static void ShadowPropertyCreated(this Microsoft.EntityFrameworkCore.Diagnostics.IDiagnosticsLogger diagnostics, Microsoft.EntityFrameworkCore.Metadata.IProperty property);" }, + { + "Member": "static void ShadowPropertyNameNotValidIdentifierWarning(this Microsoft.EntityFrameworkCore.Diagnostics.IDiagnosticsLogger diagnostics, Microsoft.EntityFrameworkCore.Metadata.IProperty property);" + }, { "Member": "static void SkipCollectionChangeDetected(this Microsoft.EntityFrameworkCore.Diagnostics.IDiagnosticsLogger diagnostics, Microsoft.EntityFrameworkCore.ChangeTracking.Internal.InternalEntityEntry internalEntityEntry, Microsoft.EntityFrameworkCore.Metadata.ISkipNavigation navigation, System.Collections.Generic.ISet added, System.Collections.Generic.ISet removed);" }, diff --git a/src/EFCore/Infrastructure/ModelValidator.cs b/src/EFCore/Infrastructure/ModelValidator.cs index e0a7e8f743c..eb30c7968b0 100644 --- a/src/EFCore/Infrastructure/ModelValidator.cs +++ b/src/EFCore/Infrastructure/ModelValidator.cs @@ -3,6 +3,7 @@ using System.Collections; using System.Collections.ObjectModel; +using System.Globalization; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -174,6 +175,70 @@ protected virtual void ValidateProperty( ValidateTypeMapping(property, logger); ValidatePrimitiveCollection(property, logger); ValidateAutoLoaded(property, structuralType, logger); + + if (property.IsShadowProperty() + && !IsValidCSharpIdentifier(property.Name)) + { + logger.ShadowPropertyNameNotValidIdentifierWarning(property); + } + } + + private static bool IsValidCSharpIdentifier(string name) + { + if (string.IsNullOrEmpty(name) + || !IsIdentifierStartCharacter(name[0])) + { + return false; + } + + for (var i = 1; i < name.Length; i++) + { + if (!IsIdentifierPartCharacter(name[i])) + { + return false; + } + } + + return true; + + static bool IsIdentifierStartCharacter(char ch) + => ch < 'a' + ? ch is >= 'A' and (<= 'Z' or '_') + : ch <= 'z' || (ch > '\u007F' && IsLetterChar(CharUnicodeInfo.GetUnicodeCategory(ch))); + + static bool IsIdentifierPartCharacter(char ch) + { + if (ch < 'a') + { + return (ch < 'A' ? ch is >= '0' and <= '9' : ch <= 'Z') || ch == '_'; + } + + if (ch <= 'z') + { + return true; + } + + if (ch <= '\u007F') + { + return false; + } + + var cat = CharUnicodeInfo.GetUnicodeCategory(ch); + return IsLetterChar(cat) + || cat is UnicodeCategory.DecimalDigitNumber + or UnicodeCategory.ConnectorPunctuation + or UnicodeCategory.NonSpacingMark + or UnicodeCategory.SpacingCombiningMark + or UnicodeCategory.Format; + } + + static bool IsLetterChar(UnicodeCategory cat) + => cat is UnicodeCategory.UppercaseLetter + or UnicodeCategory.LowercaseLetter + or UnicodeCategory.TitlecaseLetter + or UnicodeCategory.ModifierLetter + or UnicodeCategory.OtherLetter + or UnicodeCategory.LetterNumber; } /// diff --git a/src/EFCore/Properties/CoreStrings.Designer.cs b/src/EFCore/Properties/CoreStrings.Designer.cs index 186af2df532..d9368ed5897 100644 --- a/src/EFCore/Properties/CoreStrings.Designer.cs +++ b/src/EFCore/Properties/CoreStrings.Designer.cs @@ -5557,6 +5557,31 @@ public static EventDefinition LogShadowPropertyCreated(IDiagnost return (EventDefinition)definition; } + /// + /// The shadow property '{entityType}.{property}' has a name that is not a valid C# identifier. Precompiled queries that use this property will fail to compile. Consider renaming the property to a valid C# identifier. + /// + public static EventDefinition LogShadowPropertyNameNotValidIdentifier(IDiagnosticsLogger logger) + { + var definition = ((LoggingDefinitions)logger.Definitions).LogShadowPropertyNameNotValidIdentifier; + if (definition == null) + { + definition = NonCapturingLazyInitializer.EnsureInitialized( + ref ((LoggingDefinitions)logger.Definitions).LogShadowPropertyNameNotValidIdentifier, + logger, + static logger => new EventDefinition( + logger.Options, + CoreEventId.ShadowPropertyNameNotValidIdentifierWarning, + LogLevel.Warning, + "CoreEventId.ShadowPropertyNameNotValidIdentifierWarning", + level => LoggerMessage.Define( + level, + CoreEventId.ShadowPropertyNameNotValidIdentifierWarning, + _resourceManager.GetString("LogShadowPropertyNameNotValidIdentifier")!))); + } + + return (EventDefinition)definition; + } + /// /// {addedCount} entities were added and {removedCount} entities were removed from skip navigation '{entityType}.{property}'. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see key values. /// diff --git a/src/EFCore/Properties/CoreStrings.resx b/src/EFCore/Properties/CoreStrings.resx index 09ee563d2d1..13f459c928c 100644 --- a/src/EFCore/Properties/CoreStrings.resx +++ b/src/EFCore/Properties/CoreStrings.resx @@ -1230,6 +1230,10 @@ The property '{entityType}.{property}' was created in shadow state because there are no eligible CLR members with a matching name. Debug CoreEventId.ShadowPropertyCreated string string + + The shadow property '{entityType}.{property}' has a name that is not a valid C# identifier. Precompiled queries that use this property will fail to compile. Consider renaming the property to a valid C# identifier. + Warning CoreEventId.ShadowPropertyNameNotValidIdentifierWarning string string + {addedCount} entities were added and {removedCount} entities were removed from skip navigation '{entityType}.{property}'. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see key values. Debug CoreEventId.SkipCollectionChangeDetected int int string string diff --git a/test/EFCore.Relational.Specification.Tests/Query/AdHocPrecompiledQueryRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/AdHocPrecompiledQueryRelationalTestBase.cs index 79fba24c6cf..a36e2612871 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/AdHocPrecompiledQueryRelationalTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/AdHocPrecompiledQueryRelationalTestBase.cs @@ -390,7 +390,8 @@ public class InvalidNameNestedEntity [Fact] public virtual async Task Invalid_identifier_shadow_property_name() { - var contextFactory = await InitializeNonSharedTest(); + var contextFactory = await InitializeNonSharedTest( + onConfiguring: o => o.ConfigureWarnings(w => w.Ignore(CoreEventId.ShadowPropertyNameNotValidIdentifierWarning))); var options = contextFactory.GetOptions(); await Test( diff --git a/test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs b/test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs index 275a48afaea..a0c3b9bb75f 100644 --- a/test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs +++ b/test/EFCore.Tests/Infrastructure/ModelValidatorTest.cs @@ -462,6 +462,40 @@ public virtual void Passes_on_shadow_primary_key_created_by_convention_in_depend .GenerateMessage("A", "Key"), modelBuilder, LogLevel.Debug); } + [Fact] + public virtual void Warns_on_shadow_property_name_that_is_not_a_valid_identifier() + { + var modelBuilder = CreateConventionlessModelBuilder(); + var model = modelBuilder.Model; + + var entityType = model.AddEntityType(typeof(A)); + SetPrimaryKey(entityType); + AddProperties(entityType); + + entityType.AddProperty("NOT VALID !!!1", typeof(string)); + + VerifyWarning( + CoreResources.LogShadowPropertyNameNotValidIdentifier(new TestLogger()) + .GenerateMessage("A", "NOT VALID !!!1"), modelBuilder, LogLevel.Warning); + } + + [Fact] + public virtual void Does_not_warn_on_shadow_property_with_valid_identifier_name() + { + var modelBuilder = CreateConventionlessModelBuilder(); + var model = modelBuilder.Model; + + var entityType = model.AddEntityType(typeof(A)); + SetPrimaryKey(entityType); + AddProperties(entityType); + + entityType.AddProperty("ValidName", typeof(string)); + + VerifyLogDoesNotContain( + CoreResources.LogShadowPropertyNameNotValidIdentifier(new TestLogger()) + .GenerateMessage("A", "ValidName"), modelBuilder); + } + [Fact] // Issue #33484 public virtual void Does_not_log_for_shadow_property_when_creating_indexer_property() { From d83e0d597326d61d7de4113c44881d20e13c6122 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 18 Jun 2026 17:52:02 +0000 Subject: [PATCH 04/23] Document why C# identifier validation is replicated in runtime assembly Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- src/EFCore/Infrastructure/ModelValidator.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/EFCore/Infrastructure/ModelValidator.cs b/src/EFCore/Infrastructure/ModelValidator.cs index eb30c7968b0..303994f2ce8 100644 --- a/src/EFCore/Infrastructure/ModelValidator.cs +++ b/src/EFCore/Infrastructure/ModelValidator.cs @@ -185,6 +185,8 @@ protected virtual void ValidateProperty( private static bool IsValidCSharpIdentifier(string name) { + // This mirrors the Unicode rules used by Roslyn (and CSharpHelper in the Design assembly), replicated here because the + // runtime assembly does not reference Roslyn. if (string.IsNullOrEmpty(name) || !IsIdentifierStartCharacter(name[0])) { From a928c0d389421a3856fc525b42406588d5a76b2e Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Jun 2026 02:29:55 +0000 Subject: [PATCH 05/23] Move sanitization into LiftConstants; simplify identifier check; update warning message Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../Internal/PrecompiledQueryCodeGenerator.cs | 48 ++-------------- src/EFCore/Infrastructure/ModelValidator.cs | 55 +++---------------- src/EFCore/Properties/CoreStrings.Designer.cs | 2 +- src/EFCore/Properties/CoreStrings.resx | 2 +- src/EFCore/Query/LiftableConstantProcessor.cs | 6 +- 5 files changed, 20 insertions(+), 93 deletions(-) diff --git a/src/EFCore.Design/Query/Internal/PrecompiledQueryCodeGenerator.cs b/src/EFCore.Design/Query/Internal/PrecompiledQueryCodeGenerator.cs index e04490d4daa..fa488ff6f90 100644 --- a/src/EFCore.Design/Query/Internal/PrecompiledQueryCodeGenerator.cs +++ b/src/EFCore.Design/Query/Internal/PrecompiledQueryCodeGenerator.cs @@ -975,52 +975,12 @@ private void GenerateQueryExecutor( var queryExecutorAfterLiftingExpression = _liftableConstantProcessor.LiftConstants(queryExecutor, materializerLiftableConstantContext, variableNames); - // Lifted constant variable names are partly derived from model metadata (e.g. property names), which may not be valid C# - // identifiers (shadow properties can be given arbitrary names). Sanitize any such names and replace the corresponding - // parameters across all the lifted constant expressions and the query executor. - var liftedConstants = _liftableConstantProcessor.LiftedConstants; - var sanitizedNames = new string[liftedConstants.Count]; - var liftedConstantExpressions = new Expression[liftedConstants.Count]; - List? originalParameters = null; - List? sanitizedParameters = null; - for (var i = 0; i < liftedConstants.Count; i++) - { - var (parameter, expression) = liftedConstants[i]; - liftedConstantExpressions[i] = expression; - - var sanitizedName = SanitizeIdentifierName(parameter.Name ?? "unknown"); - if (sanitizedName != parameter.Name) - { - var baseName = sanitizedName; - for (var j = 0; variableNames.Contains(sanitizedName); j++) - { - sanitizedName = baseName + j; - } - - (originalParameters ??= []).Add(parameter); - (sanitizedParameters ??= []).Add(Expression.Parameter(parameter.Type, sanitizedName)); - } - - variableNames.Add(sanitizedName); - sanitizedNames[i] = sanitizedName; - } - - if (originalParameters is not null) - { - var replacer = new ReplacingExpressionVisitor(originalParameters, sanitizedParameters!); - queryExecutorAfterLiftingExpression = replacer.Visit(queryExecutorAfterLiftingExpression); - - for (var i = 0; i < liftedConstantExpressions.Length; i++) - { - liftedConstantExpressions[i] = replacer.Visit(liftedConstantExpressions[i]); - } - } - - for (var i = 0; i < liftedConstants.Count; i++) + foreach (var liftedConstant in _liftableConstantProcessor.LiftedConstants) { var variableValueSyntax = _linqToCSharpTranslator.TranslateExpression( - liftedConstantExpressions[i], _constantReplacements, _memberAccessReplacements, namespaces, unsafeAccessors); - code.AppendLine($"var {sanitizedNames[i]} = {variableValueSyntax.NormalizeWhitespace().ToFullString()};"); + liftedConstant.Expression, _constantReplacements, _memberAccessReplacements, namespaces, unsafeAccessors); + // code.AppendLine($"{liftedConstant.Parameter.Type.Name} {liftedConstant.Parameter.Name} = {variableValueSyntax.NormalizeWhitespace().ToFullString()};"); + code.AppendLine($"var {liftedConstant.Parameter.Name} = {variableValueSyntax.NormalizeWhitespace().ToFullString()};"); } var queryExecutorSyntaxTree = diff --git a/src/EFCore/Infrastructure/ModelValidator.cs b/src/EFCore/Infrastructure/ModelValidator.cs index 303994f2ce8..e70bd4c8a54 100644 --- a/src/EFCore/Infrastructure/ModelValidator.cs +++ b/src/EFCore/Infrastructure/ModelValidator.cs @@ -3,7 +3,6 @@ using System.Collections; using System.Collections.ObjectModel; -using System.Globalization; using Microsoft.EntityFrameworkCore.ChangeTracking.Internal; using Microsoft.EntityFrameworkCore.Internal; using Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -177,70 +176,34 @@ protected virtual void ValidateProperty( ValidateAutoLoaded(property, structuralType, logger); if (property.IsShadowProperty() - && !IsValidCSharpIdentifier(property.Name)) + && !IsValidIdentifier(property.Name)) { logger.ShadowPropertyNameNotValidIdentifierWarning(property); } } - private static bool IsValidCSharpIdentifier(string name) + /// + /// Returns if the given name only uses letters, digits and underscores and does not start with a digit; + /// that is, if it can be used as-is as a C# identifier in generated code. + /// + internal static bool IsValidIdentifier(string? name) { - // This mirrors the Unicode rules used by Roslyn (and CSharpHelper in the Design assembly), replicated here because the - // runtime assembly does not reference Roslyn. if (string.IsNullOrEmpty(name) - || !IsIdentifierStartCharacter(name[0])) + || (!char.IsLetter(name[0]) && name[0] != '_')) { return false; } for (var i = 1; i < name.Length; i++) { - if (!IsIdentifierPartCharacter(name[i])) + var ch = name[i]; + if (!char.IsLetter(ch) && !char.IsAsciiDigit(ch) && ch != '_') { return false; } } return true; - - static bool IsIdentifierStartCharacter(char ch) - => ch < 'a' - ? ch is >= 'A' and (<= 'Z' or '_') - : ch <= 'z' || (ch > '\u007F' && IsLetterChar(CharUnicodeInfo.GetUnicodeCategory(ch))); - - static bool IsIdentifierPartCharacter(char ch) - { - if (ch < 'a') - { - return (ch < 'A' ? ch is >= '0' and <= '9' : ch <= 'Z') || ch == '_'; - } - - if (ch <= 'z') - { - return true; - } - - if (ch <= '\u007F') - { - return false; - } - - var cat = CharUnicodeInfo.GetUnicodeCategory(ch); - return IsLetterChar(cat) - || cat is UnicodeCategory.DecimalDigitNumber - or UnicodeCategory.ConnectorPunctuation - or UnicodeCategory.NonSpacingMark - or UnicodeCategory.SpacingCombiningMark - or UnicodeCategory.Format; - } - - static bool IsLetterChar(UnicodeCategory cat) - => cat is UnicodeCategory.UppercaseLetter - or UnicodeCategory.LowercaseLetter - or UnicodeCategory.TitlecaseLetter - or UnicodeCategory.ModifierLetter - or UnicodeCategory.OtherLetter - or UnicodeCategory.LetterNumber; } /// diff --git a/src/EFCore/Properties/CoreStrings.Designer.cs b/src/EFCore/Properties/CoreStrings.Designer.cs index d9368ed5897..8c72415e1ec 100644 --- a/src/EFCore/Properties/CoreStrings.Designer.cs +++ b/src/EFCore/Properties/CoreStrings.Designer.cs @@ -5558,7 +5558,7 @@ public static EventDefinition LogShadowPropertyCreated(IDiagnost } /// - /// The shadow property '{entityType}.{property}' has a name that is not a valid C# identifier. Precompiled queries that use this property will fail to compile. Consider renaming the property to a valid C# identifier. + /// The shadow property '{entityType}.{property}' has a name that is not a valid identifier. This can cause issues in generated code. Consider renaming the property using only numbers, letters and underscore. /// public static EventDefinition LogShadowPropertyNameNotValidIdentifier(IDiagnosticsLogger logger) { diff --git a/src/EFCore/Properties/CoreStrings.resx b/src/EFCore/Properties/CoreStrings.resx index 13f459c928c..8ef2bef77eb 100644 --- a/src/EFCore/Properties/CoreStrings.resx +++ b/src/EFCore/Properties/CoreStrings.resx @@ -1231,7 +1231,7 @@ Debug CoreEventId.ShadowPropertyCreated string string - The shadow property '{entityType}.{property}' has a name that is not a valid C# identifier. Precompiled queries that use this property will fail to compile. Consider renaming the property to a valid C# identifier. + The shadow property '{entityType}.{property}' has a name that is not a valid identifier. This can cause issues in generated code. Consider renaming the property using only numbers, letters and underscore. Warning CoreEventId.ShadowPropertyNameNotValidIdentifierWarning string string diff --git a/src/EFCore/Query/LiftableConstantProcessor.cs b/src/EFCore/Query/LiftableConstantProcessor.cs index 525d460bb1c..80dd5a61aa8 100644 --- a/src/EFCore/Query/LiftableConstantProcessor.cs +++ b/src/EFCore/Query/LiftableConstantProcessor.cs @@ -126,7 +126,11 @@ public virtual Expression LiftConstants(Expression expression, ParameterExpressi continue; } - var name = liftedConstant.Parameter.Name ?? "unknown"; + // Lifted constant variable names are partly derived from model metadata (e.g. property names), which may not be valid C# + // identifiers (shadow properties can be given arbitrary names). Fall back to a generic name in that case. + var name = ModelValidator.IsValidIdentifier(liftedConstant.Parameter.Name) + ? liftedConstant.Parameter.Name! + : "unknown"; var baseName = name; for (var j = 0; variableNames.Contains(name); j++) { From 0e95a844b9b7d4ffb032a4b4a53d7573c54602ec Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Jun 2026 04:42:52 +0000 Subject: [PATCH 06/23] Use strict IsValidIdentifier logic in CSharpHelper identifier char checks Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../Design/Internal/CSharpHelper.cs | 68 +------------------ 1 file changed, 2 insertions(+), 66 deletions(-) diff --git a/src/EFCore.Design/Design/Internal/CSharpHelper.cs b/src/EFCore.Design/Design/Internal/CSharpHelper.cs index c62d8194854..953469b0133 100644 --- a/src/EFCore.Design/Design/Internal/CSharpHelper.cs +++ b/src/EFCore.Design/Design/Internal/CSharpHelper.cs @@ -1633,72 +1633,8 @@ public virtual string Expression( } private static bool IsIdentifierStartCharacter(char ch) - { - if (ch < 'a') - { - return ch is >= 'A' and (<= 'Z' or '_'); - } - - if (ch <= 'z') - { - return true; - } - - return ch > '\u007F' && IsLetterChar(CharUnicodeInfo.GetUnicodeCategory(ch)); - } + => char.IsLetter(ch) || ch == '_'; private static bool IsIdentifierPartCharacter(char ch) - { - if (ch < 'a') - { - return (ch < 'A' - ? ch is >= '0' and <= '9' - : ch <= 'Z') - || ch == '_'; - } - - if (ch <= 'z') - { - return true; - } - - if (ch <= '\u007F') - { - return false; - } - - var cat = CharUnicodeInfo.GetUnicodeCategory(ch); - if (IsLetterChar(cat)) - { - return true; - } - - switch (cat) - { - case UnicodeCategory.DecimalDigitNumber: - case UnicodeCategory.ConnectorPunctuation: - case UnicodeCategory.NonSpacingMark: - case UnicodeCategory.SpacingCombiningMark: - case UnicodeCategory.Format: - return true; - } - - return false; - } - - private static bool IsLetterChar(UnicodeCategory cat) - { - switch (cat) - { - case UnicodeCategory.UppercaseLetter: - case UnicodeCategory.LowercaseLetter: - case UnicodeCategory.TitlecaseLetter: - case UnicodeCategory.ModifierLetter: - case UnicodeCategory.OtherLetter: - case UnicodeCategory.LetterNumber: - return true; - } - - return false; - } + => char.IsLetter(ch) || char.IsAsciiDigit(ch) || ch == '_'; } From eeb2c519fb76afa6f8fd03ea45527f1f8071a15f Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Thu, 18 Jun 2026 23:27:46 -0700 Subject: [PATCH 07/23] Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- src/EFCore/Diagnostics/CoreEventId.cs | 2 +- src/EFCore/Infrastructure/ModelValidator.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/EFCore/Diagnostics/CoreEventId.cs b/src/EFCore/Diagnostics/CoreEventId.cs index 0a4e8f45bf9..8ec0fc0f7fb 100644 --- a/src/EFCore/Diagnostics/CoreEventId.cs +++ b/src/EFCore/Diagnostics/CoreEventId.cs @@ -752,7 +752,7 @@ private static EventId MakeModelValidationId(Id id) public static readonly EventId AccidentalComplexPropertyCollection = MakeModelValidationId(Id.AccidentalComplexPropertyCollection); /// - /// A shadow property has a name that is not a valid C# identifier, which prevents it from being used in precompiled queries. + /// A shadow property has a name that is not a valid identifier, which can cause issues in generated code. /// /// /// diff --git a/src/EFCore/Infrastructure/ModelValidator.cs b/src/EFCore/Infrastructure/ModelValidator.cs index e70bd4c8a54..c3974a1cfc3 100644 --- a/src/EFCore/Infrastructure/ModelValidator.cs +++ b/src/EFCore/Infrastructure/ModelValidator.cs @@ -183,8 +183,8 @@ protected virtual void ValidateProperty( } /// - /// Returns if the given name only uses letters, digits and underscores and does not start with a digit; - /// that is, if it can be used as-is as a C# identifier in generated code. + /// Returns if the given name only uses letters, ASCII digits and underscores and does not start with a digit; + /// that is, if it can be used as-is as an identifier in generated code. /// internal static bool IsValidIdentifier(string? name) { From 1d734842afd181bb8501cf5df5d76c9655648af1 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Jun 2026 06:34:02 +0000 Subject: [PATCH 08/23] Adjust invalid shadow property warning message Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- src/EFCore/Properties/CoreStrings.Designer.cs | 2 +- src/EFCore/Properties/CoreStrings.resx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/EFCore/Properties/CoreStrings.Designer.cs b/src/EFCore/Properties/CoreStrings.Designer.cs index 8c72415e1ec..c2c0a1c764e 100644 --- a/src/EFCore/Properties/CoreStrings.Designer.cs +++ b/src/EFCore/Properties/CoreStrings.Designer.cs @@ -5558,7 +5558,7 @@ public static EventDefinition LogShadowPropertyCreated(IDiagnost } /// - /// The shadow property '{entityType}.{property}' has a name that is not a valid identifier. This can cause issues in generated code. Consider renaming the property using only numbers, letters and underscore. + /// The shadow property '{entityType}.{property}' has a name that is not a valid identifier. This can cause issues in generated code. Consider renaming the property to start with a letter or underscore, and use only letters, digits and underscore. /// public static EventDefinition LogShadowPropertyNameNotValidIdentifier(IDiagnosticsLogger logger) { diff --git a/src/EFCore/Properties/CoreStrings.resx b/src/EFCore/Properties/CoreStrings.resx index 8ef2bef77eb..e50f1964c7e 100644 --- a/src/EFCore/Properties/CoreStrings.resx +++ b/src/EFCore/Properties/CoreStrings.resx @@ -1231,7 +1231,7 @@ Debug CoreEventId.ShadowPropertyCreated string string - The shadow property '{entityType}.{property}' has a name that is not a valid identifier. This can cause issues in generated code. Consider renaming the property using only numbers, letters and underscore. + The shadow property '{entityType}.{property}' has a name that is not a valid identifier. This can cause issues in generated code. Consider renaming the property to start with a letter or underscore, and use only letters, digits and underscore. Warning CoreEventId.ShadowPropertyNameNotValidIdentifierWarning string string From 3a006aaae43673eeccd5a15d0698ad485c622378 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Jun 2026 06:34:29 +0000 Subject: [PATCH 09/23] Polish invalid shadow property warning text Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- src/EFCore/Properties/CoreStrings.Designer.cs | 2 +- src/EFCore/Properties/CoreStrings.resx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/EFCore/Properties/CoreStrings.Designer.cs b/src/EFCore/Properties/CoreStrings.Designer.cs index c2c0a1c764e..1539ef0796a 100644 --- a/src/EFCore/Properties/CoreStrings.Designer.cs +++ b/src/EFCore/Properties/CoreStrings.Designer.cs @@ -5558,7 +5558,7 @@ public static EventDefinition LogShadowPropertyCreated(IDiagnost } /// - /// The shadow property '{entityType}.{property}' has a name that is not a valid identifier. This can cause issues in generated code. Consider renaming the property to start with a letter or underscore, and use only letters, digits and underscore. + /// The shadow property '{entityType}.{property}' has a name that is not a valid identifier. This can cause issues in generated code. Consider renaming the property to start with a letter or underscore, and use only letters, digits, and underscore. /// public static EventDefinition LogShadowPropertyNameNotValidIdentifier(IDiagnosticsLogger logger) { diff --git a/src/EFCore/Properties/CoreStrings.resx b/src/EFCore/Properties/CoreStrings.resx index e50f1964c7e..bc24b148df1 100644 --- a/src/EFCore/Properties/CoreStrings.resx +++ b/src/EFCore/Properties/CoreStrings.resx @@ -1231,7 +1231,7 @@ Debug CoreEventId.ShadowPropertyCreated string string - The shadow property '{entityType}.{property}' has a name that is not a valid identifier. This can cause issues in generated code. Consider renaming the property to start with a letter or underscore, and use only letters, digits and underscore. + The shadow property '{entityType}.{property}' has a name that is not a valid identifier. This can cause issues in generated code. Consider renaming the property to start with a letter or underscore, and use only letters, digits, and underscore. Warning CoreEventId.ShadowPropertyNameNotValidIdentifierWarning string string From 9573291693555102960e8aaf70b6d517c4e395c0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 19 Jun 2026 19:21:28 +0000 Subject: [PATCH 10/23] Adjust invalid shadow property warning wording Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- src/EFCore/Properties/CoreStrings.Designer.cs | 2 +- src/EFCore/Properties/CoreStrings.resx | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/EFCore/Properties/CoreStrings.Designer.cs b/src/EFCore/Properties/CoreStrings.Designer.cs index 1539ef0796a..b7c29e725f2 100644 --- a/src/EFCore/Properties/CoreStrings.Designer.cs +++ b/src/EFCore/Properties/CoreStrings.Designer.cs @@ -5558,7 +5558,7 @@ public static EventDefinition LogShadowPropertyCreated(IDiagnost } /// - /// The shadow property '{entityType}.{property}' has a name that is not a valid identifier. This can cause issues in generated code. Consider renaming the property to start with a letter or underscore, and use only letters, digits, and underscore. + /// The shadow property '{entityType}.{property}' has a name that is not a valid identifier. This can cause issues in generated code. Consider renaming the property to use only letters, digits (except for the first character), and underscore. /// public static EventDefinition LogShadowPropertyNameNotValidIdentifier(IDiagnosticsLogger logger) { diff --git a/src/EFCore/Properties/CoreStrings.resx b/src/EFCore/Properties/CoreStrings.resx index bc24b148df1..0166459de44 100644 --- a/src/EFCore/Properties/CoreStrings.resx +++ b/src/EFCore/Properties/CoreStrings.resx @@ -1231,7 +1231,7 @@ Debug CoreEventId.ShadowPropertyCreated string string - The shadow property '{entityType}.{property}' has a name that is not a valid identifier. This can cause issues in generated code. Consider renaming the property to start with a letter or underscore, and use only letters, digits, and underscore. + The shadow property '{entityType}.{property}' has a name that is not a valid identifier. This can cause issues in generated code. Consider renaming the property to use only letters, digits (except for the first character), and underscore. Warning CoreEventId.ShadowPropertyNameNotValidIdentifierWarning string string From ee5e1f17c9bdfef9a4a4d901d7f1ded58586c657 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Jun 2026 03:09:18 +0000 Subject: [PATCH 11/23] Update Cosmos discriminator shadow property name Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../CosmosDiscriminatorConvention.cs | 14 +++++++---- .../Query/NorthwindQueryCosmosFixture.cs | 23 +++++++++++-------- .../Extensions/CosmosBuilderExtensionsTest.cs | 20 ++++++++++++++-- 3 files changed, 41 insertions(+), 16 deletions(-) diff --git a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs index 2990718e5c0..df9507ee2ef 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; +using Microsoft.EntityFrameworkCore; // ReSharper disable once CheckNamespace namespace Microsoft.EntityFrameworkCore.Metadata.Conventions; @@ -21,6 +22,8 @@ public class CosmosDiscriminatorConvention : IEntityTypeAnnotationChangedConvention, IModelEmbeddedDiscriminatorNameConvention { + private const string DiscriminatorPropertyName = "_type"; + /// /// Creates a new instance of . /// @@ -86,8 +89,9 @@ private static void ProcessEntityType(IConventionEntityTypeBuilder entityTypeBui if (entityType.IsDocumentRoot()) { - entityTypeBuilder.HasDiscriminator(entityType.Model.GetEmbeddedDiscriminatorName(), typeof(string)) - ?.HasValue(entityType, entityType.ShortName()); + var discriminator = entityTypeBuilder.HasDiscriminator(DiscriminatorPropertyName, typeof(string)); + discriminator?.EntityType.FindDiscriminatorProperty()?.Builder.ToJsonProperty(entityType.Model.GetEmbeddedDiscriminatorName()); + discriminator?.HasValue(entityType, entityType.ShortName()); } else { @@ -125,7 +129,8 @@ public override void ProcessEntityTypeBaseTypeChanged( { if (entityType.IsDocumentRoot()) { - entityTypeBuilder.HasDiscriminator(entityType.Model.GetEmbeddedDiscriminatorName(), typeof(string)); + var discriminator = entityTypeBuilder.HasDiscriminator(DiscriminatorPropertyName, typeof(string)); + discriminator?.EntityType.FindDiscriminatorProperty()?.Builder.ToJsonProperty(entityType.Model.GetEmbeddedDiscriminatorName()); } } else @@ -137,9 +142,10 @@ public override void ProcessEntityTypeBaseTypeChanged( return; } - var discriminator = rootType.Builder.HasDiscriminator(entityType.Model.GetEmbeddedDiscriminatorName(), typeof(string)); + var discriminator = rootType.Builder.HasDiscriminator(DiscriminatorPropertyName, typeof(string)); if (discriminator != null) { + discriminator.EntityType.FindDiscriminatorProperty()?.Builder.ToJsonProperty(entityType.Model.GetEmbeddedDiscriminatorName()); SetDefaultDiscriminatorValues(entityTypeBuilder.Metadata.GetDerivedTypesInclusive(), discriminator); } } diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindQueryCosmosFixture.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindQueryCosmosFixture.cs index fd75389851b..1e8f5bb69b8 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindQueryCosmosFixture.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindQueryCosmosFixture.cs @@ -52,32 +52,35 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con .HasRootDiscriminatorInJsonId() .ToContainer("ProductsAndOrders"); - modelBuilder.Entity() - .ToContainer("ProductsAndOrders") - .HasRootDiscriminatorInJsonId() - .HasDiscriminator("$type").HasValue("Order"); + modelBuilder.Entity().ToContainer("ProductsAndOrders").HasRootDiscriminatorInJsonId(); + modelBuilder.Entity().HasDiscriminator("_type").HasValue("Order"); + modelBuilder.Entity().Property("_type").ToJsonProperty("$type"); modelBuilder .Entity() .ToContainer("ProductsAndOrders") - .HasRootDiscriminatorInJsonId() - .HasDiscriminator("$type").HasValue("Product"); + .HasRootDiscriminatorInJsonId(); + modelBuilder.Entity().HasDiscriminator("_type").HasValue("Product"); + modelBuilder.Entity().Property("_type").ToJsonProperty("$type"); modelBuilder .Entity() .ToContainer("ProductsAndOrders") - .HasRootDiscriminatorInJsonId() - .HasDiscriminator("$type").HasValue("ProductView"); + .HasRootDiscriminatorInJsonId(); + modelBuilder.Entity().HasDiscriminator("_type").HasValue("ProductView"); + modelBuilder.Entity().Property("_type").ToJsonProperty("$type"); modelBuilder .Entity() .ToContainer("Customers") - .HasDiscriminator("$type").HasValue("Customer"); + .HasDiscriminator("_type").HasValue("Customer"); + modelBuilder.Entity().Property("_type").ToJsonProperty("$type"); modelBuilder .Entity() .ToContainer("Customers") - .HasDiscriminator("$type").HasValue("Customer"); + .HasDiscriminator("_type").HasValue("Customer"); + modelBuilder.Entity().Property("_type").ToJsonProperty("$type"); modelBuilder.Entity().Metadata.RemoveIndex( modelBuilder.Entity().Property(e => e.City).Metadata.GetContainingIndexes().Single()); diff --git a/test/EFCore.Cosmos.Tests/Extensions/CosmosBuilderExtensionsTest.cs b/test/EFCore.Cosmos.Tests/Extensions/CosmosBuilderExtensionsTest.cs index 193fe2084af..49945ead2d9 100644 --- a/test/EFCore.Cosmos.Tests/Extensions/CosmosBuilderExtensionsTest.cs +++ b/test/EFCore.Cosmos.Tests/Extensions/CosmosBuilderExtensionsTest.cs @@ -135,7 +135,8 @@ public void Default_discriminator_can_be_removed() var entityType = modelBuilder.Model.FindEntityType(typeof(Customer))!; - Assert.Equal("$type", entityType.FindDiscriminatorProperty()!.Name); + Assert.Equal("_type", entityType.FindDiscriminatorProperty()!.Name); + Assert.Equal("$type", entityType.FindDiscriminatorProperty()!.GetJsonPropertyName()); Assert.Equal(nameof(Customer), entityType.GetDiscriminatorValue()); modelBuilder.Entity().HasNoDiscriminator(); @@ -145,7 +146,8 @@ public void Default_discriminator_can_be_removed() modelBuilder.Entity().HasBaseType(); - Assert.Equal("$type", entityType.FindDiscriminatorProperty()!.Name); + Assert.Equal("_type", entityType.FindDiscriminatorProperty()!.Name); + Assert.Equal("$type", entityType.FindDiscriminatorProperty()!.GetJsonPropertyName()); Assert.Equal(nameof(Customer), entityType.GetDiscriminatorValue()); modelBuilder.Entity().HasBaseType((string)null); @@ -166,6 +168,20 @@ public void Can_set_etag_concurrency_entity() Assert.True(etagProperty.IsConcurrencyToken); } + [Fact] + public void Default_discriminator_property_uses_embedded_discriminator_json_name() + { + var modelBuilder = CreateConventionModelBuilder(); + + modelBuilder.HasEmbeddedDiscriminatorName("Terminator"); + modelBuilder.Entity(); + + var discriminatorProperty = modelBuilder.Model.FindEntityType(typeof(Customer))!.FindDiscriminatorProperty()!; + + Assert.Equal("_type", discriminatorProperty.Name); + Assert.Equal("Terminator", discriminatorProperty.GetJsonPropertyName()); + } + [Fact] public void Can_set_etag_concurrency_property() { From 955413398d2ad875d4895d7cfd4e7fc0b145ae81 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Jun 2026 03:15:04 +0000 Subject: [PATCH 12/23] Polish Cosmos discriminator configuration updates Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../CosmosDiscriminatorConvention.cs | 25 +++++++++----- .../Query/NorthwindQueryCosmosFixture.cs | 34 +++++++++---------- 2 files changed, 34 insertions(+), 25 deletions(-) diff --git a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs index df9507ee2ef..00126127dc4 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs @@ -2,7 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; -using Microsoft.EntityFrameworkCore; // ReSharper disable once CheckNamespace namespace Microsoft.EntityFrameworkCore.Metadata.Conventions; @@ -86,11 +85,9 @@ private static void ProcessEntityType(IConventionEntityTypeBuilder entityTypeBui { return; } - if (entityType.IsDocumentRoot()) { - var discriminator = entityTypeBuilder.HasDiscriminator(DiscriminatorPropertyName, typeof(string)); - discriminator?.EntityType.FindDiscriminatorProperty()?.Builder.ToJsonProperty(entityType.Model.GetEmbeddedDiscriminatorName()); + var discriminator = HasDiscriminator(entityTypeBuilder); discriminator?.HasValue(entityType, entityType.ShortName()); } else @@ -129,8 +126,7 @@ public override void ProcessEntityTypeBaseTypeChanged( { if (entityType.IsDocumentRoot()) { - var discriminator = entityTypeBuilder.HasDiscriminator(DiscriminatorPropertyName, typeof(string)); - discriminator?.EntityType.FindDiscriminatorProperty()?.Builder.ToJsonProperty(entityType.Model.GetEmbeddedDiscriminatorName()); + HasDiscriminator(entityTypeBuilder); } } else @@ -142,15 +138,28 @@ public override void ProcessEntityTypeBaseTypeChanged( return; } - var discriminator = rootType.Builder.HasDiscriminator(DiscriminatorPropertyName, typeof(string)); + var discriminator = HasDiscriminator(rootType.Builder); if (discriminator != null) { - discriminator.EntityType.FindDiscriminatorProperty()?.Builder.ToJsonProperty(entityType.Model.GetEmbeddedDiscriminatorName()); SetDefaultDiscriminatorValues(entityTypeBuilder.Metadata.GetDerivedTypesInclusive(), discriminator); } } } + private static IConventionDiscriminatorBuilder? HasDiscriminator(IConventionEntityTypeBuilder entityTypeBuilder) + { + var discriminator = entityTypeBuilder.HasDiscriminator(DiscriminatorPropertyName, typeof(string)); + var discriminatorProperty = discriminator?.EntityType.FindDiscriminatorProperty(); + if (discriminatorProperty != null) + { + CosmosPropertyBuilderExtensions.ToJsonProperty( + discriminatorProperty.Builder, + entityTypeBuilder.Metadata.Model.GetEmbeddedDiscriminatorName()); + } + + return discriminator; + } + /// protected override void SetDefaultDiscriminatorValues( IEnumerable entityTypes, diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindQueryCosmosFixture.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindQueryCosmosFixture.cs index 1e8f5bb69b8..1d4f647ed78 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindQueryCosmosFixture.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindQueryCosmosFixture.cs @@ -52,35 +52,35 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con .HasRootDiscriminatorInJsonId() .ToContainer("ProductsAndOrders"); - modelBuilder.Entity().ToContainer("ProductsAndOrders").HasRootDiscriminatorInJsonId(); - modelBuilder.Entity().HasDiscriminator("_type").HasValue("Order"); - modelBuilder.Entity().Property("_type").ToJsonProperty("$type"); + var orderQuery = modelBuilder.Entity().ToContainer("ProductsAndOrders").HasRootDiscriminatorInJsonId(); + orderQuery.HasDiscriminator("_type").HasValue("Order"); + orderQuery.Property("_type").ToJsonProperty("$type"); - modelBuilder + var productQuery = modelBuilder .Entity() .ToContainer("ProductsAndOrders") .HasRootDiscriminatorInJsonId(); - modelBuilder.Entity().HasDiscriminator("_type").HasValue("Product"); - modelBuilder.Entity().Property("_type").ToJsonProperty("$type"); + productQuery.HasDiscriminator("_type").HasValue("Product"); + productQuery.Property("_type").ToJsonProperty("$type"); - modelBuilder + var productView = modelBuilder .Entity() .ToContainer("ProductsAndOrders") .HasRootDiscriminatorInJsonId(); - modelBuilder.Entity().HasDiscriminator("_type").HasValue("ProductView"); - modelBuilder.Entity().Property("_type").ToJsonProperty("$type"); + productView.HasDiscriminator("_type").HasValue("ProductView"); + productView.Property("_type").ToJsonProperty("$type"); - modelBuilder + var customerQueryWithQueryFilter = modelBuilder .Entity() - .ToContainer("Customers") - .HasDiscriminator("_type").HasValue("Customer"); - modelBuilder.Entity().Property("_type").ToJsonProperty("$type"); + .ToContainer("Customers"); + customerQueryWithQueryFilter.HasDiscriminator("_type").HasValue("Customer"); + customerQueryWithQueryFilter.Property("_type").ToJsonProperty("$type"); - modelBuilder + var customerQuery = modelBuilder .Entity() - .ToContainer("Customers") - .HasDiscriminator("_type").HasValue("Customer"); - modelBuilder.Entity().Property("_type").ToJsonProperty("$type"); + .ToContainer("Customers"); + customerQuery.HasDiscriminator("_type").HasValue("Customer"); + customerQuery.Property("_type").ToJsonProperty("$type"); modelBuilder.Entity().Metadata.RemoveIndex( modelBuilder.Entity().Property(e => e.City).Metadata.GetContainingIndexes().Single()); From c6bb2875e46272a6fa1849053fd3de764f8b7485 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 20 Jun 2026 04:46:15 +0000 Subject: [PATCH 13/23] Use default Cosmos discriminator property name Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../CosmosDiscriminatorConvention.cs | 4 +--- .../Query/NorthwindQueryCosmosFixture.cs | 20 +++++++++---------- .../Extensions/CosmosBuilderExtensionsTest.cs | 6 +++--- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs index 00126127dc4..1e007b7aaf5 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs @@ -21,8 +21,6 @@ public class CosmosDiscriminatorConvention : IEntityTypeAnnotationChangedConvention, IModelEmbeddedDiscriminatorNameConvention { - private const string DiscriminatorPropertyName = "_type"; - /// /// Creates a new instance of . /// @@ -148,7 +146,7 @@ public override void ProcessEntityTypeBaseTypeChanged( private static IConventionDiscriminatorBuilder? HasDiscriminator(IConventionEntityTypeBuilder entityTypeBuilder) { - var discriminator = entityTypeBuilder.HasDiscriminator(DiscriminatorPropertyName, typeof(string)); + var discriminator = entityTypeBuilder.HasDiscriminator(typeof(string)); var discriminatorProperty = discriminator?.EntityType.FindDiscriminatorProperty(); if (discriminatorProperty != null) { diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindQueryCosmosFixture.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindQueryCosmosFixture.cs index 1d4f647ed78..dae02c001a8 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindQueryCosmosFixture.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindQueryCosmosFixture.cs @@ -53,34 +53,34 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con .ToContainer("ProductsAndOrders"); var orderQuery = modelBuilder.Entity().ToContainer("ProductsAndOrders").HasRootDiscriminatorInJsonId(); - orderQuery.HasDiscriminator("_type").HasValue("Order"); - orderQuery.Property("_type").ToJsonProperty("$type"); + orderQuery.HasDiscriminator().HasValue("Order"); + orderQuery.Property("Discriminator").ToJsonProperty("$type"); var productQuery = modelBuilder .Entity() .ToContainer("ProductsAndOrders") .HasRootDiscriminatorInJsonId(); - productQuery.HasDiscriminator("_type").HasValue("Product"); - productQuery.Property("_type").ToJsonProperty("$type"); + productQuery.HasDiscriminator().HasValue("Product"); + productQuery.Property("Discriminator").ToJsonProperty("$type"); var productView = modelBuilder .Entity() .ToContainer("ProductsAndOrders") .HasRootDiscriminatorInJsonId(); - productView.HasDiscriminator("_type").HasValue("ProductView"); - productView.Property("_type").ToJsonProperty("$type"); + productView.HasDiscriminator().HasValue("ProductView"); + productView.Property("Discriminator").ToJsonProperty("$type"); var customerQueryWithQueryFilter = modelBuilder .Entity() .ToContainer("Customers"); - customerQueryWithQueryFilter.HasDiscriminator("_type").HasValue("Customer"); - customerQueryWithQueryFilter.Property("_type").ToJsonProperty("$type"); + customerQueryWithQueryFilter.HasDiscriminator().HasValue("Customer"); + customerQueryWithQueryFilter.Property("Discriminator").ToJsonProperty("$type"); var customerQuery = modelBuilder .Entity() .ToContainer("Customers"); - customerQuery.HasDiscriminator("_type").HasValue("Customer"); - customerQuery.Property("_type").ToJsonProperty("$type"); + customerQuery.HasDiscriminator().HasValue("Customer"); + customerQuery.Property("Discriminator").ToJsonProperty("$type"); modelBuilder.Entity().Metadata.RemoveIndex( modelBuilder.Entity().Property(e => e.City).Metadata.GetContainingIndexes().Single()); diff --git a/test/EFCore.Cosmos.Tests/Extensions/CosmosBuilderExtensionsTest.cs b/test/EFCore.Cosmos.Tests/Extensions/CosmosBuilderExtensionsTest.cs index 49945ead2d9..91a680b2538 100644 --- a/test/EFCore.Cosmos.Tests/Extensions/CosmosBuilderExtensionsTest.cs +++ b/test/EFCore.Cosmos.Tests/Extensions/CosmosBuilderExtensionsTest.cs @@ -135,7 +135,7 @@ public void Default_discriminator_can_be_removed() var entityType = modelBuilder.Model.FindEntityType(typeof(Customer))!; - Assert.Equal("_type", entityType.FindDiscriminatorProperty()!.Name); + Assert.Equal("Discriminator", entityType.FindDiscriminatorProperty()!.Name); Assert.Equal("$type", entityType.FindDiscriminatorProperty()!.GetJsonPropertyName()); Assert.Equal(nameof(Customer), entityType.GetDiscriminatorValue()); @@ -146,7 +146,7 @@ public void Default_discriminator_can_be_removed() modelBuilder.Entity().HasBaseType(); - Assert.Equal("_type", entityType.FindDiscriminatorProperty()!.Name); + Assert.Equal("Discriminator", entityType.FindDiscriminatorProperty()!.Name); Assert.Equal("$type", entityType.FindDiscriminatorProperty()!.GetJsonPropertyName()); Assert.Equal(nameof(Customer), entityType.GetDiscriminatorValue()); @@ -178,7 +178,7 @@ public void Default_discriminator_property_uses_embedded_discriminator_json_name var discriminatorProperty = modelBuilder.Model.FindEntityType(typeof(Customer))!.FindDiscriminatorProperty()!; - Assert.Equal("_type", discriminatorProperty.Name); + Assert.Equal("Discriminator", discriminatorProperty.Name); Assert.Equal("Terminator", discriminatorProperty.GetJsonPropertyName()); } From 482bd555aad5a05530631b986e4788155ba38267 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Jun 2026 18:23:29 +0000 Subject: [PATCH 14/23] Use embedded discriminator name in relational JSON snapshots Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../Design/AnnotationCodeGenerator.cs | 8 ++- .../RelationalPropertyExtensions.cs | 2 +- ...rpMigrationsGeneratorTest.ModelSnapshot.cs | 18 ++++++- .../RelationalBuilderExtensionsTest.cs | 49 +++++++++++++++++++ 4 files changed, 73 insertions(+), 4 deletions(-) diff --git a/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs b/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs index 3a09933958a..ca63c50d4af 100644 --- a/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs +++ b/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs @@ -52,7 +52,8 @@ public AnnotationCodeGenerator(AnnotationCodeGeneratorDependencies dependencies) /// public virtual IEnumerable FilterIgnoredAnnotations(IEnumerable annotations) - => annotations.Where(a => !(CoreAnnotationNames.AllNames.Contains(a.Name) + => annotations.Where(a => !((CoreAnnotationNames.AllNames.Contains(a.Name) + && a.Name != CoreAnnotationNames.EmbeddedDiscriminatorName) || IgnoredRelationalAnnotations.Contains(a.Name))); /// @@ -180,6 +181,11 @@ public virtual IReadOnlyList GenerateFluentApiCalls( { var methodCallCodeFragments = new List(); + GenerateSimpleFluentApiCall( + annotations, + CoreAnnotationNames.EmbeddedDiscriminatorName, "HasEmbeddedDiscriminatorName", + methodCallCodeFragments); + GenerateSimpleFluentApiCall( annotations, RelationalAnnotationNames.DefaultSchema, nameof(RelationalModelBuilderExtensions.HasDefaultSchema), diff --git a/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs b/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs index caa17d220d1..3e1e3e866e9 100644 --- a/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs @@ -2071,7 +2071,7 @@ private static TValue ThrowReadValueException( ?? (property.IsKey() || !property.DeclaringType.IsMappedToJson() ? null : property == property.DeclaringType.FindDiscriminatorProperty() - ? "$type" + ? property.DeclaringType.Model.GetEmbeddedDiscriminatorName() : property.Name); /// diff --git a/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.ModelSnapshot.cs b/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.ModelSnapshot.cs index 89d1a99e71b..7387d9ce459 100644 --- a/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.ModelSnapshot.cs +++ b/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.ModelSnapshot.cs @@ -6489,6 +6489,7 @@ public virtual void Complex_types_mapped_to_json_are_stored_in_snapshot() => Test( builder => { + builder.HasEmbeddedDiscriminatorName("Terminator"); builder.Entity(b => { b.HasKey(x => x.Id).HasName("PK_Custom"); @@ -6501,6 +6502,7 @@ public virtual void Complex_types_mapped_to_json_are_stored_in_snapshot() bb.ComplexProperty( x => x.EntityWithStringKey, bbb => { + bbb.HasDiscriminator("Discriminator"); bbb.ComplexCollection(x => x.Properties, bbbb => bbbb.HasJsonPropertyName("JsonProps")); }); bb.ComplexProperty( @@ -6513,8 +6515,14 @@ public virtual void Complex_types_mapped_to_json_are_stored_in_snapshot() }); }, AddBoilerPlate( - GetHeading() - + """ + """ + modelBuilder + .HasEmbeddedDiscriminatorName("Terminator") + .HasDefaultSchema("DefaultSchema") + .HasAnnotation("Relational:MaxIdentifierLength", 128); + + SqlServerModelBuilderExtensions.UseIdentityColumns(modelBuilder); + modelBuilder.Entity("Microsoft.EntityFrameworkCore.Migrations.Design.CSharpMigrationsGeneratorTest+EntityWithOneProperty", b => { var id = b.Property("Id") @@ -6543,6 +6551,9 @@ public virtual void Complex_types_mapped_to_json_are_stored_in_snapshot() b1.ComplexProperty(typeof(Dictionary), "EntityWithStringKey", "Microsoft.EntityFrameworkCore.Migrations.Design.CSharpMigrationsGeneratorTest+EntityWithOneProperty.EntityWithTwoProperties#EntityWithTwoProperties.EntityWithStringKey#EntityWithStringKey", b2 => { + b2.Property("Discriminator") + .IsRequired(); + b2.Property("Id"); b2.ComplexCollection(typeof(List>), "Properties", "Microsoft.EntityFrameworkCore.Migrations.Design.CSharpMigrationsGeneratorTest+EntityWithOneProperty.EntityWithTwoProperties#EntityWithTwoProperties.EntityWithStringKey#EntityWithStringKey.Properties#EntityWithStringProperty", b3 => @@ -6553,6 +6564,8 @@ public virtual void Complex_types_mapped_to_json_are_stored_in_snapshot() b3.HasJsonPropertyName("JsonProps"); }); + + b2.HasDiscriminator("Discriminator").HasValue("EntityWithStringKey"); }); b1 @@ -6595,6 +6608,7 @@ public virtual void Complex_types_mapped_to_json_are_stored_in_snapshot() Assert.False(entityWithStringKeyComplexProperty.IsCollection); Assert.True(entityWithStringKeyComplexProperty.IsNullable); var entityWithStringKeyComplexType = entityWithStringKeyComplexProperty.ComplexType; + Assert.Equal("Terminator", entityWithStringKeyComplexType.FindDiscriminatorProperty()!.GetJsonPropertyName()); var propertiesComplexCollection = entityWithStringKeyComplexType.FindComplexProperty(nameof(EntityWithStringKey.Properties)); diff --git a/test/EFCore.Relational.Tests/Extensions/RelationalBuilderExtensionsTest.cs b/test/EFCore.Relational.Tests/Extensions/RelationalBuilderExtensionsTest.cs index 8ce3403ad5a..3ca98c7b8a9 100644 --- a/test/EFCore.Relational.Tests/Extensions/RelationalBuilderExtensionsTest.cs +++ b/test/EFCore.Relational.Tests/Extensions/RelationalBuilderExtensionsTest.cs @@ -895,6 +895,38 @@ public void Can_set_default_discriminator_value_separately() Assert.Equal("2", modelBuilder.Model.FindEntityType(typeof(SpecialCustomer)).GetDiscriminatorValue()); } + [Fact] + public void Embedded_discriminator_name_is_used_for_json_entity_and_complex_discriminators() + { + var modelBuilder = CreateConventionModelBuilder(); + + modelBuilder.HasEmbeddedDiscriminatorName("Terminator"); + modelBuilder.Entity( + b => + { + b.OwnsOne( + e => e.JsonOwned, bb => + { + bb.ToJson(); + }); + b.ComplexProperty( + e => e.JsonComplex, bb => + { + bb.ToJson(); + bb.HasDiscriminator("ComplexDiscriminator"); + }); + }); + + var entityType = modelBuilder.Model.FindEntityType(typeof(JsonContainer))!; + var ownedEntityType = entityType.FindNavigation(nameof(JsonContainer.JsonOwned))!.TargetEntityType; + ((EntityType)ownedEntityType).Builder.HasDiscriminator("EntityDiscriminator", typeof(string), ConfigurationSource.Explicit)!.HasValue( + typeof(JsonOwned), "Owned"); + var complexType = entityType.FindComplexProperty(nameof(JsonContainer.JsonComplex))!.ComplexType; + + Assert.Equal("Terminator", ownedEntityType.FindDiscriminatorProperty()!.GetJsonPropertyName()); + Assert.Equal("Terminator", complexType.FindDiscriminatorProperty()!.GetJsonPropertyName()); + } + [Fact] public void Can_set_schema_on_model() { @@ -1522,6 +1554,23 @@ private class OrderDetails public Order Order { get; } } + private class JsonContainer + { + public int Id { get; set; } + public JsonOwned JsonOwned { get; set; } + public JsonComplex JsonComplex { get; set; } + } + + private class JsonOwned + { + public string Name { get; set; } + } + + private class JsonComplex + { + public string Name { get; set; } + } + private class Splot { public static readonly PropertyInfo SplowedProperty = typeof(Splot).GetProperty("Splowed"); From ef171203219629a7572163180f5ff63140449d30 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Jun 2026 18:27:32 +0000 Subject: [PATCH 15/23] Polish embedded discriminator snapshot coverage Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- src/EFCore.Relational/Design/AnnotationCodeGenerator.cs | 7 ++++--- .../Extensions/RelationalBuilderExtensionsTest.cs | 9 +++++++-- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs b/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs index ca63c50d4af..65cd05470cc 100644 --- a/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs +++ b/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs @@ -52,9 +52,10 @@ public AnnotationCodeGenerator(AnnotationCodeGeneratorDependencies dependencies) /// public virtual IEnumerable FilterIgnoredAnnotations(IEnumerable annotations) - => annotations.Where(a => !((CoreAnnotationNames.AllNames.Contains(a.Name) - && a.Name != CoreAnnotationNames.EmbeddedDiscriminatorName) - || IgnoredRelationalAnnotations.Contains(a.Name))); + => annotations.Where( + a => (!CoreAnnotationNames.AllNames.Contains(a.Name) + || a.Name == CoreAnnotationNames.EmbeddedDiscriminatorName) + && !IgnoredRelationalAnnotations.Contains(a.Name)); /// public virtual void RemoveAnnotationsHandledByConventions(IModel model, IDictionary annotations) diff --git a/test/EFCore.Relational.Tests/Extensions/RelationalBuilderExtensionsTest.cs b/test/EFCore.Relational.Tests/Extensions/RelationalBuilderExtensionsTest.cs index 3ca98c7b8a9..54e51ca07fd 100644 --- a/test/EFCore.Relational.Tests/Extensions/RelationalBuilderExtensionsTest.cs +++ b/test/EFCore.Relational.Tests/Extensions/RelationalBuilderExtensionsTest.cs @@ -923,8 +923,13 @@ public void Embedded_discriminator_name_is_used_for_json_entity_and_complex_disc typeof(JsonOwned), "Owned"); var complexType = entityType.FindComplexProperty(nameof(JsonContainer.JsonComplex))!.ComplexType; - Assert.Equal("Terminator", ownedEntityType.FindDiscriminatorProperty()!.GetJsonPropertyName()); - Assert.Equal("Terminator", complexType.FindDiscriminatorProperty()!.GetJsonPropertyName()); + var ownedDiscriminatorProperty = ownedEntityType.FindDiscriminatorProperty()!; + var complexDiscriminatorProperty = complexType.FindDiscriminatorProperty()!; + + Assert.Equal("EntityDiscriminator", ownedDiscriminatorProperty.Name); + Assert.Equal("Terminator", ownedDiscriminatorProperty.GetJsonPropertyName()); + Assert.Equal("ComplexDiscriminator", complexDiscriminatorProperty.Name); + Assert.Equal("Terminator", complexDiscriminatorProperty.GetJsonPropertyName()); } [Fact] From 4ce5c26d964962551c416ce2291317919e84c9c6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Jun 2026 18:30:41 +0000 Subject: [PATCH 16/23] Fix nullability in relational discriminator test Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../Extensions/RelationalBuilderExtensionsTest.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/EFCore.Relational.Tests/Extensions/RelationalBuilderExtensionsTest.cs b/test/EFCore.Relational.Tests/Extensions/RelationalBuilderExtensionsTest.cs index 54e51ca07fd..d3d88f8417d 100644 --- a/test/EFCore.Relational.Tests/Extensions/RelationalBuilderExtensionsTest.cs +++ b/test/EFCore.Relational.Tests/Extensions/RelationalBuilderExtensionsTest.cs @@ -1562,18 +1562,18 @@ private class OrderDetails private class JsonContainer { public int Id { get; set; } - public JsonOwned JsonOwned { get; set; } - public JsonComplex JsonComplex { get; set; } + public JsonOwned JsonOwned { get; set; } = null!; + public JsonComplex JsonComplex { get; set; } = null!; } private class JsonOwned { - public string Name { get; set; } + public string Name { get; set; } = null!; } private class JsonComplex { - public string Name { get; set; } + public string Name { get; set; } = null!; } private class Splot From 667b21e8fb1d6aa80b5c2fbc72816daa6ba82ebd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Jun 2026 18:34:22 +0000 Subject: [PATCH 17/23] Refine embedded discriminator readability Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- src/EFCore.Relational/Design/AnnotationCodeGenerator.cs | 5 ++++- .../Extensions/RelationalBuilderExtensionsTest.cs | 5 +++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs b/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs index 65cd05470cc..b3b505189a6 100644 --- a/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs +++ b/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs @@ -54,9 +54,12 @@ public AnnotationCodeGenerator(AnnotationCodeGeneratorDependencies dependencies) public virtual IEnumerable FilterIgnoredAnnotations(IEnumerable annotations) => annotations.Where( a => (!CoreAnnotationNames.AllNames.Contains(a.Name) - || a.Name == CoreAnnotationNames.EmbeddedDiscriminatorName) + || ShouldGenerateCoreAnnotation(a.Name)) && !IgnoredRelationalAnnotations.Contains(a.Name)); + private static bool ShouldGenerateCoreAnnotation(string annotationName) + => annotationName == CoreAnnotationNames.EmbeddedDiscriminatorName; + /// public virtual void RemoveAnnotationsHandledByConventions(IModel model, IDictionary annotations) => RemoveConventionalAnnotationsHelper(model, annotations, IsHandledByConvention); diff --git a/test/EFCore.Relational.Tests/Extensions/RelationalBuilderExtensionsTest.cs b/test/EFCore.Relational.Tests/Extensions/RelationalBuilderExtensionsTest.cs index d3d88f8417d..4036d2daab3 100644 --- a/test/EFCore.Relational.Tests/Extensions/RelationalBuilderExtensionsTest.cs +++ b/test/EFCore.Relational.Tests/Extensions/RelationalBuilderExtensionsTest.cs @@ -919,8 +919,9 @@ public void Embedded_discriminator_name_is_used_for_json_entity_and_complex_disc var entityType = modelBuilder.Model.FindEntityType(typeof(JsonContainer))!; var ownedEntityType = entityType.FindNavigation(nameof(JsonContainer.JsonOwned))!.TargetEntityType; - ((EntityType)ownedEntityType).Builder.HasDiscriminator("EntityDiscriminator", typeof(string), ConfigurationSource.Explicit)!.HasValue( - typeof(JsonOwned), "Owned"); + var discriminatorBuilder = ((EntityType)ownedEntityType).Builder.HasDiscriminator( + "EntityDiscriminator", typeof(string), ConfigurationSource.Explicit)!; + discriminatorBuilder.HasValue(typeof(JsonOwned), "Owned"); var complexType = entityType.FindComplexProperty(nameof(JsonContainer.JsonComplex))!.ComplexType; var ownedDiscriminatorProperty = ownedEntityType.FindDiscriminatorProperty()!; From 01eb71151d012cdf78b5c9c4823c093caa036064 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Jun 2026 19:11:09 +0000 Subject: [PATCH 18/23] WIP: update Cosmos discriminator expectations Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../Conventions/CosmosDiscriminatorConvention.cs | 2 +- src/EFCore.Design/Design/Internal/CSharpHelper.cs | 7 +++---- .../Migrations/Design/CSharpSnapshotGenerator.cs | 9 +++++++++ .../Design/AnnotationCodeGenerator.cs | 14 ++------------ .../Extensions/RelationalPropertyExtensions.cs | 2 +- src/EFCore/Infrastructure/ModelValidator.cs | 3 ++- .../Inheritance/InheritanceQueryCosmosFixture.cs | 1 - .../Inheritance/InheritanceQueryCosmosTest.cs | 6 +++--- .../Baselines/BigModel/ManyTypesEntityType.cs | 2 +- .../Baselines/BigModel/PrincipalBaseEntityType.cs | 2 +- ...ePrincipalDerivedDependentBasebyteEntityType.cs | 2 +- .../BigModel/PrincipalDerivedEntityType.cs | 2 +- .../ComplexTypes/PrincipalBaseEntityType.cs | 2 +- .../ComplexTypes/PrincipalDerivedEntityType.cs | 2 +- .../IndexedDataEntityType.cs | 2 +- .../Baselines/No_NativeAOT/ManyTypesEntityType.cs | 2 +- .../No_NativeAOT/PrincipalBaseEntityType.cs | 2 +- ...ePrincipalDerivedDependentBasebyteEntityType.cs | 2 +- .../No_NativeAOT/PrincipalDerivedEntityType.cs | 2 +- .../SimpleModel/DependentDerivedEntityType.cs | 2 +- .../Extensions/CosmosBuilderExtensionsTest.cs | 4 ++-- .../CSharpMigrationsGeneratorTest.ModelSnapshot.cs | 4 ++-- 22 files changed, 37 insertions(+), 39 deletions(-) diff --git a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs index 1e007b7aaf5..22bb65d622e 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs @@ -152,7 +152,7 @@ public override void ProcessEntityTypeBaseTypeChanged( { CosmosPropertyBuilderExtensions.ToJsonProperty( discriminatorProperty.Builder, - entityTypeBuilder.Metadata.Model.GetEmbeddedDiscriminatorName()); + (string?)entityTypeBuilder.Metadata.Model.FindAnnotation("EmbeddedDiscriminatorName")?.Value); } return discriminator; diff --git a/src/EFCore.Design/Design/Internal/CSharpHelper.cs b/src/EFCore.Design/Design/Internal/CSharpHelper.cs index 953469b0133..100d32ccbab 100644 --- a/src/EFCore.Design/Design/Internal/CSharpHelper.cs +++ b/src/EFCore.Design/Design/Internal/CSharpHelper.cs @@ -297,8 +297,7 @@ private static string Identifier(string name, bool? capitalize) builder.Append(name[partStart..]); } - if (builder.Length == 0 - || !IsIdentifierStartCharacter(builder[0])) + if (!ModelValidator.IsValidIdentifier(builder.ToString())) { builder.Insert(0, '_'); } @@ -1633,8 +1632,8 @@ public virtual string Expression( } private static bool IsIdentifierStartCharacter(char ch) - => char.IsLetter(ch) || ch == '_'; + => ModelValidator.IsValidIdentifier(ch.ToString()); private static bool IsIdentifierPartCharacter(char ch) - => char.IsLetter(ch) || char.IsAsciiDigit(ch) || ch == '_'; + => ModelValidator.IsValidIdentifier($"_{ch}"); } diff --git a/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs b/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs index 5aaa65db93b..f151fdb9bd9 100644 --- a/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs +++ b/src/EFCore.Design/Migrations/Design/CSharpSnapshotGenerator.cs @@ -579,6 +579,15 @@ private Dictionary GetAnnotations(IProperty property) property.GetColumnName()); } + if (!annotations.ContainsKey(RelationalAnnotationNames.JsonPropertyName) + && property.GetJsonPropertyName() is { } jsonPropertyName + && property.Name != jsonPropertyName) + { + annotations[RelationalAnnotationNames.JsonPropertyName] = new Annotation( + RelationalAnnotationNames.JsonPropertyName, + jsonPropertyName); + } + return Dependencies.AnnotationCodeGenerator .FilterIgnoredAnnotations(annotations.Values) .ToDictionary(a => a.Name, a => a); diff --git a/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs b/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs index b3b505189a6..3a09933958a 100644 --- a/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs +++ b/src/EFCore.Relational/Design/AnnotationCodeGenerator.cs @@ -52,13 +52,8 @@ public AnnotationCodeGenerator(AnnotationCodeGeneratorDependencies dependencies) /// public virtual IEnumerable FilterIgnoredAnnotations(IEnumerable annotations) - => annotations.Where( - a => (!CoreAnnotationNames.AllNames.Contains(a.Name) - || ShouldGenerateCoreAnnotation(a.Name)) - && !IgnoredRelationalAnnotations.Contains(a.Name)); - - private static bool ShouldGenerateCoreAnnotation(string annotationName) - => annotationName == CoreAnnotationNames.EmbeddedDiscriminatorName; + => annotations.Where(a => !(CoreAnnotationNames.AllNames.Contains(a.Name) + || IgnoredRelationalAnnotations.Contains(a.Name))); /// public virtual void RemoveAnnotationsHandledByConventions(IModel model, IDictionary annotations) @@ -185,11 +180,6 @@ public virtual IReadOnlyList GenerateFluentApiCalls( { var methodCallCodeFragments = new List(); - GenerateSimpleFluentApiCall( - annotations, - CoreAnnotationNames.EmbeddedDiscriminatorName, "HasEmbeddedDiscriminatorName", - methodCallCodeFragments); - GenerateSimpleFluentApiCall( annotations, RelationalAnnotationNames.DefaultSchema, nameof(RelationalModelBuilderExtensions.HasDefaultSchema), diff --git a/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs b/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs index 3e1e3e866e9..9514b9bf52c 100644 --- a/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs @@ -2071,7 +2071,7 @@ private static TValue ThrowReadValueException( ?? (property.IsKey() || !property.DeclaringType.IsMappedToJson() ? null : property == property.DeclaringType.FindDiscriminatorProperty() - ? property.DeclaringType.Model.GetEmbeddedDiscriminatorName() + ? (string?)property.DeclaringType.Model.FindAnnotation("EmbeddedDiscriminatorName")?.Value : property.Name); /// diff --git a/src/EFCore/Infrastructure/ModelValidator.cs b/src/EFCore/Infrastructure/ModelValidator.cs index c3974a1cfc3..f06d6d37048 100644 --- a/src/EFCore/Infrastructure/ModelValidator.cs +++ b/src/EFCore/Infrastructure/ModelValidator.cs @@ -186,7 +186,8 @@ protected virtual void ValidateProperty( /// Returns if the given name only uses letters, ASCII digits and underscores and does not start with a digit; /// that is, if it can be used as-is as an identifier in generated code. /// - internal static bool IsValidIdentifier(string? name) + [EntityFrameworkInternal] + public static bool IsValidIdentifier(string? name) { if (string.IsNullOrEmpty(name) || (!char.IsLetter(name[0]) && name[0] != '_')) diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/Inheritance/InheritanceQueryCosmosFixture.cs b/test/EFCore.Cosmos.FunctionalTests/Query/Inheritance/InheritanceQueryCosmosFixture.cs index 43862b4fde2..83521a667c0 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/Inheritance/InheritanceQueryCosmosFixture.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/Inheritance/InheritanceQueryCosmosFixture.cs @@ -34,7 +34,6 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity().ToContainer("Animals"); modelBuilder.Entity().ToContainer("Plants"); - modelBuilder.Entity().Property("Discriminator").ToJsonProperty("_type"); modelBuilder.Entity().ToContainer("Countries"); modelBuilder.Entity().ToContainer("Drinks"); modelBuilder.Entity().ToContainer("Animals"); diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/Inheritance/InheritanceQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/Inheritance/InheritanceQueryCosmosTest.cs index 64780ac44dc..31dc9368881 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/Inheritance/InheritanceQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/Inheritance/InheritanceQueryCosmosTest.cs @@ -253,7 +253,7 @@ public override Task Can_use_of_type_rose(bool async) """ SELECT VALUE c FROM root c -WHERE (c["$type"] IN ("Daisy", "Rose") AND (c["$type"] = "Rose")) +WHERE (c["Discriminator"] IN ("Daisy", "Rose") AND (c["Discriminator"] = "Rose")) """); }); @@ -290,7 +290,7 @@ public override Task Can_query_all_plants(bool async) """ SELECT VALUE c FROM root c -WHERE c["$type"] IN ("Daisy", "Rose") +WHERE c["Discriminator"] IN ("Daisy", "Rose") ORDER BY c["id"] """); }); @@ -350,7 +350,7 @@ public override Task Can_query_just_roses(bool async) """ SELECT VALUE c FROM root c -WHERE (c["$type"] = "Rose") +WHERE (c["Discriminator"] = "Rose") OFFSET 0 LIMIT 2 """); }); diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/ManyTypesEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/ManyTypesEntityType.cs index 10f0b26b8a5..9088f2b2e27 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/ManyTypesEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/ManyTypesEntityType.cs @@ -36,7 +36,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas "Microsoft.EntityFrameworkCore.Scaffolding.CompiledModelTestBase+ManyTypes", typeof(CompiledModelTestBase.ManyTypes), baseEntityType, - discriminatorProperty: "$type", + discriminatorProperty: "Discriminator", discriminatorValue: "ManyTypes", propertyCount: 170, keyCount: 1); diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBaseEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBaseEntityType.cs index 06643bad1a0..074783fedc5 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBaseEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBaseEntityType.cs @@ -32,7 +32,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas "Microsoft.EntityFrameworkCore.Scaffolding.CompiledModelTestBase+PrincipalBase", typeof(CompiledModelTestBase.PrincipalBase), baseEntityType, - discriminatorProperty: "$type", + discriminatorProperty: "Discriminator", discriminatorValue: "PrincipalBase", derivedTypesCount: 1, propertyCount: 15, diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs index d9d7d3e8a99..d5dfb096b62 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs @@ -34,7 +34,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas sharedClrType: true, indexerPropertyInfo: RuntimeEntityType.FindIndexerProperty(typeof(Dictionary)), propertyBag: true, - discriminatorProperty: "$type", + discriminatorProperty: "Discriminator", discriminatorValue: "PrincipalBasePrincipalDerived>", propertyCount: 8, foreignKeyCount: 2, diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalDerivedEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalDerivedEntityType.cs index edcac7de4b9..5712ed3bf4a 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalDerivedEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalDerivedEntityType.cs @@ -24,7 +24,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas "Microsoft.EntityFrameworkCore.Scaffolding.CompiledModelTestBase+PrincipalDerived>", typeof(CompiledModelTestBase.PrincipalDerived>), baseEntityType, - discriminatorProperty: "$type", + discriminatorProperty: "Discriminator", discriminatorValue: "PrincipalDerived", propertyCount: 0, navigationCount: 2, diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs index 1ab863968a2..2b6ee66c55a 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs @@ -32,7 +32,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas "Microsoft.EntityFrameworkCore.Scaffolding.CompiledModelTestBase+PrincipalBase", typeof(CompiledModelTestBase.PrincipalBase), baseEntityType, - discriminatorProperty: "$type", + discriminatorProperty: "Discriminator", discriminatorValue: "PrincipalBase", derivedTypesCount: 1, propertyCount: 15, diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalDerivedEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalDerivedEntityType.cs index cbe7e7aac5b..8645018f1ea 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalDerivedEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalDerivedEntityType.cs @@ -31,7 +31,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas "Microsoft.EntityFrameworkCore.Scaffolding.CompiledModelTestBase+PrincipalDerived>", typeof(CompiledModelTestBase.PrincipalDerived>), baseEntityType, - discriminatorProperty: "$type", + discriminatorProperty: "Discriminator", discriminatorValue: "PrincipalDerived", propertyCount: 0, complexPropertyCount: 2); diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/Cosmos_model_with_index_types/IndexedDataEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/Cosmos_model_with_index_types/IndexedDataEntityType.cs index 11be89f211d..9a549751d78 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/Cosmos_model_with_index_types/IndexedDataEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/Cosmos_model_with_index_types/IndexedDataEntityType.cs @@ -32,7 +32,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas "Microsoft.EntityFrameworkCore.Scaffolding.CompiledModelCosmosTest+IndexedData", typeof(CompiledModelCosmosTest.IndexedData), baseEntityType, - discriminatorProperty: "$type", + discriminatorProperty: "Discriminator", discriminatorValue: "IndexedData", propertyCount: 10, unnamedIndexCount: 3, diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/ManyTypesEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/ManyTypesEntityType.cs index a4efb56e17a..f72adba1643 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/ManyTypesEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/ManyTypesEntityType.cs @@ -30,7 +30,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas "Microsoft.EntityFrameworkCore.Scaffolding.CompiledModelTestBase+ManyTypes", typeof(CompiledModelTestBase.ManyTypes), baseEntityType, - discriminatorProperty: "$type", + discriminatorProperty: "Discriminator", discriminatorValue: "ManyTypes", propertyCount: 170, keyCount: 1); diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBaseEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBaseEntityType.cs index 269b6688b8e..c6796a07ca0 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBaseEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBaseEntityType.cs @@ -25,7 +25,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas "Microsoft.EntityFrameworkCore.Scaffolding.CompiledModelTestBase+PrincipalBase", typeof(CompiledModelTestBase.PrincipalBase), baseEntityType, - discriminatorProperty: "$type", + discriminatorProperty: "Discriminator", discriminatorValue: "PrincipalBase", derivedTypesCount: 1, propertyCount: 15, diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs index 2db1a4e4cee..385bed9b0c9 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs @@ -26,7 +26,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas sharedClrType: true, indexerPropertyInfo: RuntimeEntityType.FindIndexerProperty(typeof(Dictionary)), propertyBag: true, - discriminatorProperty: "$type", + discriminatorProperty: "Discriminator", discriminatorValue: "PrincipalBasePrincipalDerived>", propertyCount: 8, foreignKeyCount: 2, diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalDerivedEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalDerivedEntityType.cs index 09d7c707205..a41a3ec75a5 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalDerivedEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalDerivedEntityType.cs @@ -20,7 +20,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas "Microsoft.EntityFrameworkCore.Scaffolding.CompiledModelTestBase+PrincipalDerived>", typeof(CompiledModelTestBase.PrincipalDerived>), baseEntityType, - discriminatorProperty: "$type", + discriminatorProperty: "Discriminator", discriminatorValue: "PrincipalDerived", propertyCount: 0, navigationCount: 2, diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs index 84ccae895e1..4450549e976 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs @@ -28,7 +28,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas "Microsoft.EntityFrameworkCore.Scaffolding.CompiledModelTestBase+DependentDerived", typeof(CompiledModelTestBase.DependentDerived), baseEntityType, - discriminatorProperty: "$type", + discriminatorProperty: "Discriminator", discriminatorValue: "DependentDerived", propertyCount: 5, keyCount: 1); diff --git a/test/EFCore.Cosmos.Tests/Extensions/CosmosBuilderExtensionsTest.cs b/test/EFCore.Cosmos.Tests/Extensions/CosmosBuilderExtensionsTest.cs index 91a680b2538..0a7b249397b 100644 --- a/test/EFCore.Cosmos.Tests/Extensions/CosmosBuilderExtensionsTest.cs +++ b/test/EFCore.Cosmos.Tests/Extensions/CosmosBuilderExtensionsTest.cs @@ -136,7 +136,7 @@ public void Default_discriminator_can_be_removed() var entityType = modelBuilder.Model.FindEntityType(typeof(Customer))!; Assert.Equal("Discriminator", entityType.FindDiscriminatorProperty()!.Name); - Assert.Equal("$type", entityType.FindDiscriminatorProperty()!.GetJsonPropertyName()); + Assert.Equal("Discriminator", entityType.FindDiscriminatorProperty()!.GetJsonPropertyName()); Assert.Equal(nameof(Customer), entityType.GetDiscriminatorValue()); modelBuilder.Entity().HasNoDiscriminator(); @@ -147,7 +147,7 @@ public void Default_discriminator_can_be_removed() modelBuilder.Entity().HasBaseType(); Assert.Equal("Discriminator", entityType.FindDiscriminatorProperty()!.Name); - Assert.Equal("$type", entityType.FindDiscriminatorProperty()!.GetJsonPropertyName()); + Assert.Equal("Discriminator", entityType.FindDiscriminatorProperty()!.GetJsonPropertyName()); Assert.Equal(nameof(Customer), entityType.GetDiscriminatorValue()); modelBuilder.Entity().HasBaseType((string)null); diff --git a/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.ModelSnapshot.cs b/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.ModelSnapshot.cs index 7387d9ce459..3726e535176 100644 --- a/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.ModelSnapshot.cs +++ b/test/EFCore.Design.Tests/Migrations/Design/CSharpMigrationsGeneratorTest.ModelSnapshot.cs @@ -6517,7 +6517,6 @@ public virtual void Complex_types_mapped_to_json_are_stored_in_snapshot() AddBoilerPlate( """ modelBuilder - .HasEmbeddedDiscriminatorName("Terminator") .HasDefaultSchema("DefaultSchema") .HasAnnotation("Relational:MaxIdentifierLength", 128); @@ -6552,7 +6551,8 @@ public virtual void Complex_types_mapped_to_json_are_stored_in_snapshot() b1.ComplexProperty(typeof(Dictionary), "EntityWithStringKey", "Microsoft.EntityFrameworkCore.Migrations.Design.CSharpMigrationsGeneratorTest+EntityWithOneProperty.EntityWithTwoProperties#EntityWithTwoProperties.EntityWithStringKey#EntityWithStringKey", b2 => { b2.Property("Discriminator") - .IsRequired(); + .IsRequired() + .HasJsonPropertyName("Terminator"); b2.Property("Id"); From 98eda42f44dbedde9dae29ad7291909a46707594 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Jun 2026 19:15:52 +0000 Subject: [PATCH 19/23] Update Cosmos compiled-model baselines Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../ComplexTypes/PrincipalBaseEntityType.cs | 20 ++--- .../PrincipalDerivedEntityType.cs | 6 +- .../IndexedDataEntityType.cs | 82 +++++++++---------- .../No_NativeAOT/ManyTypesEntityType.cs | 12 +-- .../No_NativeAOT/PrincipalBaseEntityType.cs | 4 +- ...cipalDerivedDependentBasebyteEntityType.cs | 4 +- .../SimpleModel/DependentDerivedEntityType.cs | 76 ++++++++--------- 7 files changed, 102 insertions(+), 102 deletions(-) diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs index 2b6ee66c55a..09f1742af1e 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs @@ -92,23 +92,23 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas id.SetComparer(new NullableValueComparer(id.TypeMapping.Comparer)); id.SetKeyComparer(new NullableValueComparer(id.TypeMapping.KeyComparer)); - var type = runtimeEntityType.AddProperty( - "$type", + var discriminator = runtimeEntityType.AddProperty( + "Discriminator", typeof(string), afterSaveBehavior: PropertySaveBehavior.Throw, valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); - type.SetAccessors( + discriminator.SetAccessors( string (IInternalEntry entry) => entry.ReadShadowValue(0), string (IInternalEntry entry) => entry.ReadShadowValue(0), - string (IInternalEntry entry) => entry.ReadOriginalValue(type, 1), - string (IInternalEntry entry) => entry.GetCurrentValue(type)); - type.SetPropertyIndexes( + string (IInternalEntry entry) => entry.ReadOriginalValue(discriminator, 1), + string (IInternalEntry entry) => entry.GetCurrentValue(discriminator)); + discriminator.SetPropertyIndexes( index: 1, originalValueIndex: 1, shadowIndex: 0, relationshipIndex: -1, storeGenerationIndex: -1); - type.TypeMapping = CosmosTypeMapping.Default.Clone( + discriminator.TypeMapping = CosmosTypeMapping.Default.Clone( comparer: new ValueComparer( bool (string v1, string v2) => v1 == v2, int (string v) => ((object)v).GetHashCode(), @@ -2445,7 +2445,7 @@ public static RuntimeForeignKey CreateForeignKey1(RuntimeEntityType declaringEnt public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) { var id = runtimeEntityType.FindProperty("Id"); - var type = runtimeEntityType.FindProperty("$type"); + var discriminator = runtimeEntityType.FindProperty("Discriminator"); var enum1 = runtimeEntityType.FindProperty("Enum1"); var enum2 = runtimeEntityType.FindProperty("Enum2"); var flagsEnum1 = runtimeEntityType.FindProperty("FlagsEnum1"); @@ -2491,7 +2491,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (IInternalEntry source) => { var structuralType = ((CompiledModelTestBase.PrincipalBase)(source.Entity)); - var liftedArg = ((ISnapshot)(new Snapshot, IList, DateTime[], IEnumerable, IList, List, string, JObject, string, int, IEnumerable, IList, DateTime[], IEnumerable, IList, List, object, Guid, CompiledModelTestBase.AnEnum, CompiledModelTestBase.AnEnum?, CompiledModelTestBase.AFlagsEnum, CompiledModelTestBase.AFlagsEnum, long?>((source.GetCurrentValue(id) == null ? null : ((ValueComparer)(((IProperty)id).GetValueComparer())).Snapshot(source.GetCurrentValue(id))), (source.GetCurrentValue(type) == null ? null : ((ValueComparer)(((IProperty)type).GetValueComparer())).Snapshot(source.GetCurrentValue(type))), ((ValueComparer)(((IProperty)enum1).GetValueComparer())).Snapshot(source.GetCurrentValue(enum1)), (source.GetCurrentValue(enum2) == null ? null : ((ValueComparer)(((IProperty)enum2).GetValueComparer())).Snapshot(source.GetCurrentValue(enum2))), ((ValueComparer)(((IProperty)flagsEnum1).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum1)), ((ValueComparer)(((IProperty)flagsEnum2).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum2)), (source.GetCurrentValue(principalBaseId) == null ? null : ((ValueComparer)(((IProperty)principalBaseId).GetValueComparer())).Snapshot(source.GetCurrentValue(principalBaseId))), (((object)(source.GetCurrentValue>(refTypeEnumerable))) == null ? null : ((IEnumerable)(((ValueComparer)(((IProperty)refTypeEnumerable).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeEnumerable))))))), (((object)(source.GetCurrentValue>(refTypeIList))) == null ? null : ((IList)(((ValueComparer)(((IProperty)refTypeIList).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeIList))))))), (((IEnumerable)(source.GetCurrentValue(valueTypeArray))) == null ? null : ((DateTime[])(((ValueComparer>)(((IProperty)valueTypeArray).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(valueTypeArray))))))), (source.GetCurrentValue>(valueTypeEnumerable) == null ? null : ((ValueComparer>)(((IProperty)valueTypeEnumerable).GetValueComparer())).Snapshot(source.GetCurrentValue>(valueTypeEnumerable))), (((IEnumerable)(source.GetCurrentValue>(valueTypeIList))) == null ? null : ((IList)(((ValueComparer>)(((IProperty)valueTypeIList).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeIList))))))), (((IEnumerable)(source.GetCurrentValue>(valueTypeList))) == null ? null : ((List)(((ValueComparer>)(((IProperty)valueTypeList).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeList))))))), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetValueComparer())).Snapshot(source.GetCurrentValue(__id))), (source.GetCurrentValue(__jObject) == null ? null : ((ValueComparer)(((IProperty)__jObject).GetValueComparer())).Snapshot(source.GetCurrentValue(__jObject))), (source.GetCurrentValue(details) == null ? null : ((ValueComparer)(((IProperty)details).GetValueComparer())).Snapshot(source.GetCurrentValue(details))), ((ValueComparer)(((IProperty)number).GetValueComparer())).Snapshot(source.GetCurrentValue(number)), (((object)(source.GetCurrentValue>(refTypeEnumerable0))) == null ? null : ((IEnumerable)(((ValueComparer)(((IProperty)refTypeEnumerable0).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeEnumerable0))))))), (((object)(source.GetCurrentValue>(refTypeIList0))) == null ? null : ((IList)(((ValueComparer)(((IProperty)refTypeIList0).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeIList0))))))), (((IEnumerable)(source.GetCurrentValue(valueTypeArray0))) == null ? null : ((DateTime[])(((ValueComparer>)(((IProperty)valueTypeArray0).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(valueTypeArray0))))))), (source.GetCurrentValue>(valueTypeEnumerable0) == null ? null : ((ValueComparer>)(((IProperty)valueTypeEnumerable0).GetValueComparer())).Snapshot(source.GetCurrentValue>(valueTypeEnumerable0))), (((IEnumerable)(source.GetCurrentValue>(valueTypeIList0))) == null ? null : ((IList)(((ValueComparer>)(((IProperty)valueTypeIList0).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeIList0))))))), (((IEnumerable)(source.GetCurrentValue>(valueTypeList0))) == null ? null : ((List)(((ValueComparer>)(((IProperty)valueTypeList0).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeList0))))))), ((object)(source.GetCurrentValue(principal))), ((ValueComparer)(((IProperty)alternateId).GetValueComparer())).Snapshot(source.GetCurrentValue(alternateId)), ((ValueComparer)(((IProperty)enum10).GetValueComparer())).Snapshot(source.GetCurrentValue(enum10)), (source.GetCurrentValue(enum20) == null ? null : ((ValueComparer)(((IProperty)enum20).GetValueComparer())).Snapshot(source.GetCurrentValue(enum20))), ((ValueComparer)(((IProperty)flagsEnum10).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum10)), ((ValueComparer)(((IProperty)flagsEnum20).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum20)), (source.GetCurrentValue(id0) == null ? null : ((ValueComparer)(((IProperty)id0).GetValueComparer())).Snapshot(source.GetCurrentValue(id0)))))); + var liftedArg = ((ISnapshot)(new Snapshot, IList, DateTime[], IEnumerable, IList, List, string, JObject, string, int, IEnumerable, IList, DateTime[], IEnumerable, IList, List, object, Guid, CompiledModelTestBase.AnEnum, CompiledModelTestBase.AnEnum?, CompiledModelTestBase.AFlagsEnum, CompiledModelTestBase.AFlagsEnum, long?>((source.GetCurrentValue(id) == null ? null : ((ValueComparer)(((IProperty)id).GetValueComparer())).Snapshot(source.GetCurrentValue(id))), (source.GetCurrentValue(discriminator) == null ? null : ((ValueComparer)(((IProperty)discriminator).GetValueComparer())).Snapshot(source.GetCurrentValue(discriminator))), ((ValueComparer)(((IProperty)enum1).GetValueComparer())).Snapshot(source.GetCurrentValue(enum1)), (source.GetCurrentValue(enum2) == null ? null : ((ValueComparer)(((IProperty)enum2).GetValueComparer())).Snapshot(source.GetCurrentValue(enum2))), ((ValueComparer)(((IProperty)flagsEnum1).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum1)), ((ValueComparer)(((IProperty)flagsEnum2).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum2)), (source.GetCurrentValue(principalBaseId) == null ? null : ((ValueComparer)(((IProperty)principalBaseId).GetValueComparer())).Snapshot(source.GetCurrentValue(principalBaseId))), (((object)(source.GetCurrentValue>(refTypeEnumerable))) == null ? null : ((IEnumerable)(((ValueComparer)(((IProperty)refTypeEnumerable).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeEnumerable))))))), (((object)(source.GetCurrentValue>(refTypeIList))) == null ? null : ((IList)(((ValueComparer)(((IProperty)refTypeIList).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeIList))))))), (((IEnumerable)(source.GetCurrentValue(valueTypeArray))) == null ? null : ((DateTime[])(((ValueComparer>)(((IProperty)valueTypeArray).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(valueTypeArray))))))), (source.GetCurrentValue>(valueTypeEnumerable) == null ? null : ((ValueComparer>)(((IProperty)valueTypeEnumerable).GetValueComparer())).Snapshot(source.GetCurrentValue>(valueTypeEnumerable))), (((IEnumerable)(source.GetCurrentValue>(valueTypeIList))) == null ? null : ((IList)(((ValueComparer>)(((IProperty)valueTypeIList).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeIList))))))), (((IEnumerable)(source.GetCurrentValue>(valueTypeList))) == null ? null : ((List)(((ValueComparer>)(((IProperty)valueTypeList).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeList))))))), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetValueComparer())).Snapshot(source.GetCurrentValue(__id))), (source.GetCurrentValue(__jObject) == null ? null : ((ValueComparer)(((IProperty)__jObject).GetValueComparer())).Snapshot(source.GetCurrentValue(__jObject))), (source.GetCurrentValue(details) == null ? null : ((ValueComparer)(((IProperty)details).GetValueComparer())).Snapshot(source.GetCurrentValue(details))), ((ValueComparer)(((IProperty)number).GetValueComparer())).Snapshot(source.GetCurrentValue(number)), (((object)(source.GetCurrentValue>(refTypeEnumerable0))) == null ? null : ((IEnumerable)(((ValueComparer)(((IProperty)refTypeEnumerable0).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeEnumerable0))))))), (((object)(source.GetCurrentValue>(refTypeIList0))) == null ? null : ((IList)(((ValueComparer)(((IProperty)refTypeIList0).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeIList0))))))), (((IEnumerable)(source.GetCurrentValue(valueTypeArray0))) == null ? null : ((DateTime[])(((ValueComparer>)(((IProperty)valueTypeArray0).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(valueTypeArray0))))))), (source.GetCurrentValue>(valueTypeEnumerable0) == null ? null : ((ValueComparer>)(((IProperty)valueTypeEnumerable0).GetValueComparer())).Snapshot(source.GetCurrentValue>(valueTypeEnumerable0))), (((IEnumerable)(source.GetCurrentValue>(valueTypeIList0))) == null ? null : ((IList)(((ValueComparer>)(((IProperty)valueTypeIList0).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeIList0))))))), (((IEnumerable)(source.GetCurrentValue>(valueTypeList0))) == null ? null : ((List)(((ValueComparer>)(((IProperty)valueTypeList0).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeList0))))))), ((object)(source.GetCurrentValue(principal))), ((ValueComparer)(((IProperty)alternateId).GetValueComparer())).Snapshot(source.GetCurrentValue(alternateId)), ((ValueComparer)(((IProperty)enum10).GetValueComparer())).Snapshot(source.GetCurrentValue(enum10)), (source.GetCurrentValue(enum20) == null ? null : ((ValueComparer)(((IProperty)enum20).GetValueComparer())).Snapshot(source.GetCurrentValue(enum20))), ((ValueComparer)(((IProperty)flagsEnum10).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum10)), ((ValueComparer)(((IProperty)flagsEnum20).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum20)), (source.GetCurrentValue(id0) == null ? null : ((ValueComparer)(((IProperty)id0).GetValueComparer())).Snapshot(source.GetCurrentValue(id0)))))); var structuralType0 = ((CompiledModelTestBase.PrincipalBase)(source.Entity)); return ((ISnapshot)(new MultiSnapshot(new ISnapshot[] { liftedArg, ((ISnapshot)(new Snapshot, IList, DateTime[], IEnumerable, IList, List>((((object)(source.GetCurrentValue>(refTypeEnumerable1))) == null ? null : ((IEnumerable)(((ValueComparer)(((IProperty)refTypeEnumerable1).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeEnumerable1))))))), (((object)(source.GetCurrentValue>(refTypeIList1))) == null ? null : ((IList)(((ValueComparer)(((IProperty)refTypeIList1).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeIList1))))))), (((IEnumerable)(source.GetCurrentValue(valueTypeArray1))) == null ? null : ((DateTime[])(((ValueComparer>)(((IProperty)valueTypeArray1).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(valueTypeArray1))))))), (source.GetCurrentValue>(valueTypeEnumerable1) == null ? null : ((ValueComparer>)(((IProperty)valueTypeEnumerable1).GetValueComparer())).Snapshot(source.GetCurrentValue>(valueTypeEnumerable1))), (((IEnumerable)(source.GetCurrentValue>(valueTypeIList1))) == null ? null : ((IList)(((ValueComparer>)(((IProperty)valueTypeIList1).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeIList1))))))), (((IEnumerable)(source.GetCurrentValue>(valueTypeList1))) == null ? null : ((List)(((ValueComparer>)(((IProperty)valueTypeList1).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeList1)))))))))) }))); }); @@ -2500,7 +2500,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) runtimeEntityType.SetTemporaryValuesFactory( ISnapshot (IInternalEntry source) => ((ISnapshot)(new Snapshot(default(long? ))))); runtimeEntityType.SetShadowValuesFactory( - ISnapshot (IDictionary source) => ((ISnapshot)(new Snapshot((source.ContainsKey("$type") ? ((string)(source["$type"])) : null), (source.ContainsKey("PrincipalBaseId") ? ((long? )(source["PrincipalBaseId"])) : null), (source.ContainsKey("__id") ? ((string)(source["__id"])) : null), (source.ContainsKey("__jObject") ? ((JObject)(source["__jObject"])) : null))))); + ISnapshot (IDictionary source) => ((ISnapshot)(new Snapshot((source.ContainsKey("Discriminator") ? ((string)(source["Discriminator"])) : null), (source.ContainsKey("PrincipalBaseId") ? ((long? )(source["PrincipalBaseId"])) : null), (source.ContainsKey("__id") ? ((string)(source["__id"])) : null), (source.ContainsKey("__jObject") ? ((JObject)(source["__jObject"])) : null))))); runtimeEntityType.SetEmptyShadowValuesFactory( ISnapshot () => ((ISnapshot)(new Snapshot(default(string), default(long? ), default(string), default(JObject))))); runtimeEntityType.SetRelationshipSnapshotFactory( diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalDerivedEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalDerivedEntityType.cs index 8645018f1ea..d1a3d06a914 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalDerivedEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalDerivedEntityType.cs @@ -1927,7 +1927,7 @@ public static RuntimeComplexProperty Create(RuntimeComplexType declaringType) public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) { var id = runtimeEntityType.FindProperty("Id"); - var type = runtimeEntityType.FindProperty("$type"); + var discriminator = runtimeEntityType.FindProperty("Discriminator"); var enum1 = runtimeEntityType.FindProperty("Enum1"); var enum2 = runtimeEntityType.FindProperty("Enum2"); var flagsEnum1 = runtimeEntityType.FindProperty("FlagsEnum1"); @@ -1997,7 +1997,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (IInternalEntry source) => { var structuralType1 = ((CompiledModelTestBase.PrincipalDerived>)(source.Entity)); - var liftedArg0 = ((ISnapshot)(new Snapshot, IList, DateTime[], IEnumerable, IList, List, string, JObject, string, int, IEnumerable, IList, DateTime[], IEnumerable, IList, List, object, Guid, CompiledModelTestBase.AnEnum, CompiledModelTestBase.AnEnum?, CompiledModelTestBase.AFlagsEnum, CompiledModelTestBase.AFlagsEnum, long?>((source.GetCurrentValue(id) == null ? null : ((ValueComparer)(((IProperty)id).GetValueComparer())).Snapshot(source.GetCurrentValue(id))), (source.GetCurrentValue(type) == null ? null : ((ValueComparer)(((IProperty)type).GetValueComparer())).Snapshot(source.GetCurrentValue(type))), ((ValueComparer)(((IProperty)enum1).GetValueComparer())).Snapshot(source.GetCurrentValue(enum1)), (source.GetCurrentValue(enum2) == null ? null : ((ValueComparer)(((IProperty)enum2).GetValueComparer())).Snapshot(source.GetCurrentValue(enum2))), ((ValueComparer)(((IProperty)flagsEnum1).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum1)), ((ValueComparer)(((IProperty)flagsEnum2).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum2)), (source.GetCurrentValue(principalBaseId) == null ? null : ((ValueComparer)(((IProperty)principalBaseId).GetValueComparer())).Snapshot(source.GetCurrentValue(principalBaseId))), (((object)(source.GetCurrentValue>(refTypeEnumerable))) == null ? null : ((IEnumerable)(((ValueComparer)(((IProperty)refTypeEnumerable).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeEnumerable))))))), (((object)(source.GetCurrentValue>(refTypeIList))) == null ? null : ((IList)(((ValueComparer)(((IProperty)refTypeIList).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeIList))))))), (((IEnumerable)(source.GetCurrentValue(valueTypeArray))) == null ? null : ((DateTime[])(((ValueComparer>)(((IProperty)valueTypeArray).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(valueTypeArray))))))), (source.GetCurrentValue>(valueTypeEnumerable) == null ? null : ((ValueComparer>)(((IProperty)valueTypeEnumerable).GetValueComparer())).Snapshot(source.GetCurrentValue>(valueTypeEnumerable))), (((IEnumerable)(source.GetCurrentValue>(valueTypeIList))) == null ? null : ((IList)(((ValueComparer>)(((IProperty)valueTypeIList).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeIList))))))), (((IEnumerable)(source.GetCurrentValue>(valueTypeList))) == null ? null : ((List)(((ValueComparer>)(((IProperty)valueTypeList).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeList))))))), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetValueComparer())).Snapshot(source.GetCurrentValue(__id))), (source.GetCurrentValue(__jObject) == null ? null : ((ValueComparer)(((IProperty)__jObject).GetValueComparer())).Snapshot(source.GetCurrentValue(__jObject))), (source.GetCurrentValue(details) == null ? null : ((ValueComparer)(((IProperty)details).GetValueComparer())).Snapshot(source.GetCurrentValue(details))), ((ValueComparer)(((IProperty)number).GetValueComparer())).Snapshot(source.GetCurrentValue(number)), (((object)(source.GetCurrentValue>(refTypeEnumerable0))) == null ? null : ((IEnumerable)(((ValueComparer)(((IProperty)refTypeEnumerable0).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeEnumerable0))))))), (((object)(source.GetCurrentValue>(refTypeIList0))) == null ? null : ((IList)(((ValueComparer)(((IProperty)refTypeIList0).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeIList0))))))), (((IEnumerable)(source.GetCurrentValue(valueTypeArray0))) == null ? null : ((DateTime[])(((ValueComparer>)(((IProperty)valueTypeArray0).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(valueTypeArray0))))))), (source.GetCurrentValue>(valueTypeEnumerable0) == null ? null : ((ValueComparer>)(((IProperty)valueTypeEnumerable0).GetValueComparer())).Snapshot(source.GetCurrentValue>(valueTypeEnumerable0))), (((IEnumerable)(source.GetCurrentValue>(valueTypeIList0))) == null ? null : ((IList)(((ValueComparer>)(((IProperty)valueTypeIList0).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeIList0))))))), (((IEnumerable)(source.GetCurrentValue>(valueTypeList0))) == null ? null : ((List)(((ValueComparer>)(((IProperty)valueTypeList0).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeList0))))))), ((object)(source.GetCurrentValue(principal))), ((ValueComparer)(((IProperty)alternateId).GetValueComparer())).Snapshot(source.GetCurrentValue(alternateId)), ((ValueComparer)(((IProperty)enum10).GetValueComparer())).Snapshot(source.GetCurrentValue(enum10)), (source.GetCurrentValue(enum20) == null ? null : ((ValueComparer)(((IProperty)enum20).GetValueComparer())).Snapshot(source.GetCurrentValue(enum20))), ((ValueComparer)(((IProperty)flagsEnum10).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum10)), ((ValueComparer)(((IProperty)flagsEnum20).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum20)), (source.GetCurrentValue(id0) == null ? null : ((ValueComparer)(((IProperty)id0).GetValueComparer())).Snapshot(source.GetCurrentValue(id0)))))); + var liftedArg0 = ((ISnapshot)(new Snapshot, IList, DateTime[], IEnumerable, IList, List, string, JObject, string, int, IEnumerable, IList, DateTime[], IEnumerable, IList, List, object, Guid, CompiledModelTestBase.AnEnum, CompiledModelTestBase.AnEnum?, CompiledModelTestBase.AFlagsEnum, CompiledModelTestBase.AFlagsEnum, long?>((source.GetCurrentValue(id) == null ? null : ((ValueComparer)(((IProperty)id).GetValueComparer())).Snapshot(source.GetCurrentValue(id))), (source.GetCurrentValue(discriminator) == null ? null : ((ValueComparer)(((IProperty)discriminator).GetValueComparer())).Snapshot(source.GetCurrentValue(discriminator))), ((ValueComparer)(((IProperty)enum1).GetValueComparer())).Snapshot(source.GetCurrentValue(enum1)), (source.GetCurrentValue(enum2) == null ? null : ((ValueComparer)(((IProperty)enum2).GetValueComparer())).Snapshot(source.GetCurrentValue(enum2))), ((ValueComparer)(((IProperty)flagsEnum1).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum1)), ((ValueComparer)(((IProperty)flagsEnum2).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum2)), (source.GetCurrentValue(principalBaseId) == null ? null : ((ValueComparer)(((IProperty)principalBaseId).GetValueComparer())).Snapshot(source.GetCurrentValue(principalBaseId))), (((object)(source.GetCurrentValue>(refTypeEnumerable))) == null ? null : ((IEnumerable)(((ValueComparer)(((IProperty)refTypeEnumerable).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeEnumerable))))))), (((object)(source.GetCurrentValue>(refTypeIList))) == null ? null : ((IList)(((ValueComparer)(((IProperty)refTypeIList).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeIList))))))), (((IEnumerable)(source.GetCurrentValue(valueTypeArray))) == null ? null : ((DateTime[])(((ValueComparer>)(((IProperty)valueTypeArray).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(valueTypeArray))))))), (source.GetCurrentValue>(valueTypeEnumerable) == null ? null : ((ValueComparer>)(((IProperty)valueTypeEnumerable).GetValueComparer())).Snapshot(source.GetCurrentValue>(valueTypeEnumerable))), (((IEnumerable)(source.GetCurrentValue>(valueTypeIList))) == null ? null : ((IList)(((ValueComparer>)(((IProperty)valueTypeIList).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeIList))))))), (((IEnumerable)(source.GetCurrentValue>(valueTypeList))) == null ? null : ((List)(((ValueComparer>)(((IProperty)valueTypeList).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeList))))))), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetValueComparer())).Snapshot(source.GetCurrentValue(__id))), (source.GetCurrentValue(__jObject) == null ? null : ((ValueComparer)(((IProperty)__jObject).GetValueComparer())).Snapshot(source.GetCurrentValue(__jObject))), (source.GetCurrentValue(details) == null ? null : ((ValueComparer)(((IProperty)details).GetValueComparer())).Snapshot(source.GetCurrentValue(details))), ((ValueComparer)(((IProperty)number).GetValueComparer())).Snapshot(source.GetCurrentValue(number)), (((object)(source.GetCurrentValue>(refTypeEnumerable0))) == null ? null : ((IEnumerable)(((ValueComparer)(((IProperty)refTypeEnumerable0).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeEnumerable0))))))), (((object)(source.GetCurrentValue>(refTypeIList0))) == null ? null : ((IList)(((ValueComparer)(((IProperty)refTypeIList0).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeIList0))))))), (((IEnumerable)(source.GetCurrentValue(valueTypeArray0))) == null ? null : ((DateTime[])(((ValueComparer>)(((IProperty)valueTypeArray0).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(valueTypeArray0))))))), (source.GetCurrentValue>(valueTypeEnumerable0) == null ? null : ((ValueComparer>)(((IProperty)valueTypeEnumerable0).GetValueComparer())).Snapshot(source.GetCurrentValue>(valueTypeEnumerable0))), (((IEnumerable)(source.GetCurrentValue>(valueTypeIList0))) == null ? null : ((IList)(((ValueComparer>)(((IProperty)valueTypeIList0).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeIList0))))))), (((IEnumerable)(source.GetCurrentValue>(valueTypeList0))) == null ? null : ((List)(((ValueComparer>)(((IProperty)valueTypeList0).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeList0))))))), ((object)(source.GetCurrentValue(principal))), ((ValueComparer)(((IProperty)alternateId).GetValueComparer())).Snapshot(source.GetCurrentValue(alternateId)), ((ValueComparer)(((IProperty)enum10).GetValueComparer())).Snapshot(source.GetCurrentValue(enum10)), (source.GetCurrentValue(enum20) == null ? null : ((ValueComparer)(((IProperty)enum20).GetValueComparer())).Snapshot(source.GetCurrentValue(enum20))), ((ValueComparer)(((IProperty)flagsEnum10).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum10)), ((ValueComparer)(((IProperty)flagsEnum20).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum20)), (source.GetCurrentValue(id0) == null ? null : ((ValueComparer)(((IProperty)id0).GetValueComparer())).Snapshot(source.GetCurrentValue(id0)))))); var structuralType2 = ((CompiledModelTestBase.PrincipalDerived>)(source.Entity)); return ((ISnapshot)(new MultiSnapshot(new ISnapshot[] { liftedArg0, ((ISnapshot)(new Snapshot, IList, DateTime[], IEnumerable, IList, List, object, byte?, object>((((object)(source.GetCurrentValue>(refTypeEnumerable1))) == null ? null : ((IEnumerable)(((ValueComparer)(((IProperty)refTypeEnumerable1).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeEnumerable1))))))), (((object)(source.GetCurrentValue>(refTypeIList1))) == null ? null : ((IList)(((ValueComparer)(((IProperty)refTypeIList1).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeIList1))))))), (((IEnumerable)(source.GetCurrentValue(valueTypeArray1))) == null ? null : ((DateTime[])(((ValueComparer>)(((IProperty)valueTypeArray1).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(valueTypeArray1))))))), (source.GetCurrentValue>(valueTypeEnumerable1) == null ? null : ((ValueComparer>)(((IProperty)valueTypeEnumerable1).GetValueComparer())).Snapshot(source.GetCurrentValue>(valueTypeEnumerable1))), (((IEnumerable)(source.GetCurrentValue>(valueTypeIList1))) == null ? null : ((IList)(((ValueComparer>)(((IProperty)valueTypeIList1).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeIList1))))))), (((IEnumerable)(source.GetCurrentValue>(valueTypeList1))) == null ? null : ((List)(((ValueComparer>)(((IProperty)valueTypeList1).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeList1))))))), ((object)(source.GetCurrentValue>(dependent))), (source.GetCurrentValue(id1) == null ? null : ((ValueComparer)(((IProperty)id1).GetValueComparer())).Snapshot(source.GetCurrentValue(id1))), SnapshotFactoryFactory.SnapshotComplexCollection(((IList)(source.GetCurrentValue>(manyOwned))), manyOwned)))) }))); }); @@ -2006,7 +2006,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) runtimeEntityType.SetTemporaryValuesFactory( ISnapshot (IInternalEntry source) => ((ISnapshot)(new Snapshot(default(long? ))))); runtimeEntityType.SetShadowValuesFactory( - ISnapshot (IDictionary source) => ((ISnapshot)(new Snapshot((source.ContainsKey("$type") ? ((string)(source["$type"])) : null), (source.ContainsKey("PrincipalBaseId") ? ((long? )(source["PrincipalBaseId"])) : null), (source.ContainsKey("__id") ? ((string)(source["__id"])) : null), (source.ContainsKey("__jObject") ? ((JObject)(source["__jObject"])) : null))))); + ISnapshot (IDictionary source) => ((ISnapshot)(new Snapshot((source.ContainsKey("Discriminator") ? ((string)(source["Discriminator"])) : null), (source.ContainsKey("PrincipalBaseId") ? ((long? )(source["PrincipalBaseId"])) : null), (source.ContainsKey("__id") ? ((string)(source["__id"])) : null), (source.ContainsKey("__jObject") ? ((JObject)(source["__jObject"])) : null))))); runtimeEntityType.SetEmptyShadowValuesFactory( ISnapshot () => ((ISnapshot)(new Snapshot(default(string), default(long? ), default(string), default(JObject))))); runtimeEntityType.SetRelationshipSnapshotFactory( diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/Cosmos_model_with_index_types/IndexedDataEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/Cosmos_model_with_index_types/IndexedDataEntityType.cs index 9a549751d78..5a238d83d3c 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/Cosmos_model_with_index_types/IndexedDataEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/Cosmos_model_with_index_types/IndexedDataEntityType.cs @@ -137,38 +137,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas jsonValueReaderWriter: JsonStringReaderWriter.Instance); partitionId.SetCurrentValueComparer(new EntryCurrentValueComparer(partitionId)); - var type = runtimeEntityType.AddProperty( - "$type", - typeof(string), - afterSaveBehavior: PropertySaveBehavior.Throw, - valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); - type.SetAccessors( - string (IInternalEntry entry) => entry.ReadShadowValue(0), - string (IInternalEntry entry) => entry.ReadShadowValue(0), - string (IInternalEntry entry) => entry.ReadOriginalValue(type, 2), - string (IInternalEntry entry) => entry.GetCurrentValue(type)); - type.SetPropertyIndexes( - index: 2, - originalValueIndex: 2, - shadowIndex: 0, - relationshipIndex: -1, - storeGenerationIndex: -1); - type.TypeMapping = CosmosTypeMapping.Default.Clone( - comparer: new ValueComparer( - bool (string v1, string v2) => v1 == v2, - int (string v) => ((object)v).GetHashCode(), - string (string v) => v), - keyComparer: new ValueComparer( - bool (string v1, string v2) => v1 == v2, - int (string v) => ((object)v).GetHashCode(), - string (string v) => v), - providerValueComparer: new ValueComparer( - bool (string v1, string v2) => v1 == v2, - int (string v) => ((object)v).GetHashCode(), - string (string v) => v), - clrType: typeof(string), - jsonValueReaderWriter: JsonStringReaderWriter.Instance); - var category = runtimeEntityType.AddProperty( "Category", typeof(string), @@ -192,11 +160,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas category.SetAccessors( string (IInternalEntry entry) => IndexedDataUnsafeAccessors.Category(((CompiledModelCosmosTest.IndexedData)(entry.Entity))), string (IInternalEntry entry) => IndexedDataUnsafeAccessors.Category(((CompiledModelCosmosTest.IndexedData)(entry.Entity))), - string (IInternalEntry entry) => entry.ReadOriginalValue(category, 3), + string (IInternalEntry entry) => entry.ReadOriginalValue(category, 2), string (IInternalEntry entry) => entry.GetCurrentValue(category)); category.SetPropertyIndexes( - index: 3, - originalValueIndex: 3, + index: 2, + originalValueIndex: 2, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -239,11 +207,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas description.SetAccessors( string (IInternalEntry entry) => IndexedDataUnsafeAccessors.Description(((CompiledModelCosmosTest.IndexedData)(entry.Entity))), string (IInternalEntry entry) => IndexedDataUnsafeAccessors.Description(((CompiledModelCosmosTest.IndexedData)(entry.Entity))), - string (IInternalEntry entry) => entry.ReadOriginalValue(description, 4), + string (IInternalEntry entry) => entry.ReadOriginalValue(description, 3), string (IInternalEntry entry) => entry.GetCurrentValue(description)); description.SetPropertyIndexes( - index: 4, - originalValueIndex: 4, + index: 3, + originalValueIndex: 3, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -265,6 +233,38 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas description.AddAnnotation("Cosmos:FullTextSearchLanguage", null); description.AddAnnotation("Cosmos:IsFullTextSearchEnabled", true); + var discriminator = runtimeEntityType.AddProperty( + "Discriminator", + typeof(string), + afterSaveBehavior: PropertySaveBehavior.Throw, + valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); + discriminator.SetAccessors( + string (IInternalEntry entry) => entry.ReadShadowValue(0), + string (IInternalEntry entry) => entry.ReadShadowValue(0), + string (IInternalEntry entry) => entry.ReadOriginalValue(discriminator, 4), + string (IInternalEntry entry) => entry.GetCurrentValue(discriminator)); + discriminator.SetPropertyIndexes( + index: 4, + originalValueIndex: 4, + shadowIndex: 0, + relationshipIndex: -1, + storeGenerationIndex: -1); + discriminator.TypeMapping = CosmosTypeMapping.Default.Clone( + comparer: new ValueComparer( + bool (string v1, string v2) => v1 == v2, + int (string v) => ((object)v).GetHashCode(), + string (string v) => v), + keyComparer: new ValueComparer( + bool (string v1, string v2) => v1 == v2, + int (string v) => ((object)v).GetHashCode(), + string (string v) => v), + providerValueComparer: new ValueComparer( + bool (string v1, string v2) => v1 == v2, + int (string v) => ((object)v).GetHashCode(), + string (string v) => v), + clrType: typeof(string), + jsonValueReaderWriter: JsonStringReaderWriter.Instance); + var embedding = runtimeEntityType.AddProperty( "Embedding", typeof(ReadOnlyMemory), @@ -501,9 +501,9 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) { var id = runtimeEntityType.FindProperty("Id"); var partitionId = runtimeEntityType.FindProperty("PartitionId"); - var type = runtimeEntityType.FindProperty("$type"); var category = runtimeEntityType.FindProperty("Category"); var description = runtimeEntityType.FindProperty("Description"); + var discriminator = runtimeEntityType.FindProperty("Discriminator"); var embedding = runtimeEntityType.FindProperty("Embedding"); var notes = runtimeEntityType.FindProperty("Notes"); var region = runtimeEntityType.FindProperty("Region"); @@ -516,14 +516,14 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (IInternalEntry source) => { var structuralType = ((CompiledModelCosmosTest.IndexedData)(source.Entity)); - return ((ISnapshot)(new Snapshot, string, string, string, JObject>(((ValueComparer)(((IProperty)id).GetValueComparer())).Snapshot(source.GetCurrentValue(id)), (source.GetCurrentValue(partitionId) == null ? null : ((ValueComparer)(((IProperty)partitionId).GetValueComparer())).Snapshot(source.GetCurrentValue(partitionId))), (source.GetCurrentValue(type) == null ? null : ((ValueComparer)(((IProperty)type).GetValueComparer())).Snapshot(source.GetCurrentValue(type))), (source.GetCurrentValue(category) == null ? null : ((ValueComparer)(((IProperty)category).GetValueComparer())).Snapshot(source.GetCurrentValue(category))), (source.GetCurrentValue(description) == null ? null : ((ValueComparer)(((IProperty)description).GetValueComparer())).Snapshot(source.GetCurrentValue(description))), ((ValueComparer>)(((IProperty)embedding).GetValueComparer())).Snapshot(source.GetCurrentValue>(embedding)), (source.GetCurrentValue(notes) == null ? null : ((ValueComparer)(((IProperty)notes).GetValueComparer())).Snapshot(source.GetCurrentValue(notes))), (source.GetCurrentValue(region) == null ? null : ((ValueComparer)(((IProperty)region).GetValueComparer())).Snapshot(source.GetCurrentValue(region))), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetValueComparer())).Snapshot(source.GetCurrentValue(__id))), (source.GetCurrentValue(__jObject) == null ? null : ((ValueComparer)(((IProperty)__jObject).GetValueComparer())).Snapshot(source.GetCurrentValue(__jObject)))))); + return ((ISnapshot)(new Snapshot, string, string, string, JObject>(((ValueComparer)(((IProperty)id).GetValueComparer())).Snapshot(source.GetCurrentValue(id)), (source.GetCurrentValue(partitionId) == null ? null : ((ValueComparer)(((IProperty)partitionId).GetValueComparer())).Snapshot(source.GetCurrentValue(partitionId))), (source.GetCurrentValue(category) == null ? null : ((ValueComparer)(((IProperty)category).GetValueComparer())).Snapshot(source.GetCurrentValue(category))), (source.GetCurrentValue(description) == null ? null : ((ValueComparer)(((IProperty)description).GetValueComparer())).Snapshot(source.GetCurrentValue(description))), (source.GetCurrentValue(discriminator) == null ? null : ((ValueComparer)(((IProperty)discriminator).GetValueComparer())).Snapshot(source.GetCurrentValue(discriminator))), ((ValueComparer>)(((IProperty)embedding).GetValueComparer())).Snapshot(source.GetCurrentValue>(embedding)), (source.GetCurrentValue(notes) == null ? null : ((ValueComparer)(((IProperty)notes).GetValueComparer())).Snapshot(source.GetCurrentValue(notes))), (source.GetCurrentValue(region) == null ? null : ((ValueComparer)(((IProperty)region).GetValueComparer())).Snapshot(source.GetCurrentValue(region))), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetValueComparer())).Snapshot(source.GetCurrentValue(__id))), (source.GetCurrentValue(__jObject) == null ? null : ((ValueComparer)(((IProperty)__jObject).GetValueComparer())).Snapshot(source.GetCurrentValue(__jObject)))))); }); runtimeEntityType.SetStoreGeneratedValuesFactory( ISnapshot () => ((ISnapshot)(new Snapshot((default(JObject) == null ? null : ((ValueComparer)(((IProperty)__jObject).GetValueComparer())).Snapshot(default(JObject))))))); runtimeEntityType.SetTemporaryValuesFactory( ISnapshot (IInternalEntry source) => ((ISnapshot)(new Snapshot(default(JObject))))); runtimeEntityType.SetShadowValuesFactory( - ISnapshot (IDictionary source) => ((ISnapshot)(new Snapshot((source.ContainsKey("$type") ? ((string)(source["$type"])) : null), (source.ContainsKey("__id") ? ((string)(source["__id"])) : null), (source.ContainsKey("__jObject") ? ((JObject)(source["__jObject"])) : null))))); + ISnapshot (IDictionary source) => ((ISnapshot)(new Snapshot((source.ContainsKey("Discriminator") ? ((string)(source["Discriminator"])) : null), (source.ContainsKey("__id") ? ((string)(source["__id"])) : null), (source.ContainsKey("__jObject") ? ((JObject)(source["__jObject"])) : null))))); runtimeEntityType.SetEmptyShadowValuesFactory( ISnapshot () => ((ISnapshot)(new Snapshot(default(string), default(string), default(JObject))))); runtimeEntityType.SetRelationshipSnapshotFactory( diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/ManyTypesEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/ManyTypesEntityType.cs index f72adba1643..43ac0135f2c 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/ManyTypesEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/ManyTypesEntityType.cs @@ -44,12 +44,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas valueConverter: new CompiledModelTestBase.ManyTypesIdConverter()); id.SetSentinelFromProviderValue(0); - var type = runtimeEntityType.AddProperty( - "$type", - typeof(string), - afterSaveBehavior: PropertySaveBehavior.Throw, - valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); - var @bool = runtimeEntityType.AddProperty( "Bool", typeof(bool), @@ -268,6 +262,12 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas valueConverter: new NumberToStringConverter()); decimalNumberToStringConverterProperty.SetSentinelFromProviderValue("0"); + var discriminator = runtimeEntityType.AddProperty( + "Discriminator", + typeof(string), + afterSaveBehavior: PropertySaveBehavior.Throw, + valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); + var @double = runtimeEntityType.AddProperty( "Double", typeof(double), diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBaseEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBaseEntityType.cs index c6796a07ca0..885d049f5ff 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBaseEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBaseEntityType.cs @@ -49,8 +49,8 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas jsonValueReaderWriter: JsonGuidReaderWriter.Instance); alternateId.SetSentinelFromProviderValue("00000000-0000-0000-0000-000000000000"); - var type = runtimeEntityType.AddProperty( - "$type", + var discriminator = runtimeEntityType.AddProperty( + "Discriminator", typeof(string), afterSaveBehavior: PropertySaveBehavior.Throw, valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs index 385bed9b0c9..9dec95ad330 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs @@ -56,8 +56,8 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas propertyInfo: runtimeEntityType.FindIndexerPropertyInfo(), afterSaveBehavior: PropertySaveBehavior.Throw); - var type = runtimeEntityType.AddProperty( - "$type", + var discriminator = runtimeEntityType.AddProperty( + "Discriminator", typeof(string), propertyInfo: runtimeEntityType.FindIndexerPropertyInfo(), afterSaveBehavior: PropertySaveBehavior.Throw, diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs index 4450549e976..176923feb5b 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs @@ -83,38 +83,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas jsonValueReaderWriter: JsonInt32ReaderWriter.Instance); id.SetCurrentValueComparer(new EntryCurrentValueComparer(id)); - var type = runtimeEntityType.AddProperty( - "$type", - typeof(string), - afterSaveBehavior: PropertySaveBehavior.Throw, - valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); - type.SetAccessors( - string (IInternalEntry entry) => entry.ReadShadowValue(0), - string (IInternalEntry entry) => entry.ReadShadowValue(0), - string (IInternalEntry entry) => entry.ReadOriginalValue(type, 1), - string (IInternalEntry entry) => entry.GetCurrentValue(type)); - type.SetPropertyIndexes( - index: 1, - originalValueIndex: 1, - shadowIndex: 0, - relationshipIndex: -1, - storeGenerationIndex: -1); - type.TypeMapping = CosmosTypeMapping.Default.Clone( - comparer: new ValueComparer( - bool (string v1, string v2) => v1 == v2, - int (string v) => ((object)v).GetHashCode(), - string (string v) => v), - keyComparer: new ValueComparer( - bool (string v1, string v2) => v1 == v2, - int (string v) => ((object)v).GetHashCode(), - string (string v) => v), - providerValueComparer: new ValueComparer( - bool (string v1, string v2) => v1 == v2, - int (string v) => ((object)v).GetHashCode(), - string (string v) => v), - clrType: typeof(string), - jsonValueReaderWriter: JsonStringReaderWriter.Instance); - var data = runtimeEntityType.AddProperty( "Data", typeof(string), @@ -139,11 +107,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas data.SetAccessors( string (IInternalEntry entry) => DependentDerivedUnsafeAccessors.Data(((CompiledModelTestBase.DependentDerived)(entry.Entity))), string (IInternalEntry entry) => DependentDerivedUnsafeAccessors.Data(((CompiledModelTestBase.DependentDerived)(entry.Entity))), - string (IInternalEntry entry) => entry.ReadOriginalValue(data, 2), + string (IInternalEntry entry) => entry.ReadOriginalValue(data, 1), string (IInternalEntry entry) => entry.GetCurrentValue(data)); data.SetPropertyIndexes( - index: 2, - originalValueIndex: 2, + index: 1, + originalValueIndex: 1, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -163,6 +131,38 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas clrType: typeof(string), jsonValueReaderWriter: JsonStringReaderWriter.Instance); + var discriminator = runtimeEntityType.AddProperty( + "Discriminator", + typeof(string), + afterSaveBehavior: PropertySaveBehavior.Throw, + valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); + discriminator.SetAccessors( + string (IInternalEntry entry) => entry.ReadShadowValue(0), + string (IInternalEntry entry) => entry.ReadShadowValue(0), + string (IInternalEntry entry) => entry.ReadOriginalValue(discriminator, 2), + string (IInternalEntry entry) => entry.GetCurrentValue(discriminator)); + discriminator.SetPropertyIndexes( + index: 2, + originalValueIndex: 2, + shadowIndex: 0, + relationshipIndex: -1, + storeGenerationIndex: -1); + discriminator.TypeMapping = CosmosTypeMapping.Default.Clone( + comparer: new ValueComparer( + bool (string v1, string v2) => v1 == v2, + int (string v) => ((object)v).GetHashCode(), + string (string v) => v), + keyComparer: new ValueComparer( + bool (string v1, string v2) => v1 == v2, + int (string v) => ((object)v).GetHashCode(), + string (string v) => v), + providerValueComparer: new ValueComparer( + bool (string v1, string v2) => v1 == v2, + int (string v) => ((object)v).GetHashCode(), + string (string v) => v), + clrType: typeof(string), + jsonValueReaderWriter: JsonStringReaderWriter.Instance); + var __id = runtimeEntityType.AddProperty( "__id", typeof(string), @@ -240,8 +240,8 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) { var id = runtimeEntityType.FindProperty("Id"); - var type = runtimeEntityType.FindProperty("$type"); var data = runtimeEntityType.FindProperty("Data"); + var discriminator = runtimeEntityType.FindProperty("Discriminator"); var __id = runtimeEntityType.FindProperty("__id"); var __jObject = runtimeEntityType.FindProperty("__jObject"); var key = runtimeEntityType.FindKey(new[] { id }); @@ -251,14 +251,14 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (IInternalEntry source) => { var structuralType = ((CompiledModelTestBase.DependentDerived)(source.Entity)); - return ((ISnapshot)(new Snapshot(((ValueComparer)(((IProperty)id).GetValueComparer())).Snapshot(source.GetCurrentValue(id)), (source.GetCurrentValue(type) == null ? null : ((ValueComparer)(((IProperty)type).GetValueComparer())).Snapshot(source.GetCurrentValue(type))), (source.GetCurrentValue(data) == null ? null : ((ValueComparer)(((IProperty)data).GetValueComparer())).Snapshot(source.GetCurrentValue(data))), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetValueComparer())).Snapshot(source.GetCurrentValue(__id))), (source.GetCurrentValue(__jObject) == null ? null : ((ValueComparer)(((IProperty)__jObject).GetValueComparer())).Snapshot(source.GetCurrentValue(__jObject)))))); + return ((ISnapshot)(new Snapshot(((ValueComparer)(((IProperty)id).GetValueComparer())).Snapshot(source.GetCurrentValue(id)), (source.GetCurrentValue(data) == null ? null : ((ValueComparer)(((IProperty)data).GetValueComparer())).Snapshot(source.GetCurrentValue(data))), (source.GetCurrentValue(discriminator) == null ? null : ((ValueComparer)(((IProperty)discriminator).GetValueComparer())).Snapshot(source.GetCurrentValue(discriminator))), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetValueComparer())).Snapshot(source.GetCurrentValue(__id))), (source.GetCurrentValue(__jObject) == null ? null : ((ValueComparer)(((IProperty)__jObject).GetValueComparer())).Snapshot(source.GetCurrentValue(__jObject)))))); }); runtimeEntityType.SetStoreGeneratedValuesFactory( ISnapshot () => ((ISnapshot)(new Snapshot((default(JObject) == null ? null : ((ValueComparer)(((IProperty)__jObject).GetValueComparer())).Snapshot(default(JObject))))))); runtimeEntityType.SetTemporaryValuesFactory( ISnapshot (IInternalEntry source) => ((ISnapshot)(new Snapshot(default(JObject))))); runtimeEntityType.SetShadowValuesFactory( - ISnapshot (IDictionary source) => ((ISnapshot)(new Snapshot((source.ContainsKey("$type") ? ((string)(source["$type"])) : null), (source.ContainsKey("__id") ? ((string)(source["__id"])) : null), (source.ContainsKey("__jObject") ? ((JObject)(source["__jObject"])) : null))))); + ISnapshot (IDictionary source) => ((ISnapshot)(new Snapshot((source.ContainsKey("Discriminator") ? ((string)(source["Discriminator"])) : null), (source.ContainsKey("__id") ? ((string)(source["__id"])) : null), (source.ContainsKey("__jObject") ? ((JObject)(source["__jObject"])) : null))))); runtimeEntityType.SetEmptyShadowValuesFactory( ISnapshot () => ((ISnapshot)(new Snapshot(default(string), default(string), default(JObject))))); runtimeEntityType.SetRelationshipSnapshotFactory( From 2a5cbf275514d78cb8cde485099a036690e84e2a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Jun 2026 19:20:20 +0000 Subject: [PATCH 20/23] Avoid per-character identifier allocations Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- src/EFCore.Design/Design/Internal/CSharpHelper.cs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/EFCore.Design/Design/Internal/CSharpHelper.cs b/src/EFCore.Design/Design/Internal/CSharpHelper.cs index 100d32ccbab..d5651aa8333 100644 --- a/src/EFCore.Design/Design/Internal/CSharpHelper.cs +++ b/src/EFCore.Design/Design/Internal/CSharpHelper.cs @@ -297,17 +297,17 @@ private static string Identifier(string name, bool? capitalize) builder.Append(name[partStart..]); } - if (!ModelValidator.IsValidIdentifier(builder.ToString())) - { - builder.Insert(0, '_'); - } - if (capitalize != null) { ChangeFirstLetterCase(builder, capitalize.Value); } var identifier = builder.ToString(); + if (!ModelValidator.IsValidIdentifier(identifier)) + { + identifier = "_" + identifier; + } + return identifier; } @@ -1632,8 +1632,8 @@ public virtual string Expression( } private static bool IsIdentifierStartCharacter(char ch) - => ModelValidator.IsValidIdentifier(ch.ToString()); + => char.IsLetter(ch) || ch == '_'; private static bool IsIdentifierPartCharacter(char ch) - => ModelValidator.IsValidIdentifier($"_{ch}"); + => char.IsLetter(ch) || char.IsAsciiDigit(ch) || ch == '_'; } From 86de7a0643a127c3cea5a1ca2d56a029ed722a27 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 21 Jun 2026 19:24:50 +0000 Subject: [PATCH 21/23] Clarify final identifier validation Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- src/EFCore.Design/Design/Internal/CSharpHelper.cs | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/EFCore.Design/Design/Internal/CSharpHelper.cs b/src/EFCore.Design/Design/Internal/CSharpHelper.cs index d5651aa8333..11fabbefa39 100644 --- a/src/EFCore.Design/Design/Internal/CSharpHelper.cs +++ b/src/EFCore.Design/Design/Internal/CSharpHelper.cs @@ -302,13 +302,11 @@ private static string Identifier(string name, bool? capitalize) ChangeFirstLetterCase(builder, capitalize.Value); } - var identifier = builder.ToString(); - if (!ModelValidator.IsValidIdentifier(identifier)) - { - identifier = "_" + identifier; - } + var candidateIdentifier = builder.ToString(); - return identifier; + return ModelValidator.IsValidIdentifier(candidateIdentifier) + ? candidateIdentifier + : "_" + candidateIdentifier; } private static void ChangeFirstLetterCase(StringBuilder builder, bool capitalize) From 70cdf0ec75fde13d493ddf3e92b8f1525ea5b515 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 23 Jun 2026 02:04:50 +0000 Subject: [PATCH 22/23] Use embedded discriminator accessor for JSON discriminator names Co-authored-by: AndriySvyryd <6539701+AndriySvyryd@users.noreply.github.com> --- .../CosmosDiscriminatorConvention.cs | 2 +- .../RelationalPropertyExtensions.cs | 2 +- .../CosmosModelBuilderGenericTest.cs | 12 +- .../Inheritance/InheritanceQueryCosmosTest.cs | 86 ++++---- .../Query/JsonQueryCosmosTest.cs | 168 +++++++------- ...temPartitionKeyQueryInheritanceTestBase.cs | 6 +- .../ReadItemPartitionKeyQueryTestBase.cs | 6 +- .../Baselines/BigModel/ManyTypesEntityType.cs | 207 +++++++++--------- .../BigModel/PrincipalBaseEntityType.cs | 21 +- ...cipalDerivedDependentBasebyteEntityType.cs | 37 ++-- .../BigModel/PrincipalDerivedEntityType.cs | 6 +- .../ComplexTypes/PrincipalBaseEntityType.cs | 3 +- .../IndexedDataEntityType.cs | 35 +-- .../No_NativeAOT/ManyTypesEntityType.cs | 1 + .../No_NativeAOT/PrincipalBaseEntityType.cs | 1 + ...cipalDerivedDependentBasebyteEntityType.cs | 1 + .../SimpleModel/DependentDerivedEntityType.cs | 35 +-- .../TestUtilities/CosmosModelAsserter.cs | 4 +- .../Extensions/CosmosBuilderExtensionsTest.cs | 4 +- 19 files changed, 293 insertions(+), 344 deletions(-) diff --git a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs index 22bb65d622e..1e007b7aaf5 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosDiscriminatorConvention.cs @@ -152,7 +152,7 @@ public override void ProcessEntityTypeBaseTypeChanged( { CosmosPropertyBuilderExtensions.ToJsonProperty( discriminatorProperty.Builder, - (string?)entityTypeBuilder.Metadata.Model.FindAnnotation("EmbeddedDiscriminatorName")?.Value); + entityTypeBuilder.Metadata.Model.GetEmbeddedDiscriminatorName()); } return discriminator; diff --git a/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs b/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs index 9514b9bf52c..3e1e3e866e9 100644 --- a/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs +++ b/src/EFCore.Relational/Extensions/RelationalPropertyExtensions.cs @@ -2071,7 +2071,7 @@ private static TValue ThrowReadValueException( ?? (property.IsKey() || !property.DeclaringType.IsMappedToJson() ? null : property == property.DeclaringType.FindDiscriminatorProperty() - ? (string?)property.DeclaringType.Model.FindAnnotation("EmbeddedDiscriminatorName")?.Value + ? property.DeclaringType.Model.GetEmbeddedDiscriminatorName() : property.Name); /// diff --git a/test/EFCore.Cosmos.FunctionalTests/ModelBuilding/CosmosModelBuilderGenericTest.cs b/test/EFCore.Cosmos.FunctionalTests/ModelBuilding/CosmosModelBuilderGenericTest.cs index 48ba83dc29c..7bb2d755e1a 100644 --- a/test/EFCore.Cosmos.FunctionalTests/ModelBuilding/CosmosModelBuilderGenericTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/ModelBuilding/CosmosModelBuilderGenericTest.cs @@ -531,7 +531,7 @@ public virtual void Single_string_primary_key_maps_to_JSON_id() Assert.Equal( [ - nameof(SingleStringKey.Id), "$type", nameof(SingleStringKey.Name), nameof(SingleStringKey.P1), + nameof(SingleStringKey.Id), "Discriminator", nameof(SingleStringKey.Name), nameof(SingleStringKey.P1), nameof(SingleStringKey.P2), nameof(SingleStringKey.P3), "__jObject" ], entityType.GetProperties().Select(p => p.Name)); @@ -558,7 +558,7 @@ public virtual void Single_string_primary_key_with_single_partition_key_maps_to_ Assert.Equal( [ - nameof(SingleStringKey.Id), nameof(SingleStringKey.P1), "$type", nameof(SingleStringKey.Name), + nameof(SingleStringKey.Id), nameof(SingleStringKey.P1), "Discriminator", nameof(SingleStringKey.Name), nameof(SingleStringKey.P2), nameof(SingleStringKey.P3), "__jObject" ], entityType.GetProperties().Select(p => p.Name)); @@ -591,7 +591,7 @@ public virtual void Single_string_primary_key_with_hierarchical_partition_key_ma Assert.Equal( [ nameof(SingleStringKey.Id), nameof(SingleStringKey.P1), nameof(SingleStringKey.P2), nameof(SingleStringKey.P3), - "$type", nameof(SingleStringKey.Name), "__jObject" + "Discriminator", nameof(SingleStringKey.Name), "__jObject" ], entityType.GetProperties().Select(p => p.Name)); @@ -626,7 +626,7 @@ public virtual void Single_GUID_primary_key_maps_to_JSON_id() Assert.Equal( [ - nameof(SingleGuidKey.Id), "$type", nameof(SingleGuidKey.Name), nameof(SingleGuidKey.P1), + nameof(SingleGuidKey.Id), "Discriminator", nameof(SingleGuidKey.Name), nameof(SingleGuidKey.P1), nameof(SingleGuidKey.P2), nameof(SingleGuidKey.P3), "__jObject" ], entityType.GetProperties().Select(p => p.Name)); @@ -653,7 +653,7 @@ public virtual void Single_GUID_primary_key_with_single_partition_key_maps_to_JS Assert.Equal( [ - nameof(SingleGuidKey.Id), nameof(SingleGuidKey.P1), "$type", nameof(SingleGuidKey.Name), + nameof(SingleGuidKey.Id), nameof(SingleGuidKey.P1), "Discriminator", nameof(SingleGuidKey.Name), nameof(SingleGuidKey.P2), nameof(SingleGuidKey.P3), "__jObject" ], entityType.GetProperties().Select(p => p.Name)); @@ -686,7 +686,7 @@ public virtual void Single_GUID_primary_key_with_hierarchical_partition_key_maps Assert.Equal( [ nameof(SingleGuidKey.Id), nameof(SingleGuidKey.P1), nameof(SingleGuidKey.P2), nameof(SingleGuidKey.P3), - "$type", nameof(SingleGuidKey.Name), "__jObject" + "Discriminator", nameof(SingleGuidKey.Name), "__jObject" ], entityType.GetProperties().Select(p => p.Name)); diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/Inheritance/InheritanceQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/Inheritance/InheritanceQueryCosmosTest.cs index 31dc9368881..b1cac0131eb 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/Inheritance/InheritanceQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/Inheritance/InheritanceQueryCosmosTest.cs @@ -80,7 +80,7 @@ public override Task Can_use_of_type_animal(bool async) """ SELECT VALUE c FROM root c -WHERE c["Discriminator"] IN ("Eagle", "Kiwi") +WHERE c["$type"] IN ("Eagle", "Kiwi") ORDER BY c["Species"] """); }); @@ -95,7 +95,7 @@ public override Task Can_use_is_kiwi(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] IN ("Eagle", "Kiwi") AND (c["Discriminator"] = "Kiwi")) +WHERE (c["$type"] IN ("Eagle", "Kiwi") AND (c["$type"] = "Kiwi")) """); }); @@ -107,9 +107,9 @@ public override Task Can_use_is_kiwi_with_cast(bool async) AssertSql( """ -SELECT VALUE ((c["Discriminator"] = "Kiwi") ? c["FoundOn"] : 0) +SELECT VALUE ((c["$type"] = "Kiwi") ? c["FoundOn"] : 0) FROM root c -WHERE c["Discriminator"] IN ("Eagle", "Kiwi") +WHERE c["$type"] IN ("Eagle", "Kiwi") """); }); @@ -123,7 +123,7 @@ public override Task Can_use_backwards_is_animal(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Kiwi") +WHERE (c["$type"] = "Kiwi") """); }); @@ -137,7 +137,7 @@ public override Task Can_use_is_kiwi_with_other_predicate(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] IN ("Eagle", "Kiwi") AND ((c["Discriminator"] = "Kiwi") AND (c["CountryId"] = 1))) +WHERE (c["$type"] IN ("Eagle", "Kiwi") AND ((c["$type"] = "Kiwi") AND (c["CountryId"] = 1))) """); }); @@ -149,9 +149,9 @@ public override Task Can_use_is_kiwi_in_projection(bool async) AssertSql( """ -SELECT VALUE (c["Discriminator"] = "Kiwi") +SELECT VALUE (c["$type"] = "Kiwi") FROM root c -WHERE c["Discriminator"] IN ("Eagle", "Kiwi") +WHERE c["$type"] IN ("Eagle", "Kiwi") """); }); @@ -165,7 +165,7 @@ public override Task Can_use_of_type_bird(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] IN ("Eagle", "Kiwi") AND c["Discriminator"] IN ("Eagle", "Kiwi")) +WHERE (c["$type"] IN ("Eagle", "Kiwi") AND c["$type"] IN ("Eagle", "Kiwi")) ORDER BY c["Species"] """); }); @@ -180,7 +180,7 @@ public override Task Can_use_of_type_bird_predicate(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] IN ("Eagle", "Kiwi") AND (c["CountryId"] = 1)) AND c["Discriminator"] IN ("Eagle", "Kiwi")) +WHERE ((c["$type"] IN ("Eagle", "Kiwi") AND (c["CountryId"] = 1)) AND c["$type"] IN ("Eagle", "Kiwi")) ORDER BY c["Species"] """); }); @@ -195,7 +195,7 @@ public override Task Can_use_of_type_bird_with_projection(bool async) """ SELECT VALUE c["EagleId"] FROM root c -WHERE (c["Discriminator"] IN ("Eagle", "Kiwi") AND c["Discriminator"] IN ("Eagle", "Kiwi")) +WHERE (c["$type"] IN ("Eagle", "Kiwi") AND c["$type"] IN ("Eagle", "Kiwi")) """); }); @@ -209,7 +209,7 @@ public override Task Can_use_of_type_bird_first(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] IN ("Eagle", "Kiwi") AND c["Discriminator"] IN ("Eagle", "Kiwi")) +WHERE (c["$type"] IN ("Eagle", "Kiwi") AND c["$type"] IN ("Eagle", "Kiwi")) ORDER BY c["Species"] OFFSET 0 LIMIT 1 """); @@ -225,7 +225,7 @@ public override Task Can_use_of_type_kiwi(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] IN ("Eagle", "Kiwi") AND (c["Discriminator"] = "Kiwi")) +WHERE (c["$type"] IN ("Eagle", "Kiwi") AND (c["$type"] = "Kiwi")) """); }); @@ -239,7 +239,7 @@ public override Task Can_use_backwards_of_type_animal(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Kiwi") +WHERE (c["$type"] = "Kiwi") """); }); @@ -253,7 +253,7 @@ public override Task Can_use_of_type_rose(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] IN ("Daisy", "Rose") AND (c["Discriminator"] = "Rose")) +WHERE (c["$type"] IN ("Daisy", "Rose") AND (c["$type"] = "Rose")) """); }); @@ -267,7 +267,7 @@ public override Task Can_query_all_animals(bool async) """ SELECT VALUE c FROM root c -WHERE c["Discriminator"] IN ("Eagle", "Kiwi") +WHERE c["$type"] IN ("Eagle", "Kiwi") ORDER BY c["Species"] """); }); @@ -290,7 +290,7 @@ public override Task Can_query_all_plants(bool async) """ SELECT VALUE c FROM root c -WHERE c["Discriminator"] IN ("Daisy", "Rose") +WHERE c["$type"] IN ("Daisy", "Rose") ORDER BY c["id"] """); }); @@ -305,7 +305,7 @@ public override Task Can_filter_all_animals(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] IN ("Eagle", "Kiwi") AND (c["Name"] = "Great spotted kiwi")) +WHERE (c["$type"] IN ("Eagle", "Kiwi") AND (c["Name"] = "Great spotted kiwi")) ORDER BY c["Species"] """); }); @@ -320,7 +320,7 @@ public override Task Can_query_all_birds(bool async) """ SELECT VALUE c FROM root c -WHERE c["Discriminator"] IN ("Eagle", "Kiwi") +WHERE c["$type"] IN ("Eagle", "Kiwi") ORDER BY c["Species"] """); }); @@ -335,7 +335,7 @@ public override Task Can_query_just_kiwis(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Kiwi") +WHERE (c["$type"] = "Kiwi") OFFSET 0 LIMIT 2 """); }); @@ -350,7 +350,7 @@ public override Task Can_query_just_roses(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Rose") +WHERE (c["$type"] = "Rose") OFFSET 0 LIMIT 2 """); }); @@ -381,7 +381,7 @@ public override Task Can_use_of_type_kiwi_where_south_on_derived_property(bool a """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] IN ("Eagle", "Kiwi") AND (c["Discriminator"] = "Kiwi")) AND (c["FoundOn"] = 1)) +WHERE ((c["$type"] IN ("Eagle", "Kiwi") AND (c["$type"] = "Kiwi")) AND (c["FoundOn"] = 1)) """); }); @@ -395,7 +395,7 @@ public override Task Can_use_of_type_kiwi_where_north_on_derived_property(bool a """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] IN ("Eagle", "Kiwi") AND (c["Discriminator"] = "Kiwi")) AND (c["FoundOn"] = 0)) +WHERE ((c["$type"] IN ("Eagle", "Kiwi") AND (c["$type"] = "Kiwi")) AND (c["FoundOn"] = 0)) """); }); @@ -409,7 +409,7 @@ public override Task Discriminator_used_when_projection_over_derived_type(bool a """ SELECT VALUE c["FoundOn"] FROM root c -WHERE (c["Discriminator"] = "Kiwi") +WHERE (c["$type"] = "Kiwi") """); }); @@ -421,9 +421,13 @@ public override Task Discriminator_used_when_projection_over_derived_type2(bool AssertSql( """ -SELECT c["IsFlightless"], c["Discriminator"] +SELECT VALUE +{ + "IsFlightless" : c["IsFlightless"], + "Discriminator" : c["$type"] +} FROM root c -WHERE c["Discriminator"] IN ("Eagle", "Kiwi") +WHERE c["$type"] IN ("Eagle", "Kiwi") """); }); @@ -437,7 +441,7 @@ public override Task Discriminator_with_cast_in_shadow_property(bool async) """ SELECT VALUE c["Name"] FROM root c -WHERE (c["Discriminator"] IN ("Eagle", "Kiwi") AND ("Kiwi" = c["Discriminator"])) +WHERE (c["$type"] IN ("Eagle", "Kiwi") AND ("Kiwi" = c["$type"])) """); }); @@ -451,7 +455,7 @@ public override Task Discriminator_used_when_projection_over_of_type(bool async) """ SELECT VALUE c["FoundOn"] FROM root c -WHERE (c["Discriminator"] IN ("Eagle", "Kiwi") AND (c["Discriminator"] = "Kiwi")) +WHERE (c["$type"] IN ("Eagle", "Kiwi") AND (c["$type"] = "Kiwi")) """); }); @@ -504,7 +508,7 @@ public override async Task Setting_foreign_key_to_a_different_type_throws() """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Kiwi") +WHERE (c["$type"] = "Kiwi") OFFSET 0 LIMIT 2 """); } @@ -519,7 +523,7 @@ public override Task Byte_enum_value_constant_used_in_projection(bool async) """ SELECT VALUE (c["IsFlightless"] ? 0 : 1) FROM root c -WHERE (c["Discriminator"] = "Kiwi") +WHERE (c["$type"] = "Kiwi") """); }); @@ -531,7 +535,7 @@ public override async Task Member_access_on_intermediate_type_works() """ SELECT VALUE c["Name"] FROM root c -WHERE (c["Discriminator"] = "Kiwi") +WHERE (c["$type"] = "Kiwi") ORDER BY c["Name"] """); } @@ -554,7 +558,7 @@ public override Task Selecting_only_base_properties_on_base_type(bool async) """ SELECT VALUE c["Name"] FROM root c -WHERE c["Discriminator"] IN ("Eagle", "Kiwi") +WHERE c["$type"] IN ("Eagle", "Kiwi") """); }); @@ -568,7 +572,7 @@ public override Task Selecting_only_base_properties_on_derived_type(bool async) """ SELECT VALUE c["Name"] FROM root c -WHERE c["Discriminator"] IN ("Eagle", "Kiwi") +WHERE c["$type"] IN ("Eagle", "Kiwi") """); }); @@ -582,7 +586,7 @@ public override Task GetType_in_hierarchy_in_abstract_base_type(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] IN ("Eagle", "Kiwi") AND false) +WHERE (c["$type"] IN ("Eagle", "Kiwi") AND false) """); }); @@ -596,7 +600,7 @@ public override Task GetType_in_hierarchy_in_intermediate_type(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] IN ("Eagle", "Kiwi") AND false) +WHERE (c["$type"] IN ("Eagle", "Kiwi") AND false) """); }); @@ -610,7 +614,7 @@ public override Task GetType_in_hierarchy_in_leaf_type_with_sibling(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] IN ("Eagle", "Kiwi") AND (c["Discriminator"] = "Eagle")) +WHERE (c["$type"] IN ("Eagle", "Kiwi") AND (c["$type"] = "Eagle")) """); }); @@ -624,7 +628,7 @@ public override Task GetType_in_hierarchy_in_leaf_type_with_sibling2(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] IN ("Eagle", "Kiwi") AND (c["Discriminator"] = "Kiwi")) +WHERE (c["$type"] IN ("Eagle", "Kiwi") AND (c["$type"] = "Kiwi")) """); }); @@ -638,7 +642,7 @@ public override Task GetType_in_hierarchy_in_leaf_type_with_sibling2_reverse(boo """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] IN ("Eagle", "Kiwi") AND (c["Discriminator"] = "Kiwi")) +WHERE (c["$type"] IN ("Eagle", "Kiwi") AND (c["$type"] = "Kiwi")) """); }); @@ -652,7 +656,7 @@ public override Task GetType_in_hierarchy_in_leaf_type_with_sibling2_not_equal(b """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] IN ("Eagle", "Kiwi") AND (c["Discriminator"] != "Kiwi")) +WHERE (c["$type"] IN ("Eagle", "Kiwi") AND (c["$type"] != "Kiwi")) """); }); @@ -666,7 +670,7 @@ public override Task Using_is_operator_on_multiple_type_with_no_result(bool asyn """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] IN ("Eagle", "Kiwi") AND (c["Discriminator"] = "Kiwi")) AND (c["Discriminator"] = "Eagle")) +WHERE ((c["$type"] IN ("Eagle", "Kiwi") AND (c["$type"] = "Kiwi")) AND (c["$type"] = "Eagle")) """); }); @@ -680,7 +684,7 @@ public override Task Using_is_operator_with_of_type_on_multiple_type_with_no_res """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] IN ("Eagle", "Kiwi") AND (c["Discriminator"] = "Kiwi")) AND (c["Discriminator"] = "Eagle")) +WHERE ((c["$type"] IN ("Eagle", "Kiwi") AND (c["$type"] = "Kiwi")) AND (c["$type"] = "Eagle")) """); }); diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/JsonQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/JsonQueryCosmosTest.cs index 37a00de8df6..335d42d6740 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/JsonQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/JsonQueryCosmosTest.cs @@ -28,7 +28,7 @@ public override Task Basic_json_projection_enum_inside_json_entity(bool async) """ SELECT c["Id"], c["OwnedReferenceRoot"]["OwnedReferenceBranch"]["Enum"] FROM root c -WHERE (c["Discriminator"] = "Basic") +WHERE (c["$type"] = "Basic") """); }); @@ -64,7 +64,7 @@ public override Task Basic_json_projection_owned_collection_root_NoTrackingWithI """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Basic") +WHERE (c["$type"] = "Basic") """); }); @@ -78,7 +78,7 @@ public override Task Basic_json_projection_owned_reference_branch_NoTrackingWith """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Basic") +WHERE (c["$type"] = "Basic") """); }); @@ -92,7 +92,7 @@ public override Task Basic_json_projection_owned_reference_duplicated2_NoTrackin """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Basic") +WHERE (c["$type"] = "Basic") ORDER BY c["Id"] """); }); @@ -107,7 +107,7 @@ public override Task Basic_json_projection_owned_reference_duplicated_NoTracking """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Basic") +WHERE (c["$type"] = "Basic") ORDER BY c["Id"] """); }); @@ -122,7 +122,7 @@ public override Task Basic_json_projection_owned_reference_leaf(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Basic") +WHERE (c["$type"] = "Basic") """); }); @@ -137,7 +137,7 @@ public override Task Basic_json_projection_owned_reference_root_NoTrackingWithId """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Basic") +WHERE (c["$type"] = "Basic") """); }); @@ -151,7 +151,7 @@ public override Task Basic_json_projection_owner_entity_duplicated_NoTrackingWit """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "SingleOwned") +WHERE (c["$type"] = "SingleOwned") """); }); @@ -165,7 +165,7 @@ public override Task Basic_json_projection_owner_entity_NoTrackingWithIdentityRe """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Basic") +WHERE (c["$type"] = "Basic") """); }); @@ -179,7 +179,7 @@ public override Task Basic_json_projection_owner_entity_twice_NoTrackingWithIden """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Basic") +WHERE (c["$type"] = "Basic") """); }); @@ -193,7 +193,7 @@ public override Task Basic_json_projection_scalar(bool async) """ SELECT VALUE c["OwnedReferenceRoot"]["Name"] FROM root c -WHERE (c["Discriminator"] = "Basic") +WHERE (c["$type"] = "Basic") """); }); @@ -218,7 +218,7 @@ public override Task Custom_naming_projection_owned_collection(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "CustomNaming") +WHERE (c["$type"] = "CustomNaming") ORDER BY c["Id"] """); }); @@ -233,7 +233,7 @@ public override Task Custom_naming_projection_owned_reference(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "CustomNaming") +WHERE (c["$type"] = "CustomNaming") """); }); @@ -247,7 +247,7 @@ public override Task Custom_naming_projection_owned_scalar(bool async) """ SELECT VALUE c["OwnedReferenceRoot"]["OwnedReferenceBranch"]["Fraction"] FROM root c -WHERE (c["Discriminator"] = "CustomNaming") +WHERE (c["$type"] = "CustomNaming") """); }); @@ -261,7 +261,7 @@ public override Task Custom_naming_projection_owner_entity(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "CustomNaming") +WHERE (c["$type"] = "CustomNaming") """); }); @@ -315,7 +315,7 @@ public override Task Json_all_types_entity_projection(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "AllTypes") +WHERE (c["$type"] = "AllTypes") """); }); @@ -331,7 +331,7 @@ public override Task Json_all_types_projection_from_owned_entity_reference(bool """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "AllTypes") +WHERE (c["$type"] = "AllTypes") """); }); @@ -345,7 +345,7 @@ public override Task Json_all_types_projection_individual_properties(bool async) """ SELECT c["Reference"]["TestDefaultString"], c["Reference"]["TestMaxLengthString"], c["Reference"]["TestBoolean"], c["Reference"]["TestByte"], c["Reference"]["TestCharacter"], c["Reference"]["TestDateTime"], c["Reference"]["TestDateTimeOffset"], c["Reference"]["TestDecimal"], c["Reference"]["TestDouble"], c["Reference"]["TestGuid"], c["Reference"]["TestInt16"], c["Reference"]["TestInt32"], c["Reference"]["TestInt64"], c["Reference"]["TestSignedByte"], c["Reference"]["TestSingle"], c["Reference"]["TestTimeSpan"], c["Reference"]["TestDateOnly"], c["Reference"]["TestTimeOnly"], c["Reference"]["TestUnsignedInt16"], c["Reference"]["TestUnsignedInt32"], c["Reference"]["TestUnsignedInt64"], c["Reference"]["TestEnum"], c["Reference"]["TestEnumWithIntConverter"], c["Reference"]["TestNullableEnum"], c["Reference"]["TestNullableEnumWithIntConverter"], c["Reference"]["TestNullableEnumWithConverterThatHandlesNulls"] FROM root c -WHERE (c["Discriminator"] = "AllTypes") +WHERE (c["$type"] = "AllTypes") """); }); @@ -360,7 +360,7 @@ public override Task Json_boolean_predicate(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND c["Reference"]["TestBoolean"]) +WHERE ((c["$type"] = "AllTypes") AND c["Reference"]["TestBoolean"]) """); }); @@ -374,7 +374,7 @@ public override Task Json_boolean_predicate_negated(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND NOT(c["Reference"]["TestBoolean"])) +WHERE ((c["$type"] = "AllTypes") AND NOT(c["Reference"]["TestBoolean"])) """); }); @@ -388,7 +388,7 @@ public override Task Json_boolean_projection(bool async) """ SELECT VALUE c["Reference"]["TestBoolean"] FROM root c -WHERE (c["Discriminator"] = "AllTypes") +WHERE (c["$type"] = "AllTypes") """); }); @@ -402,7 +402,7 @@ public override Task Json_boolean_projection_negated(bool async) """ SELECT VALUE NOT(c["Reference"]["TestBoolean"]) FROM root c -WHERE (c["Discriminator"] = "AllTypes") +WHERE (c["$type"] = "AllTypes") """); }); @@ -468,7 +468,7 @@ public override Task Json_collection_Any_with_predicate(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Basic") AND EXISTS ( +WHERE ((c["$type"] = "Basic") AND EXISTS ( SELECT 1 FROM o IN c["OwnedReferenceRoot"]["OwnedCollectionBranch"] WHERE (o["OwnedReferenceLeaf"]["SomethingSomething"] = "e1_r_c1_r"))) @@ -515,7 +515,7 @@ SELECT VALUE "CollectionElement" : c["OwnedCollectionRoot"][0]["Number"] } FROM root c -WHERE (c["Discriminator"] = "Basic") +WHERE (c["$type"] = "Basic") """); }); @@ -529,7 +529,7 @@ public override Task Json_collection_ElementAt_in_predicate(bool async) """ SELECT VALUE c["Id"] FROM root c -WHERE ((c["Discriminator"] = "Basic") AND (c["OwnedCollectionRoot"][1]["Name"] != "Foo")) +WHERE ((c["$type"] = "Basic") AND (c["OwnedCollectionRoot"][1]["Name"] != "Foo")) """); }); @@ -597,7 +597,7 @@ public override Task Json_collection_index_in_predicate_using_constant(bool asyn """ SELECT VALUE c["Id"] FROM root c -WHERE ((c["Discriminator"] = "Basic") AND (c["OwnedCollectionRoot"][0]["Name"] != "Foo")) +WHERE ((c["$type"] = "Basic") AND (c["OwnedCollectionRoot"][0]["Name"] != "Foo")) """); }); @@ -613,7 +613,7 @@ public override Task Json_collection_index_in_predicate_using_variable(bool asyn SELECT VALUE c["Id"] FROM root c -WHERE ((c["Discriminator"] = "Basic") AND (c["OwnedCollectionRoot"][@prm]["Name"] != "Foo")) +WHERE ((c["$type"] = "Basic") AND (c["OwnedCollectionRoot"][@prm]["Name"] != "Foo")) """); }); @@ -863,7 +863,7 @@ public override Task Json_collection_in_projection_with_composition_count(bool a """ SELECT VALUE ARRAY_LENGTH(c["OwnedCollectionRoot"]) FROM root c -WHERE (c["Discriminator"] = "Basic") +WHERE (c["$type"] = "Basic") ORDER BY c["Id"] """); }); @@ -889,7 +889,7 @@ public override Task Json_collection_of_primitives_contains_in_predicate(bool as """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Basic") AND ARRAY_CONTAINS(c["OwnedReferenceRoot"]["Names"], "e1_r1")) +WHERE ((c["$type"] = "Basic") AND ARRAY_CONTAINS(c["OwnedReferenceRoot"]["Names"], "e1_r1")) """); }); @@ -903,7 +903,7 @@ public override Task Json_collection_of_primitives_index_used_in_orderby(bool as """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Basic") +WHERE (c["$type"] = "Basic") ORDER BY c["OwnedReferenceRoot"]["Numbers"][0] """); }); @@ -918,7 +918,7 @@ public override Task Json_collection_of_primitives_index_used_in_predicate(bool """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Basic") AND (c["OwnedReferenceRoot"]["Names"][0] = "e1_r1")) +WHERE ((c["$type"] = "Basic") AND (c["OwnedReferenceRoot"]["Names"][0] = "e1_r1")) """); }); @@ -949,7 +949,7 @@ public override Task Json_collection_of_primitives_SelectMany(bool async) SELECT VALUE n FROM root c JOIN n IN c["OwnedReferenceRoot"]["Names"] -WHERE (c["Discriminator"] = "Basic") +WHERE (c["$type"] = "Basic") """); }); @@ -987,7 +987,7 @@ public override Task Json_collection_Skip(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Basic") AND (ARRAY( +WHERE ((c["$type"] = "Basic") AND (ARRAY( SELECT VALUE o["OwnedReferenceLeaf"]["SomethingSomething"] FROM o IN (SELECT VALUE ARRAY_SLICE(c["OwnedReferenceRoot"]["OwnedCollectionBranch"], 1)))[0] = "e1_r_c2_r")) """); @@ -1019,7 +1019,7 @@ public override Task Json_collection_Where_ElementAt(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Basic") AND (ARRAY( +WHERE ((c["$type"] = "Basic") AND (ARRAY( SELECT VALUE o["OwnedReferenceLeaf"]["SomethingSomething"] FROM o IN c["OwnedReferenceRoot"]["OwnedCollectionBranch"] WHERE (o["Enum"] = -3))[0] = "e1_r_c2_r")) @@ -1036,7 +1036,7 @@ public override Task Json_collection_within_collection_Count(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Basic") AND EXISTS ( +WHERE ((c["$type"] = "Basic") AND EXISTS ( SELECT 1 FROM o IN c["OwnedCollectionRoot"] WHERE (ARRAY_LENGTH(o["OwnedCollectionBranch"]) = 2))) @@ -1127,7 +1127,7 @@ public override Task Json_predicate_on_bool_converted_to_int_zero_one(bool async """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["BoolConvertedToIntZeroOne"] = 1)) +WHERE ((c["$type"] = "Converters") AND (c["Reference"]["BoolConvertedToIntZeroOne"] = 1)) """); }); @@ -1141,7 +1141,7 @@ public override Task Json_predicate_on_bool_converted_to_int_zero_one_with_expli """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["BoolConvertedToIntZeroOne"] = 0)) +WHERE ((c["$type"] = "Converters") AND (c["Reference"]["BoolConvertedToIntZeroOne"] = 0)) """); }); @@ -1155,7 +1155,7 @@ public override Task Json_predicate_on_bool_converted_to_string_True_False(bool """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["BoolConvertedToStringTrueFalse"] = "True")) +WHERE ((c["$type"] = "Converters") AND (c["Reference"]["BoolConvertedToStringTrueFalse"] = "True")) """); }); @@ -1169,7 +1169,7 @@ public override Task Json_predicate_on_bool_converted_to_string_True_False_with_ """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["BoolConvertedToStringTrueFalse"] = "True")) +WHERE ((c["$type"] = "Converters") AND (c["Reference"]["BoolConvertedToStringTrueFalse"] = "True")) """); }); @@ -1183,7 +1183,7 @@ public override Task Json_predicate_on_bool_converted_to_string_Y_N(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["BoolConvertedToStringYN"] = "Y")) +WHERE ((c["$type"] = "Converters") AND (c["Reference"]["BoolConvertedToStringYN"] = "Y")) """); }); @@ -1197,7 +1197,7 @@ public override Task Json_predicate_on_bool_converted_to_string_Y_N_with_explici """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["BoolConvertedToStringYN"] = "N")) +WHERE ((c["$type"] = "Converters") AND (c["Reference"]["BoolConvertedToStringYN"] = "N")) """); }); @@ -1212,7 +1212,7 @@ public override Task Json_predicate_on_byte(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestByte"] != 3)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestByte"] != 3)) """); }); @@ -1227,7 +1227,7 @@ public override Task Json_predicate_on_byte_array(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestByteArray"] != "AQID")) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestByteArray"] != "AQID")) """); }); @@ -1242,7 +1242,7 @@ public override Task Json_predicate_on_character(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestCharacter"] != "z")) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestCharacter"] != "z")) """); }); @@ -1257,7 +1257,7 @@ public override Task Json_predicate_on_dateonly(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestDateOnly"] != "0003-02-01")) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestDateOnly"] != "0003-02-01")) """); }); @@ -1272,7 +1272,7 @@ public override Task Json_predicate_on_datetime(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestDateTime"] != "2000-01-03T00:00:00")) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestDateTime"] != "2000-01-03T00:00:00")) """); }); @@ -1287,7 +1287,7 @@ public override Task Json_predicate_on_datetimeoffset(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestDateTimeOffset"] != "2000-01-04T00:00:00+03:02")) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestDateTimeOffset"] != "2000-01-04T00:00:00+03:02")) """); }); @@ -1302,7 +1302,7 @@ public override Task Json_predicate_on_decimal(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestDecimal"] != 1.35)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestDecimal"] != 1.35)) """); }); @@ -1317,7 +1317,7 @@ public override Task Json_predicate_on_default_string(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestDefaultString"] != "MyDefaultStringInReference1")) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestDefaultString"] != "MyDefaultStringInReference1")) """); }); @@ -1332,7 +1332,7 @@ public override Task Json_predicate_on_double(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestDouble"] != 33.25)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestDouble"] != 33.25)) """); }); @@ -1347,7 +1347,7 @@ public override Task Json_predicate_on_enum(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestEnum"] != 2)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestEnum"] != 2)) """); }); @@ -1362,7 +1362,7 @@ public override Task Json_predicate_on_enumwithintconverter(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestEnumWithIntConverter"] != -3)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestEnumWithIntConverter"] != -3)) """); }); @@ -1377,7 +1377,7 @@ public override Task Json_predicate_on_guid(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestGuid"] != "00000000-0000-0000-0000-000000000000")) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestGuid"] != "00000000-0000-0000-0000-000000000000")) """); }); @@ -1392,7 +1392,7 @@ public override Task Json_predicate_on_int16(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestInt16"] != 3)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestInt16"] != 3)) """); }); @@ -1407,7 +1407,7 @@ public override Task Json_predicate_on_int32(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestInt32"] != 33)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestInt32"] != 33)) """); }); @@ -1422,7 +1422,7 @@ public override Task Json_predicate_on_int64(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestInt64"] != 333)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestInt64"] != 333)) """); }); @@ -1436,7 +1436,7 @@ public override Task Json_predicate_on_int_zero_one_converted_to_bool(bool async """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["IntZeroOneConvertedToBool"] = true)) +WHERE ((c["$type"] = "Converters") AND (c["Reference"]["IntZeroOneConvertedToBool"] = true)) """); }); @@ -1451,7 +1451,7 @@ public override Task Json_predicate_on_max_length_string(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestMaxLengthString"] != "Foo")) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestMaxLengthString"] != "Foo")) """); }); @@ -1466,7 +1466,7 @@ public override Task Json_predicate_on_nullableenum1(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestNullableEnum"] != -1)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestNullableEnum"] != -1)) """); }); @@ -1481,7 +1481,7 @@ public override Task Json_predicate_on_nullableenum2(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestNullableEnum"] != null)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestNullableEnum"] != null)) """); }); @@ -1496,7 +1496,7 @@ public override Task Json_predicate_on_nullableenumwithconverter1(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestNullableEnumWithIntConverter"] != 2)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestNullableEnumWithIntConverter"] != 2)) """); }); @@ -1511,7 +1511,7 @@ public override Task Json_predicate_on_nullableenumwithconverter2(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestNullableEnumWithIntConverter"] != null)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestNullableEnumWithIntConverter"] != null)) """); }); @@ -1526,7 +1526,7 @@ public override Task Json_predicate_on_nullableenumwithconverterthathandlesnulls """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestNullableEnumWithConverterThatHandlesNulls"] != "One")) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestNullableEnumWithConverterThatHandlesNulls"] != "One")) """); }); @@ -1550,7 +1550,7 @@ public override Task Json_predicate_on_nullableint321(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestNullableInt32"] != 100)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestNullableInt32"] != 100)) """); }); @@ -1565,7 +1565,7 @@ public override Task Json_predicate_on_nullableint322(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestNullableInt32"] != null)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestNullableInt32"] != null)) """); }); @@ -1580,7 +1580,7 @@ public override Task Json_predicate_on_signedbyte(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestSignedByte"] != 100)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestSignedByte"] != 100)) """); }); @@ -1595,7 +1595,7 @@ public override Task Json_predicate_on_single(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestSingle"] != 10.4)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestSingle"] != 10.4)) """); }); @@ -1610,7 +1610,7 @@ public override Task Json_predicate_on_string_condition(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND ((NOT(c["Reference"]["TestBoolean"]) ? c["Reference"]["TestMaxLengthString"] : c["Reference"]["TestDefaultString"]) = "MyDefaultStringInReference1")) +WHERE ((c["$type"] = "AllTypes") AND ((NOT(c["Reference"]["TestBoolean"]) ? c["Reference"]["TestMaxLengthString"] : c["Reference"]["TestDefaultString"]) = "MyDefaultStringInReference1")) """); }); @@ -1624,7 +1624,7 @@ public override Task Json_predicate_on_string_True_False_converted_to_bool(bool """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["StringTrueFalseConvertedToBool"] = false)) +WHERE ((c["$type"] = "Converters") AND (c["Reference"]["StringTrueFalseConvertedToBool"] = false)) """); }); @@ -1638,7 +1638,7 @@ public override Task Json_predicate_on_string_Y_N_converted_to_bool(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Converters") AND (c["Reference"]["StringYNConvertedToBool"] = false)) +WHERE ((c["$type"] = "Converters") AND (c["Reference"]["StringYNConvertedToBool"] = false)) """); }); @@ -1653,7 +1653,7 @@ public override Task Json_predicate_on_timeonly(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestTimeOnly"] != "03:02:00")) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestTimeOnly"] != "03:02:00")) """); }); @@ -1668,7 +1668,7 @@ public override Task Json_predicate_on_timespan(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestTimeSpan"] != "03:02:00")) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestTimeSpan"] != "03:02:00")) """); }); @@ -1683,7 +1683,7 @@ public override Task Json_predicate_on_unisgnedint16(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestUnsignedInt16"] != 100)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestUnsignedInt16"] != 100)) """); }); @@ -1698,7 +1698,7 @@ public override Task Json_predicate_on_unsignedint32(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestUnsignedInt32"] != 1000)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestUnsignedInt32"] != 1000)) """); }); @@ -1713,7 +1713,7 @@ public override Task Json_predicate_on_unsignedint64(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "AllTypes") AND (c["Reference"]["TestUnsignedInt64"] != 10000)) +WHERE ((c["$type"] = "AllTypes") AND (c["Reference"]["TestUnsignedInt64"] != 10000)) """); }); @@ -1751,7 +1751,7 @@ public override Task Json_projection_enum_with_custom_conversion(bool async) """ SELECT c["Id"], c["OwnedReferenceRoot"]["Enum"] FROM root c -WHERE (c["Discriminator"] = "CustomNaming") +WHERE (c["$type"] = "CustomNaming") """); }); @@ -1782,7 +1782,7 @@ public override Task Json_projection_nothing_interesting_AsNoTrackingWithIdentit """ SELECT c["Id"], c["Name"] FROM root c -WHERE (c["Discriminator"] = "Basic") +WHERE (c["$type"] = "Basic") """); }); @@ -1820,7 +1820,7 @@ public override Task Json_projection_owner_entity_AsNoTrackingWithIdentityResolu """ SELECT c["Id"], c FROM root c -WHERE (c["Discriminator"] = "Basic") +WHERE (c["$type"] = "Basic") """); }); @@ -1887,7 +1887,7 @@ public override Task Json_property_in_predicate(bool async) """ SELECT VALUE c["Id"] FROM root c -WHERE ((c["Discriminator"] = "Basic") AND (c["OwnedReferenceRoot"]["OwnedReferenceBranch"]["Fraction"] < 20.5)) +WHERE ((c["$type"] = "Basic") AND (c["OwnedReferenceRoot"]["OwnedReferenceBranch"]["Fraction"] < 20.5)) """); }); @@ -1901,7 +1901,7 @@ public override Task Json_scalar_length(bool async) """ SELECT VALUE c["Name"] FROM root c -WHERE ((c["Discriminator"] = "Basic") AND (LENGTH(c["OwnedReferenceRoot"]["Name"]) > 2)) +WHERE ((c["$type"] = "Basic") AND (LENGTH(c["OwnedReferenceRoot"]["Name"]) > 2)) """); }); @@ -1915,7 +1915,7 @@ public override Task Json_scalar_optional_null_semantics(bool async) """ SELECT VALUE c["Name"] FROM root c -WHERE ((c["Discriminator"] = "Basic") AND (c["OwnedReferenceRoot"]["Name"] != c["OwnedReferenceRoot"]["OwnedReferenceBranch"]["OwnedReferenceLeaf"]["SomethingSomething"])) +WHERE ((c["$type"] = "Basic") AND (c["OwnedReferenceRoot"]["Name"] != c["OwnedReferenceRoot"]["OwnedReferenceBranch"]["OwnedReferenceLeaf"]["SomethingSomething"])) """); }); @@ -1929,7 +1929,7 @@ public override Task Json_scalar_required_null_semantics(bool async) """ SELECT VALUE c["Name"] FROM root c -WHERE ((c["Discriminator"] = "Basic") AND (c["OwnedReferenceRoot"]["Number"] != LENGTH(c["OwnedReferenceRoot"]["Name"]))) +WHERE ((c["$type"] = "Basic") AND (c["OwnedReferenceRoot"]["Number"] != LENGTH(c["OwnedReferenceRoot"]["Name"]))) """); }); @@ -1995,7 +1995,7 @@ public override Task Json_with_include_on_json_entity(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Basic") +WHERE (c["$type"] = "Basic") """); }); @@ -2061,7 +2061,7 @@ public override Task Project_entity_with_single_owned(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "SingleOwned") +WHERE (c["$type"] = "SingleOwned") """); }); diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/ReadItemPartitionKeyQueryInheritanceTestBase.cs b/test/EFCore.Cosmos.FunctionalTests/Query/ReadItemPartitionKeyQueryInheritanceTestBase.cs index 134128da1eb..1c1b9b13417 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/ReadItemPartitionKeyQueryInheritanceTestBase.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/ReadItemPartitionKeyQueryInheritanceTestBase.cs @@ -340,7 +340,7 @@ public virtual Task ReadItem_with_single_explicit_discriminator_mapping_leaf() async: true, ss => ss.Set() .Where(e => e.Id == Guid.Parse("188D3253-81BE-4A87-B58F-A2BD07E6B98C") - && EF.Property(e, "$type") == nameof(DerivedSinglePartitionKeyEntity) + && EF.Property(e, "Discriminator") == nameof(DerivedSinglePartitionKeyEntity) && e.PartitionKey == partitionKey), ss => ss.Set() .Where(e => e.Id == Guid.Parse("188D3253-81BE-4A87-B58F-A2BD07E6B98C") && e.PartitionKey == partitionKey)); @@ -355,7 +355,7 @@ public virtual Task ReadItem_with_single_explicit_incorrect_discriminator_mappin async: true, ss => ss.Set() .Where(e => e.Id == Guid.Parse("188D3253-81BE-4A87-B58F-A2BD07E6B98C") - && EF.Property(e, "$type") == nameof(SinglePartitionKeyEntity) + && EF.Property(e, "Discriminator") == nameof(SinglePartitionKeyEntity) && e.PartitionKey == partitionKey), ss => ss.Set().Where(e => false), assertEmpty: true); @@ -371,7 +371,7 @@ public virtual Task ReadItem_with_single_explicit_parameterized_discriminator_ma async: true, ss => ss.Set() .Where(e => e.Id == Guid.Parse("188D3253-81BE-4A87-B58F-A2BD07E6B98C") - && EF.Property(e, "$type") == discriminator + && EF.Property(e, "Discriminator") == discriminator && e.PartitionKey == partitionKey), ss => ss.Set().Where(e => e.Id == Guid.Parse("188D3253-81BE-4A87-B58F-A2BD07E6B98C") && e.PartitionKey == partitionKey)); diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/ReadItemPartitionKeyQueryTestBase.cs b/test/EFCore.Cosmos.FunctionalTests/Query/ReadItemPartitionKeyQueryTestBase.cs index 9cb0b7a6195..c18b808ae35 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/ReadItemPartitionKeyQueryTestBase.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/ReadItemPartitionKeyQueryTestBase.cs @@ -408,7 +408,7 @@ public virtual Task ReadItem_with_single_explicit_discriminator_mapping() async: true, ss => ss.Set() .Where(e => e.Id == Guid.Parse("B29BCED8-E1E5-420E-82D7-1C7A51703D34") - && EF.Property(e, "$type") == nameof(SinglePartitionKeyEntity) + && EF.Property(e, "Discriminator") == nameof(SinglePartitionKeyEntity) && e.PartitionKey == partitionKey), ss => ss.Set() .Where(e => e.Id == Guid.Parse("B29BCED8-E1E5-420E-82D7-1C7A51703D34") && e.PartitionKey == partitionKey)); @@ -423,7 +423,7 @@ public virtual Task ReadItem_with_single_explicit_incorrect_discriminator_mappin async: true, ss => ss.Set() .Where(e => e.Id == Guid.Parse("B29BCED8-E1E5-420E-82D7-1C7A51703D34") - && EF.Property(e, "$type") == nameof(DerivedSinglePartitionKeyEntity) + && EF.Property(e, "Discriminator") == nameof(DerivedSinglePartitionKeyEntity) && e.PartitionKey == partitionKey), ss => ss.Set().Where(e => false), assertEmpty: true); @@ -439,7 +439,7 @@ public virtual Task ReadItem_with_single_explicit_parameterized_discriminator_ma async: true, ss => ss.Set() .Where(e => e.Id == Guid.Parse("B29BCED8-E1E5-420E-82D7-1C7A51703D34") - && EF.Property(e, "$type") == discriminator + && EF.Property(e, "Discriminator") == discriminator && e.PartitionKey == partitionKey), ss => ss.Set().Where(e => e.Id == Guid.Parse("B29BCED8-E1E5-420E-82D7-1C7A51703D34") && e.PartitionKey == partitionKey)); diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/ManyTypesEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/ManyTypesEntityType.cs index c9b6455ec6a..0c450d09919 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/ManyTypesEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/ManyTypesEntityType.cs @@ -82,25 +82,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas id.SetCurrentValueComparer(new CurrentProviderValueComparer(id)); id.SetSentinelFromProviderValue(0); - var type = runtimeEntityType.AddProperty( - "$type", - typeof(string), - afterSaveBehavior: PropertySaveBehavior.Throw, - valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); - type.SetAccessors( - string (IInternalEntry entry) => entry.ReadShadowValue(0), - string (IInternalEntry entry) => entry.ReadShadowValue(0), - string (IInternalEntry entry) => entry.ReadOriginalValue(type, 1), - string (IInternalEntry entry) => entry.GetCurrentValue(type)); - type.SetPropertyIndexes( - index: 1, - originalValueIndex: 1, - shadowIndex: 0, - relationshipIndex: -1, - storeGenerationIndex: -1); - type.TypeMapping = CosmosTypeMapping.Default.Clone( - jsonValueReaderWriter: JsonStringReaderWriter.Instance); - var @bool = runtimeEntityType.AddProperty( "Bool", typeof(bool), @@ -125,11 +106,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas @bool.SetAccessors( bool (IInternalEntry entry) => ManyTypesUnsafeAccessors.Bool(((CompiledModelTestBase.ManyTypes)(entry.Entity))), bool (IInternalEntry entry) => ManyTypesUnsafeAccessors.Bool(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - bool (IInternalEntry entry) => entry.ReadOriginalValue(@bool, 2), + bool (IInternalEntry entry) => entry.ReadOriginalValue(@bool, 1), bool (IInternalEntry entry) => entry.GetCurrentValue(@bool)); @bool.SetPropertyIndexes( - index: 2, - originalValueIndex: 2, + index: 1, + originalValueIndex: 1, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -159,11 +140,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas boolArray.SetAccessors( bool[] (IInternalEntry entry) => ManyTypesUnsafeAccessors.BoolArray(((CompiledModelTestBase.ManyTypes)(entry.Entity))), bool[] (IInternalEntry entry) => ManyTypesUnsafeAccessors.BoolArray(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - bool[] (IInternalEntry entry) => entry.ReadOriginalValue(boolArray, 3), + bool[] (IInternalEntry entry) => entry.ReadOriginalValue(boolArray, 2), bool[] (IInternalEntry entry) => entry.GetCurrentValue(boolArray)); boolArray.SetPropertyIndexes( - index: 3, - originalValueIndex: 3, + index: 2, + originalValueIndex: 2, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -200,11 +181,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas boolNestedCollection.SetAccessors( bool[][] (IInternalEntry entry) => ManyTypesUnsafeAccessors.BoolNestedCollection(((CompiledModelTestBase.ManyTypes)(entry.Entity))), bool[][] (IInternalEntry entry) => ManyTypesUnsafeAccessors.BoolNestedCollection(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - bool[][] (IInternalEntry entry) => entry.ReadOriginalValue(boolNestedCollection, 4), + bool[][] (IInternalEntry entry) => entry.ReadOriginalValue(boolNestedCollection, 3), bool[][] (IInternalEntry entry) => entry.GetCurrentValue(boolNestedCollection)); boolNestedCollection.SetPropertyIndexes( - index: 4, - originalValueIndex: 4, + index: 3, + originalValueIndex: 3, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -247,11 +228,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas boolReadOnlyCollection.SetAccessors( IReadOnlyCollection (IInternalEntry entry) => ((IReadOnlyCollection)(ManyTypesUnsafeAccessors._boolReadOnlyCollection(((CompiledModelTestBase.ManyTypes)(entry.Entity))))), IReadOnlyCollection (IInternalEntry entry) => ((IReadOnlyCollection)(ManyTypesUnsafeAccessors._boolReadOnlyCollection(((CompiledModelTestBase.ManyTypes)(entry.Entity))))), - IReadOnlyCollection (IInternalEntry entry) => entry.ReadOriginalValue>(boolReadOnlyCollection, 5), + IReadOnlyCollection (IInternalEntry entry) => entry.ReadOriginalValue>(boolReadOnlyCollection, 4), IReadOnlyCollection (IInternalEntry entry) => entry.GetCurrentValue>(boolReadOnlyCollection)); boolReadOnlyCollection.SetPropertyIndexes( - index: 5, - originalValueIndex: 5, + index: 4, + originalValueIndex: 4, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -288,11 +269,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas boolToStringConverterProperty.SetAccessors( bool (IInternalEntry entry) => ManyTypesUnsafeAccessors.BoolToStringConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), bool (IInternalEntry entry) => ManyTypesUnsafeAccessors.BoolToStringConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - bool (IInternalEntry entry) => entry.ReadOriginalValue(boolToStringConverterProperty, 6), + bool (IInternalEntry entry) => entry.ReadOriginalValue(boolToStringConverterProperty, 5), bool (IInternalEntry entry) => entry.GetCurrentValue(boolToStringConverterProperty)); boolToStringConverterProperty.SetPropertyIndexes( - index: 6, - originalValueIndex: 6, + index: 5, + originalValueIndex: 5, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -328,11 +309,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas boolToTwoValuesConverterProperty.SetAccessors( bool (IInternalEntry entry) => ManyTypesUnsafeAccessors.BoolToTwoValuesConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), bool (IInternalEntry entry) => ManyTypesUnsafeAccessors.BoolToTwoValuesConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - bool (IInternalEntry entry) => entry.ReadOriginalValue(boolToTwoValuesConverterProperty, 7), + bool (IInternalEntry entry) => entry.ReadOriginalValue(boolToTwoValuesConverterProperty, 6), bool (IInternalEntry entry) => entry.GetCurrentValue(boolToTwoValuesConverterProperty)); boolToTwoValuesConverterProperty.SetPropertyIndexes( - index: 7, - originalValueIndex: 7, + index: 6, + originalValueIndex: 6, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -369,11 +350,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas boolToZeroOneConverterProperty.SetAccessors( bool (IInternalEntry entry) => ManyTypesUnsafeAccessors.BoolToZeroOneConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), bool (IInternalEntry entry) => ManyTypesUnsafeAccessors.BoolToZeroOneConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - bool (IInternalEntry entry) => entry.ReadOriginalValue(boolToZeroOneConverterProperty, 8), + bool (IInternalEntry entry) => entry.ReadOriginalValue(boolToZeroOneConverterProperty, 7), bool (IInternalEntry entry) => entry.GetCurrentValue(boolToZeroOneConverterProperty)); boolToZeroOneConverterProperty.SetPropertyIndexes( - index: 8, - originalValueIndex: 8, + index: 7, + originalValueIndex: 7, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -409,11 +390,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas bytes.SetAccessors( byte[] (IInternalEntry entry) => ManyTypesUnsafeAccessors.Bytes(((CompiledModelTestBase.ManyTypes)(entry.Entity))), byte[] (IInternalEntry entry) => ManyTypesUnsafeAccessors.Bytes(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - byte[] (IInternalEntry entry) => entry.ReadOriginalValue(bytes, 9), + byte[] (IInternalEntry entry) => entry.ReadOriginalValue(bytes, 8), byte[] (IInternalEntry entry) => entry.GetCurrentValue(bytes)); bytes.SetPropertyIndexes( - index: 9, - originalValueIndex: 9, + index: 8, + originalValueIndex: 8, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -451,11 +432,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas bytesToStringConverterProperty.SetAccessors( byte[] (IInternalEntry entry) => ManyTypesUnsafeAccessors.BytesToStringConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), byte[] (IInternalEntry entry) => ManyTypesUnsafeAccessors.BytesToStringConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - byte[] (IInternalEntry entry) => entry.ReadOriginalValue(bytesToStringConverterProperty, 10), + byte[] (IInternalEntry entry) => entry.ReadOriginalValue(bytesToStringConverterProperty, 9), byte[] (IInternalEntry entry) => entry.GetCurrentValue(bytesToStringConverterProperty)); bytesToStringConverterProperty.SetPropertyIndexes( - index: 10, - originalValueIndex: 10, + index: 9, + originalValueIndex: 9, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -492,11 +473,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas castingConverterProperty.SetAccessors( int (IInternalEntry entry) => ManyTypesUnsafeAccessors.CastingConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), int (IInternalEntry entry) => ManyTypesUnsafeAccessors.CastingConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - int (IInternalEntry entry) => entry.ReadOriginalValue(castingConverterProperty, 11), + int (IInternalEntry entry) => entry.ReadOriginalValue(castingConverterProperty, 10), int (IInternalEntry entry) => entry.GetCurrentValue(castingConverterProperty)); castingConverterProperty.SetPropertyIndexes( - index: 11, - originalValueIndex: 11, + index: 10, + originalValueIndex: 10, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -533,11 +514,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas @char.SetAccessors( char (IInternalEntry entry) => ManyTypesUnsafeAccessors.Char(((CompiledModelTestBase.ManyTypes)(entry.Entity))), char (IInternalEntry entry) => ManyTypesUnsafeAccessors.Char(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - char (IInternalEntry entry) => entry.ReadOriginalValue(@char, 12), + char (IInternalEntry entry) => entry.ReadOriginalValue(@char, 11), char (IInternalEntry entry) => entry.GetCurrentValue(@char)); @char.SetPropertyIndexes( - index: 12, - originalValueIndex: 12, + index: 11, + originalValueIndex: 11, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -567,11 +548,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas charArray.SetAccessors( char[] (IInternalEntry entry) => ManyTypesUnsafeAccessors.CharArray(((CompiledModelTestBase.ManyTypes)(entry.Entity))), char[] (IInternalEntry entry) => ManyTypesUnsafeAccessors.CharArray(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - char[] (IInternalEntry entry) => entry.ReadOriginalValue(charArray, 13), + char[] (IInternalEntry entry) => entry.ReadOriginalValue(charArray, 12), char[] (IInternalEntry entry) => entry.GetCurrentValue(charArray)); charArray.SetPropertyIndexes( - index: 13, - originalValueIndex: 13, + index: 12, + originalValueIndex: 12, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -608,11 +589,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas charNestedCollection.SetAccessors( char[][] (IInternalEntry entry) => ManyTypesUnsafeAccessors.CharNestedCollection(((CompiledModelTestBase.ManyTypes)(entry.Entity))), char[][] (IInternalEntry entry) => ManyTypesUnsafeAccessors.CharNestedCollection(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - char[][] (IInternalEntry entry) => entry.ReadOriginalValue(charNestedCollection, 14), + char[][] (IInternalEntry entry) => entry.ReadOriginalValue(charNestedCollection, 13), char[][] (IInternalEntry entry) => entry.GetCurrentValue(charNestedCollection)); charNestedCollection.SetPropertyIndexes( - index: 14, - originalValueIndex: 14, + index: 13, + originalValueIndex: 13, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -656,11 +637,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas charToStringConverterProperty.SetAccessors( char (IInternalEntry entry) => ManyTypesUnsafeAccessors.CharToStringConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), char (IInternalEntry entry) => ManyTypesUnsafeAccessors.CharToStringConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - char (IInternalEntry entry) => entry.ReadOriginalValue(charToStringConverterProperty, 15), + char (IInternalEntry entry) => entry.ReadOriginalValue(charToStringConverterProperty, 14), char (IInternalEntry entry) => entry.GetCurrentValue(charToStringConverterProperty)); charToStringConverterProperty.SetPropertyIndexes( - index: 15, - originalValueIndex: 15, + index: 14, + originalValueIndex: 14, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -697,11 +678,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas dateOnly.SetAccessors( DateOnly (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateOnly(((CompiledModelTestBase.ManyTypes)(entry.Entity))), DateOnly (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateOnly(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - DateOnly (IInternalEntry entry) => entry.ReadOriginalValue(dateOnly, 16), + DateOnly (IInternalEntry entry) => entry.ReadOriginalValue(dateOnly, 15), DateOnly (IInternalEntry entry) => entry.GetCurrentValue(dateOnly)); dateOnly.SetPropertyIndexes( - index: 16, - originalValueIndex: 16, + index: 15, + originalValueIndex: 15, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -732,11 +713,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas dateOnlyToStringConverterProperty.SetAccessors( DateOnly (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateOnlyToStringConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), DateOnly (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateOnlyToStringConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - DateOnly (IInternalEntry entry) => entry.ReadOriginalValue(dateOnlyToStringConverterProperty, 17), + DateOnly (IInternalEntry entry) => entry.ReadOriginalValue(dateOnlyToStringConverterProperty, 16), DateOnly (IInternalEntry entry) => entry.GetCurrentValue(dateOnlyToStringConverterProperty)); dateOnlyToStringConverterProperty.SetPropertyIndexes( - index: 17, - originalValueIndex: 17, + index: 16, + originalValueIndex: 16, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -773,11 +754,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas dateTime.SetAccessors( DateTime (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateTime(((CompiledModelTestBase.ManyTypes)(entry.Entity))), DateTime (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateTime(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - DateTime (IInternalEntry entry) => entry.ReadOriginalValue(dateTime, 18), + DateTime (IInternalEntry entry) => entry.ReadOriginalValue(dateTime, 17), DateTime (IInternalEntry entry) => entry.GetCurrentValue(dateTime)); dateTime.SetPropertyIndexes( - index: 18, - originalValueIndex: 18, + index: 17, + originalValueIndex: 17, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -808,11 +789,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas dateTimeOffsetToBinaryConverterProperty.SetAccessors( DateTimeOffset (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateTimeOffsetToBinaryConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), DateTimeOffset (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateTimeOffsetToBinaryConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - DateTimeOffset (IInternalEntry entry) => entry.ReadOriginalValue(dateTimeOffsetToBinaryConverterProperty, 19), + DateTimeOffset (IInternalEntry entry) => entry.ReadOriginalValue(dateTimeOffsetToBinaryConverterProperty, 18), DateTimeOffset (IInternalEntry entry) => entry.GetCurrentValue(dateTimeOffsetToBinaryConverterProperty)); dateTimeOffsetToBinaryConverterProperty.SetPropertyIndexes( - index: 19, - originalValueIndex: 19, + index: 18, + originalValueIndex: 18, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -849,11 +830,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas dateTimeOffsetToBytesConverterProperty.SetAccessors( DateTimeOffset (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateTimeOffsetToBytesConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), DateTimeOffset (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateTimeOffsetToBytesConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - DateTimeOffset (IInternalEntry entry) => entry.ReadOriginalValue(dateTimeOffsetToBytesConverterProperty, 20), + DateTimeOffset (IInternalEntry entry) => entry.ReadOriginalValue(dateTimeOffsetToBytesConverterProperty, 19), DateTimeOffset (IInternalEntry entry) => entry.GetCurrentValue(dateTimeOffsetToBytesConverterProperty)); dateTimeOffsetToBytesConverterProperty.SetPropertyIndexes( - index: 20, - originalValueIndex: 20, + index: 19, + originalValueIndex: 19, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -890,11 +871,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas dateTimeOffsetToStringConverterProperty.SetAccessors( DateTimeOffset (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateTimeOffsetToStringConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), DateTimeOffset (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateTimeOffsetToStringConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - DateTimeOffset (IInternalEntry entry) => entry.ReadOriginalValue(dateTimeOffsetToStringConverterProperty, 21), + DateTimeOffset (IInternalEntry entry) => entry.ReadOriginalValue(dateTimeOffsetToStringConverterProperty, 20), DateTimeOffset (IInternalEntry entry) => entry.GetCurrentValue(dateTimeOffsetToStringConverterProperty)); dateTimeOffsetToStringConverterProperty.SetPropertyIndexes( - index: 21, - originalValueIndex: 21, + index: 20, + originalValueIndex: 20, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -931,11 +912,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas dateTimeToBinaryConverterProperty.SetAccessors( DateTime (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateTimeToBinaryConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), DateTime (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateTimeToBinaryConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - DateTime (IInternalEntry entry) => entry.ReadOriginalValue(dateTimeToBinaryConverterProperty, 22), + DateTime (IInternalEntry entry) => entry.ReadOriginalValue(dateTimeToBinaryConverterProperty, 21), DateTime (IInternalEntry entry) => entry.GetCurrentValue(dateTimeToBinaryConverterProperty)); dateTimeToBinaryConverterProperty.SetPropertyIndexes( - index: 22, - originalValueIndex: 22, + index: 21, + originalValueIndex: 21, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -972,11 +953,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas dateTimeToStringConverterProperty.SetAccessors( DateTime (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateTimeToStringConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), DateTime (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateTimeToStringConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - DateTime (IInternalEntry entry) => entry.ReadOriginalValue(dateTimeToStringConverterProperty, 23), + DateTime (IInternalEntry entry) => entry.ReadOriginalValue(dateTimeToStringConverterProperty, 22), DateTime (IInternalEntry entry) => entry.GetCurrentValue(dateTimeToStringConverterProperty)); dateTimeToStringConverterProperty.SetPropertyIndexes( - index: 23, - originalValueIndex: 23, + index: 22, + originalValueIndex: 22, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -1013,11 +994,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas dateTimeToTicksConverterProperty.SetAccessors( DateTime (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateTimeToTicksConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), DateTime (IInternalEntry entry) => ManyTypesUnsafeAccessors.DateTimeToTicksConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - DateTime (IInternalEntry entry) => entry.ReadOriginalValue(dateTimeToTicksConverterProperty, 24), + DateTime (IInternalEntry entry) => entry.ReadOriginalValue(dateTimeToTicksConverterProperty, 23), DateTime (IInternalEntry entry) => entry.GetCurrentValue(dateTimeToTicksConverterProperty)); dateTimeToTicksConverterProperty.SetPropertyIndexes( - index: 24, - originalValueIndex: 24, + index: 23, + originalValueIndex: 23, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -1048,11 +1029,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas @decimal.SetAccessors( decimal (IInternalEntry entry) => ManyTypesUnsafeAccessors.Decimal(((CompiledModelTestBase.ManyTypes)(entry.Entity))), decimal (IInternalEntry entry) => ManyTypesUnsafeAccessors.Decimal(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - decimal (IInternalEntry entry) => entry.ReadOriginalValue(@decimal, 25), + decimal (IInternalEntry entry) => entry.ReadOriginalValue(@decimal, 24), decimal (IInternalEntry entry) => entry.GetCurrentValue(@decimal)); @decimal.SetPropertyIndexes( - index: 25, - originalValueIndex: 25, + index: 24, + originalValueIndex: 24, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -1082,11 +1063,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas decimalArray.SetAccessors( decimal[] (IInternalEntry entry) => ManyTypesUnsafeAccessors.DecimalArray(((CompiledModelTestBase.ManyTypes)(entry.Entity))), decimal[] (IInternalEntry entry) => ManyTypesUnsafeAccessors.DecimalArray(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - decimal[] (IInternalEntry entry) => entry.ReadOriginalValue(decimalArray, 26), + decimal[] (IInternalEntry entry) => entry.ReadOriginalValue(decimalArray, 25), decimal[] (IInternalEntry entry) => entry.GetCurrentValue(decimalArray)); decimalArray.SetPropertyIndexes( - index: 26, - originalValueIndex: 26, + index: 25, + originalValueIndex: 25, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -1124,11 +1105,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas decimalNumberToBytesConverterProperty.SetAccessors( decimal (IInternalEntry entry) => ManyTypesUnsafeAccessors.DecimalNumberToBytesConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), decimal (IInternalEntry entry) => ManyTypesUnsafeAccessors.DecimalNumberToBytesConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - decimal (IInternalEntry entry) => entry.ReadOriginalValue(decimalNumberToBytesConverterProperty, 27), + decimal (IInternalEntry entry) => entry.ReadOriginalValue(decimalNumberToBytesConverterProperty, 26), decimal (IInternalEntry entry) => entry.GetCurrentValue(decimalNumberToBytesConverterProperty)); decimalNumberToBytesConverterProperty.SetPropertyIndexes( - index: 27, - originalValueIndex: 27, + index: 26, + originalValueIndex: 26, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -1165,11 +1146,11 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas decimalNumberToStringConverterProperty.SetAccessors( decimal (IInternalEntry entry) => ManyTypesUnsafeAccessors.DecimalNumberToStringConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), decimal (IInternalEntry entry) => ManyTypesUnsafeAccessors.DecimalNumberToStringConverterProperty(((CompiledModelTestBase.ManyTypes)(entry.Entity))), - decimal (IInternalEntry entry) => entry.ReadOriginalValue(decimalNumberToStringConverterProperty, 28), + decimal (IInternalEntry entry) => entry.ReadOriginalValue(decimalNumberToStringConverterProperty, 27), decimal (IInternalEntry entry) => entry.GetCurrentValue(decimalNumberToStringConverterProperty)); decimalNumberToStringConverterProperty.SetPropertyIndexes( - index: 28, - originalValueIndex: 28, + index: 27, + originalValueIndex: 27, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); @@ -1182,6 +1163,26 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas new ValueConverter(string (decimal v) => string.Format(CultureInfo.InvariantCulture, "{0}", ((object)v)), decimal (string v) => decimal.Parse(v, NumberStyles.Any, CultureInfo.InvariantCulture)))); decimalNumberToStringConverterProperty.SetSentinelFromProviderValue("0"); + var discriminator = runtimeEntityType.AddProperty( + "Discriminator", + typeof(string), + afterSaveBehavior: PropertySaveBehavior.Throw, + valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); + discriminator.SetAccessors( + string (IInternalEntry entry) => entry.ReadShadowValue(0), + string (IInternalEntry entry) => entry.ReadShadowValue(0), + string (IInternalEntry entry) => entry.ReadOriginalValue(discriminator, 28), + string (IInternalEntry entry) => entry.GetCurrentValue(discriminator)); + discriminator.SetPropertyIndexes( + index: 28, + originalValueIndex: 28, + shadowIndex: 0, + relationshipIndex: -1, + storeGenerationIndex: -1); + discriminator.TypeMapping = CosmosTypeMapping.Default.Clone( + jsonValueReaderWriter: JsonStringReaderWriter.Instance); + discriminator.AddAnnotation("Cosmos:PropertyName", "$type"); + var @double = runtimeEntityType.AddProperty( "Double", typeof(double), @@ -6802,7 +6803,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) { var id = runtimeEntityType.FindProperty("Id"); - var type = runtimeEntityType.FindProperty("$type"); var @bool = runtimeEntityType.FindProperty("Bool"); var boolArray = runtimeEntityType.FindProperty("BoolArray"); var boolNestedCollection = runtimeEntityType.FindProperty("BoolNestedCollection"); @@ -6830,6 +6830,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) var decimalArray = runtimeEntityType.FindProperty("DecimalArray"); var decimalNumberToBytesConverterProperty = runtimeEntityType.FindProperty("DecimalNumberToBytesConverterProperty"); var decimalNumberToStringConverterProperty = runtimeEntityType.FindProperty("DecimalNumberToStringConverterProperty"); + var discriminator = runtimeEntityType.FindProperty("Discriminator"); var @double = runtimeEntityType.FindProperty("Double"); var doubleArray = runtimeEntityType.FindProperty("DoubleArray"); var doubleNumberToBytesConverterProperty = runtimeEntityType.FindProperty("DoubleNumberToBytesConverterProperty"); @@ -6978,7 +6979,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (IInternalEntry source) => { var structuralType = ((CompiledModelTestBase.ManyTypes)(source.Entity)); - var liftedArg = ((ISnapshot)(new Snapshot, bool, bool, bool, byte[], byte[], int, char, char[], char[][], char, DateOnly, DateOnly, DateTime, DateTimeOffset, DateTimeOffset, DateTimeOffset, DateTime, DateTime, DateTime, decimal, decimal[], decimal, decimal, double>(((ValueComparer)(((IProperty)id).GetValueComparer())).Snapshot(source.GetCurrentValue(id)), (source.GetCurrentValue(type) == null ? null : ((ValueComparer)(((IProperty)type).GetValueComparer())).Snapshot(source.GetCurrentValue(type))), ((ValueComparer)(((IProperty)@bool).GetValueComparer())).Snapshot(source.GetCurrentValue(@bool)), (((IEnumerable)(source.GetCurrentValue(boolArray))) == null ? null : ((bool[])(((ValueComparer>)(((IProperty)boolArray).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(boolArray))))))), (((object)(source.GetCurrentValue(boolNestedCollection))) == null ? null : ((bool[][])(((ValueComparer)(((IProperty)boolNestedCollection).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue(boolNestedCollection))))))), (((IEnumerable)(source.GetCurrentValue>(boolReadOnlyCollection))) == null ? null : ((IReadOnlyCollection)(((ValueComparer>)(((IProperty)boolReadOnlyCollection).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(boolReadOnlyCollection))))))), ((ValueComparer)(((IProperty)boolToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(boolToStringConverterProperty)), ((ValueComparer)(((IProperty)boolToTwoValuesConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(boolToTwoValuesConverterProperty)), ((ValueComparer)(((IProperty)boolToZeroOneConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(boolToZeroOneConverterProperty)), (source.GetCurrentValue(bytes) == null ? null : ((ValueComparer)(((IProperty)bytes).GetValueComparer())).Snapshot(source.GetCurrentValue(bytes))), (source.GetCurrentValue(bytesToStringConverterProperty) == null ? null : ((ValueComparer)(((IProperty)bytesToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(bytesToStringConverterProperty))), ((ValueComparer)(((IProperty)castingConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(castingConverterProperty)), ((ValueComparer)(((IProperty)@char).GetValueComparer())).Snapshot(source.GetCurrentValue(@char)), (((IEnumerable)(source.GetCurrentValue(charArray))) == null ? null : ((char[])(((ValueComparer>)(((IProperty)charArray).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(charArray))))))), (((object)(source.GetCurrentValue(charNestedCollection))) == null ? null : ((char[][])(((ValueComparer)(((IProperty)charNestedCollection).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue(charNestedCollection))))))), ((ValueComparer)(((IProperty)charToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(charToStringConverterProperty)), ((ValueComparer)(((IProperty)dateOnly).GetValueComparer())).Snapshot(source.GetCurrentValue(dateOnly)), ((ValueComparer)(((IProperty)dateOnlyToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(dateOnlyToStringConverterProperty)), ((ValueComparer)(((IProperty)dateTime).GetValueComparer())).Snapshot(source.GetCurrentValue(dateTime)), ((ValueComparer)(((IProperty)dateTimeOffsetToBinaryConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(dateTimeOffsetToBinaryConverterProperty)), ((ValueComparer)(((IProperty)dateTimeOffsetToBytesConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(dateTimeOffsetToBytesConverterProperty)), ((ValueComparer)(((IProperty)dateTimeOffsetToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(dateTimeOffsetToStringConverterProperty)), ((ValueComparer)(((IProperty)dateTimeToBinaryConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(dateTimeToBinaryConverterProperty)), ((ValueComparer)(((IProperty)dateTimeToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(dateTimeToStringConverterProperty)), ((ValueComparer)(((IProperty)dateTimeToTicksConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(dateTimeToTicksConverterProperty)), ((ValueComparer)(((IProperty)@decimal).GetValueComparer())).Snapshot(source.GetCurrentValue(@decimal)), (((IEnumerable)(source.GetCurrentValue(decimalArray))) == null ? null : ((decimal[])(((ValueComparer>)(((IProperty)decimalArray).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(decimalArray))))))), ((ValueComparer)(((IProperty)decimalNumberToBytesConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(decimalNumberToBytesConverterProperty)), ((ValueComparer)(((IProperty)decimalNumberToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(decimalNumberToStringConverterProperty)), ((ValueComparer)(((IProperty)@double).GetValueComparer())).Snapshot(source.GetCurrentValue(@double))))); + var liftedArg = ((ISnapshot)(new Snapshot, bool, bool, bool, byte[], byte[], int, char, char[], char[][], char, DateOnly, DateOnly, DateTime, DateTimeOffset, DateTimeOffset, DateTimeOffset, DateTime, DateTime, DateTime, decimal, decimal[], decimal, decimal, string, double>(((ValueComparer)(((IProperty)id).GetValueComparer())).Snapshot(source.GetCurrentValue(id)), ((ValueComparer)(((IProperty)@bool).GetValueComparer())).Snapshot(source.GetCurrentValue(@bool)), (((IEnumerable)(source.GetCurrentValue(boolArray))) == null ? null : ((bool[])(((ValueComparer>)(((IProperty)boolArray).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(boolArray))))))), (((object)(source.GetCurrentValue(boolNestedCollection))) == null ? null : ((bool[][])(((ValueComparer)(((IProperty)boolNestedCollection).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue(boolNestedCollection))))))), (((IEnumerable)(source.GetCurrentValue>(boolReadOnlyCollection))) == null ? null : ((IReadOnlyCollection)(((ValueComparer>)(((IProperty)boolReadOnlyCollection).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(boolReadOnlyCollection))))))), ((ValueComparer)(((IProperty)boolToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(boolToStringConverterProperty)), ((ValueComparer)(((IProperty)boolToTwoValuesConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(boolToTwoValuesConverterProperty)), ((ValueComparer)(((IProperty)boolToZeroOneConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(boolToZeroOneConverterProperty)), (source.GetCurrentValue(bytes) == null ? null : ((ValueComparer)(((IProperty)bytes).GetValueComparer())).Snapshot(source.GetCurrentValue(bytes))), (source.GetCurrentValue(bytesToStringConverterProperty) == null ? null : ((ValueComparer)(((IProperty)bytesToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(bytesToStringConverterProperty))), ((ValueComparer)(((IProperty)castingConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(castingConverterProperty)), ((ValueComparer)(((IProperty)@char).GetValueComparer())).Snapshot(source.GetCurrentValue(@char)), (((IEnumerable)(source.GetCurrentValue(charArray))) == null ? null : ((char[])(((ValueComparer>)(((IProperty)charArray).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(charArray))))))), (((object)(source.GetCurrentValue(charNestedCollection))) == null ? null : ((char[][])(((ValueComparer)(((IProperty)charNestedCollection).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue(charNestedCollection))))))), ((ValueComparer)(((IProperty)charToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(charToStringConverterProperty)), ((ValueComparer)(((IProperty)dateOnly).GetValueComparer())).Snapshot(source.GetCurrentValue(dateOnly)), ((ValueComparer)(((IProperty)dateOnlyToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(dateOnlyToStringConverterProperty)), ((ValueComparer)(((IProperty)dateTime).GetValueComparer())).Snapshot(source.GetCurrentValue(dateTime)), ((ValueComparer)(((IProperty)dateTimeOffsetToBinaryConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(dateTimeOffsetToBinaryConverterProperty)), ((ValueComparer)(((IProperty)dateTimeOffsetToBytesConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(dateTimeOffsetToBytesConverterProperty)), ((ValueComparer)(((IProperty)dateTimeOffsetToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(dateTimeOffsetToStringConverterProperty)), ((ValueComparer)(((IProperty)dateTimeToBinaryConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(dateTimeToBinaryConverterProperty)), ((ValueComparer)(((IProperty)dateTimeToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(dateTimeToStringConverterProperty)), ((ValueComparer)(((IProperty)dateTimeToTicksConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(dateTimeToTicksConverterProperty)), ((ValueComparer)(((IProperty)@decimal).GetValueComparer())).Snapshot(source.GetCurrentValue(@decimal)), (((IEnumerable)(source.GetCurrentValue(decimalArray))) == null ? null : ((decimal[])(((ValueComparer>)(((IProperty)decimalArray).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(decimalArray))))))), ((ValueComparer)(((IProperty)decimalNumberToBytesConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(decimalNumberToBytesConverterProperty)), ((ValueComparer)(((IProperty)decimalNumberToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(decimalNumberToStringConverterProperty)), (source.GetCurrentValue(discriminator) == null ? null : ((ValueComparer)(((IProperty)discriminator).GetValueComparer())).Snapshot(source.GetCurrentValue(discriminator))), ((ValueComparer)(((IProperty)@double).GetValueComparer())).Snapshot(source.GetCurrentValue(@double))))); var structuralType0 = ((CompiledModelTestBase.ManyTypes)(source.Entity)); var liftedArg0 = ((ISnapshot)(new Snapshot((((IEnumerable)(source.GetCurrentValue(doubleArray))) == null ? null : ((double[])(((ValueComparer>)(((IProperty)doubleArray).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(doubleArray))))))), ((ValueComparer)(((IProperty)doubleNumberToBytesConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(doubleNumberToBytesConverterProperty)), ((ValueComparer)(((IProperty)doubleNumberToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(doubleNumberToStringConverterProperty)), ((ValueComparer)(((IProperty)enum16).GetValueComparer())).Snapshot(source.GetCurrentValue(enum16)), ((ValueComparer)(((IProperty)enum16AsString).GetValueComparer())).Snapshot(source.GetCurrentValue(enum16AsString)), ((ValueComparer)(((IProperty)enum32).GetValueComparer())).Snapshot(source.GetCurrentValue(enum32)), ((ValueComparer)(((IProperty)enum32AsString).GetValueComparer())).Snapshot(source.GetCurrentValue(enum32AsString)), ((ValueComparer)(((IProperty)enum64).GetValueComparer())).Snapshot(source.GetCurrentValue(enum64)), ((ValueComparer)(((IProperty)enum64AsString).GetValueComparer())).Snapshot(source.GetCurrentValue(enum64AsString)), ((ValueComparer)(((IProperty)enum8).GetValueComparer())).Snapshot(source.GetCurrentValue(enum8)), ((ValueComparer)(((IProperty)enum8AsString).GetValueComparer())).Snapshot(source.GetCurrentValue(enum8AsString)), ((ValueComparer)(((IProperty)enumToNumberConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(enumToNumberConverterProperty)), ((ValueComparer)(((IProperty)enumToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(enumToStringConverterProperty)), ((ValueComparer)(((IProperty)enumU16).GetValueComparer())).Snapshot(source.GetCurrentValue(enumU16)), ((ValueComparer)(((IProperty)enumU16AsString).GetValueComparer())).Snapshot(source.GetCurrentValue(enumU16AsString)), ((ValueComparer)(((IProperty)enumU32).GetValueComparer())).Snapshot(source.GetCurrentValue(enumU32)), ((ValueComparer)(((IProperty)enumU32AsString).GetValueComparer())).Snapshot(source.GetCurrentValue(enumU32AsString)), ((ValueComparer)(((IProperty)enumU64).GetValueComparer())).Snapshot(source.GetCurrentValue(enumU64)), ((ValueComparer)(((IProperty)enumU64AsString).GetValueComparer())).Snapshot(source.GetCurrentValue(enumU64AsString)), ((ValueComparer)(((IProperty)enumU8).GetValueComparer())).Snapshot(source.GetCurrentValue(enumU8)), ((ValueComparer)(((IProperty)enumU8AsString).GetValueComparer())).Snapshot(source.GetCurrentValue(enumU8AsString)), ((ValueComparer)(((IProperty)@float).GetValueComparer())).Snapshot(source.GetCurrentValue(@float)), (((IEnumerable)(source.GetCurrentValue(floatArray))) == null ? null : ((float[])(((ValueComparer>)(((IProperty)floatArray).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(floatArray))))))), ((ValueComparer)(((IProperty)guid).GetValueComparer())).Snapshot(source.GetCurrentValue(guid)), ((ValueComparer)(((IProperty)guidToBytesConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(guidToBytesConverterProperty)), ((ValueComparer)(((IProperty)guidToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(guidToStringConverterProperty)), (source.GetCurrentValue(iPAddress) == null ? null : ((ValueComparer)(((IProperty)iPAddress).GetValueComparer())).Snapshot(source.GetCurrentValue(iPAddress))), (source.GetCurrentValue(iPAddressToBytesConverterProperty) == null ? null : ((ValueComparer)(((IProperty)iPAddressToBytesConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(iPAddressToBytesConverterProperty))), (source.GetCurrentValue(iPAddressToStringConverterProperty) == null ? null : ((ValueComparer)(((IProperty)iPAddressToStringConverterProperty).GetValueComparer())).Snapshot(source.GetCurrentValue(iPAddressToStringConverterProperty))), ((ValueComparer)(((IProperty)int16).GetValueComparer())).Snapshot(source.GetCurrentValue(int16))))); var structuralType1 = ((CompiledModelTestBase.ManyTypes)(source.Entity)); @@ -6995,7 +6996,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) runtimeEntityType.SetTemporaryValuesFactory( ISnapshot (IInternalEntry source) => ((ISnapshot)(new Snapshot(default(JObject))))); runtimeEntityType.SetShadowValuesFactory( - ISnapshot (IDictionary source) => ((ISnapshot)(new Snapshot((source.ContainsKey("$type") ? ((string)(source["$type"])) : null), (source.ContainsKey("__id") ? ((string)(source["__id"])) : null), (source.ContainsKey("__jObject") ? ((JObject)(source["__jObject"])) : null))))); + ISnapshot (IDictionary source) => ((ISnapshot)(new Snapshot((source.ContainsKey("Discriminator") ? ((string)(source["Discriminator"])) : null), (source.ContainsKey("__id") ? ((string)(source["__id"])) : null), (source.ContainsKey("__jObject") ? ((JObject)(source["__jObject"])) : null))))); runtimeEntityType.SetEmptyShadowValuesFactory( ISnapshot () => ((ISnapshot)(new Snapshot(default(string), default(string), default(JObject))))); runtimeEntityType.SetRelationshipSnapshotFactory( diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBaseEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBaseEntityType.cs index 857ba54fc9f..d6d5f20a4d8 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBaseEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBaseEntityType.cs @@ -116,24 +116,25 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas alternateId.SetCurrentValueComparer(new EntryCurrentValueComparer(alternateId)); alternateId.SetSentinelFromProviderValue("00000000-0000-0000-0000-000000000000"); - var type = runtimeEntityType.AddProperty( - "$type", + var discriminator = runtimeEntityType.AddProperty( + "Discriminator", typeof(string), afterSaveBehavior: PropertySaveBehavior.Throw, valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); - type.SetAccessors( + discriminator.SetAccessors( string (IInternalEntry entry) => entry.ReadShadowValue(0), string (IInternalEntry entry) => entry.ReadShadowValue(0), - string (IInternalEntry entry) => entry.ReadOriginalValue(type, 2), - string (IInternalEntry entry) => entry.GetCurrentValue(type)); - type.SetPropertyIndexes( + string (IInternalEntry entry) => entry.ReadOriginalValue(discriminator, 2), + string (IInternalEntry entry) => entry.GetCurrentValue(discriminator)); + discriminator.SetPropertyIndexes( index: 2, originalValueIndex: 2, shadowIndex: 0, relationshipIndex: -1, storeGenerationIndex: -1); - type.TypeMapping = CosmosTypeMapping.Default.Clone( + discriminator.TypeMapping = CosmosTypeMapping.Default.Clone( jsonValueReaderWriter: JsonStringReaderWriter.Instance); + discriminator.AddAnnotation("Cosmos:PropertyName", "$type"); var enum1 = runtimeEntityType.AddProperty( "Enum1", @@ -661,7 +662,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) { var id = runtimeEntityType.FindProperty("Id"); var alternateId = runtimeEntityType.FindProperty("AlternateId"); - var type = runtimeEntityType.FindProperty("$type"); + var discriminator = runtimeEntityType.FindProperty("Discriminator"); var enum1 = runtimeEntityType.FindProperty("Enum1"); var enum2 = runtimeEntityType.FindProperty("Enum2"); var flagsEnum1 = runtimeEntityType.FindProperty("FlagsEnum1"); @@ -686,14 +687,14 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (IInternalEntry source) => { var structuralType5 = ((CompiledModelTestBase.PrincipalBase)(source.Entity)); - return ((ISnapshot)(new Snapshot, IList, DateTime[], IEnumerable, IList, List, string, JObject>((source.GetCurrentValue(id) == null ? null : ((ValueComparer)(((IProperty)id).GetValueComparer())).Snapshot(source.GetCurrentValue(id))), ((ValueComparer)(((IProperty)alternateId).GetValueComparer())).Snapshot(source.GetCurrentValue(alternateId)), (source.GetCurrentValue(type) == null ? null : ((ValueComparer)(((IProperty)type).GetValueComparer())).Snapshot(source.GetCurrentValue(type))), ((ValueComparer)(((IProperty)enum1).GetValueComparer())).Snapshot(source.GetCurrentValue(enum1)), (source.GetCurrentValue(enum2) == null ? null : ((ValueComparer)(((IProperty)enum2).GetValueComparer())).Snapshot(source.GetCurrentValue(enum2))), ((ValueComparer)(((IProperty)flagsEnum1).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum1)), ((ValueComparer)(((IProperty)flagsEnum2).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum2)), (((object)(source.GetCurrentValue>(refTypeEnumerable))) == null ? null : ((IEnumerable)(((ValueComparer)(((IProperty)refTypeEnumerable).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeEnumerable))))))), (((object)(source.GetCurrentValue>(refTypeIList))) == null ? null : ((IList)(((ValueComparer)(((IProperty)refTypeIList).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeIList))))))), (((IEnumerable)(source.GetCurrentValue(valueTypeArray))) == null ? null : ((DateTime[])(((ValueComparer>)(((IProperty)valueTypeArray).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(valueTypeArray))))))), (source.GetCurrentValue>(valueTypeEnumerable) == null ? null : ((ValueComparer>)(((IProperty)valueTypeEnumerable).GetValueComparer())).Snapshot(source.GetCurrentValue>(valueTypeEnumerable))), (((IEnumerable)(source.GetCurrentValue>(valueTypeIList))) == null ? null : ((IList)(((ValueComparer>)(((IProperty)valueTypeIList).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeIList))))))), (((IEnumerable)(source.GetCurrentValue>(valueTypeList))) == null ? null : ((List)(((ValueComparer>)(((IProperty)valueTypeList).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeList))))))), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetValueComparer())).Snapshot(source.GetCurrentValue(__id))), (source.GetCurrentValue(__jObject) == null ? null : ((ValueComparer)(((IProperty)__jObject).GetValueComparer())).Snapshot(source.GetCurrentValue(__jObject)))))); + return ((ISnapshot)(new Snapshot, IList, DateTime[], IEnumerable, IList, List, string, JObject>((source.GetCurrentValue(id) == null ? null : ((ValueComparer)(((IProperty)id).GetValueComparer())).Snapshot(source.GetCurrentValue(id))), ((ValueComparer)(((IProperty)alternateId).GetValueComparer())).Snapshot(source.GetCurrentValue(alternateId)), (source.GetCurrentValue(discriminator) == null ? null : ((ValueComparer)(((IProperty)discriminator).GetValueComparer())).Snapshot(source.GetCurrentValue(discriminator))), ((ValueComparer)(((IProperty)enum1).GetValueComparer())).Snapshot(source.GetCurrentValue(enum1)), (source.GetCurrentValue(enum2) == null ? null : ((ValueComparer)(((IProperty)enum2).GetValueComparer())).Snapshot(source.GetCurrentValue(enum2))), ((ValueComparer)(((IProperty)flagsEnum1).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum1)), ((ValueComparer)(((IProperty)flagsEnum2).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum2)), (((object)(source.GetCurrentValue>(refTypeEnumerable))) == null ? null : ((IEnumerable)(((ValueComparer)(((IProperty)refTypeEnumerable).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeEnumerable))))))), (((object)(source.GetCurrentValue>(refTypeIList))) == null ? null : ((IList)(((ValueComparer)(((IProperty)refTypeIList).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeIList))))))), (((IEnumerable)(source.GetCurrentValue(valueTypeArray))) == null ? null : ((DateTime[])(((ValueComparer>)(((IProperty)valueTypeArray).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(valueTypeArray))))))), (source.GetCurrentValue>(valueTypeEnumerable) == null ? null : ((ValueComparer>)(((IProperty)valueTypeEnumerable).GetValueComparer())).Snapshot(source.GetCurrentValue>(valueTypeEnumerable))), (((IEnumerable)(source.GetCurrentValue>(valueTypeIList))) == null ? null : ((IList)(((ValueComparer>)(((IProperty)valueTypeIList).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeIList))))))), (((IEnumerable)(source.GetCurrentValue>(valueTypeList))) == null ? null : ((List)(((ValueComparer>)(((IProperty)valueTypeList).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeList))))))), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetValueComparer())).Snapshot(source.GetCurrentValue(__id))), (source.GetCurrentValue(__jObject) == null ? null : ((ValueComparer)(((IProperty)__jObject).GetValueComparer())).Snapshot(source.GetCurrentValue(__jObject)))))); }); runtimeEntityType.SetStoreGeneratedValuesFactory( ISnapshot () => Snapshot.Empty); runtimeEntityType.SetTemporaryValuesFactory( ISnapshot (IInternalEntry source) => Snapshot.Empty); runtimeEntityType.SetShadowValuesFactory( - ISnapshot (IDictionary source) => ((ISnapshot)(new Snapshot((source.ContainsKey("$type") ? ((string)(source["$type"])) : null), (source.ContainsKey("__id") ? ((string)(source["__id"])) : null), (source.ContainsKey("__jObject") ? ((JObject)(source["__jObject"])) : null))))); + ISnapshot (IDictionary source) => ((ISnapshot)(new Snapshot((source.ContainsKey("Discriminator") ? ((string)(source["Discriminator"])) : null), (source.ContainsKey("__id") ? ((string)(source["__id"])) : null), (source.ContainsKey("__jObject") ? ((JObject)(source["__jObject"])) : null))))); runtimeEntityType.SetEmptyShadowValuesFactory( ISnapshot () => ((ISnapshot)(new Snapshot(default(string), default(string), default(JObject))))); runtimeEntityType.SetRelationshipSnapshotFactory( diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs index e083e6ced92..7840d4fa03f 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs @@ -284,40 +284,41 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas GuidToStringConverter.Instance)); principalsAlternateId.SetCurrentValueComparer(new EntryCurrentValueComparer(principalsAlternateId)); - var type = runtimeEntityType.AddProperty( - "$type", + var discriminator = runtimeEntityType.AddProperty( + "Discriminator", typeof(string), propertyInfo: runtimeEntityType.FindIndexerPropertyInfo(), afterSaveBehavior: PropertySaveBehavior.Throw, valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); - type.SetGetter( - string (Dictionary instance) => ((((IDictionary)instance).ContainsKey("$type") ? instance["$type"] : null) == null ? null : ((string)((((IDictionary)instance).ContainsKey("$type") ? instance["$type"] : null)))), - bool (Dictionary instance) => (((IDictionary)instance).ContainsKey("$type") ? instance["$type"] : null) == null); - type.SetSetter( + discriminator.SetGetter( + string (Dictionary instance) => ((((IDictionary)instance).ContainsKey("Discriminator") ? instance["Discriminator"] : null) == null ? null : ((string)((((IDictionary)instance).ContainsKey("Discriminator") ? instance["Discriminator"] : null)))), + bool (Dictionary instance) => (((IDictionary)instance).ContainsKey("Discriminator") ? instance["Discriminator"] : null) == null); + discriminator.SetSetter( Dictionary (Dictionary instance, string value) => { - instance["$type"] = ((object)value); + instance["Discriminator"] = ((object)value); return instance; }); - type.SetMaterializationSetter( + discriminator.SetMaterializationSetter( Dictionary (Dictionary instance, string value) => { - instance["$type"] = ((object)value); + instance["Discriminator"] = ((object)value); return instance; }); - type.SetAccessors( - string (IInternalEntry entry) => ((string)((((IDictionary)((Dictionary)(entry.Entity))).ContainsKey("$type") ? ((Dictionary)(entry.Entity))["$type"] : null))), - string (IInternalEntry entry) => ((string)((((IDictionary)((Dictionary)(entry.Entity))).ContainsKey("$type") ? ((Dictionary)(entry.Entity))["$type"] : null))), - string (IInternalEntry entry) => entry.ReadOriginalValue(type, 4), - string (IInternalEntry entry) => entry.GetCurrentValue(type)); - type.SetPropertyIndexes( + discriminator.SetAccessors( + string (IInternalEntry entry) => ((string)((((IDictionary)((Dictionary)(entry.Entity))).ContainsKey("Discriminator") ? ((Dictionary)(entry.Entity))["Discriminator"] : null))), + string (IInternalEntry entry) => ((string)((((IDictionary)((Dictionary)(entry.Entity))).ContainsKey("Discriminator") ? ((Dictionary)(entry.Entity))["Discriminator"] : null))), + string (IInternalEntry entry) => entry.ReadOriginalValue(discriminator, 4), + string (IInternalEntry entry) => entry.GetCurrentValue(discriminator)); + discriminator.SetPropertyIndexes( index: 4, originalValueIndex: 4, shadowIndex: -1, relationshipIndex: -1, storeGenerationIndex: -1); - type.TypeMapping = CosmosTypeMapping.Default.Clone( + discriminator.TypeMapping = CosmosTypeMapping.Default.Clone( jsonValueReaderWriter: JsonStringReaderWriter.Instance); + discriminator.AddAnnotation("Cosmos:PropertyName", "$type"); var __id = runtimeEntityType.AddProperty( "__id", @@ -469,7 +470,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) var derivedsAlternateId = runtimeEntityType.FindProperty("DerivedsAlternateId"); var principalsId = runtimeEntityType.FindProperty("PrincipalsId"); var principalsAlternateId = runtimeEntityType.FindProperty("PrincipalsAlternateId"); - var type = runtimeEntityType.FindProperty("$type"); + var discriminator = runtimeEntityType.FindProperty("Discriminator"); var __id = runtimeEntityType.FindProperty("__id"); var __jObject = runtimeEntityType.FindProperty("__jObject"); var rowid = runtimeEntityType.FindProperty("rowid"); @@ -480,7 +481,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (IInternalEntry source) => { var structuralType5 = ((Dictionary)(source.Entity)); - return ((ISnapshot)(new Snapshot(((ValueComparer)(((IProperty)derivedsId).GetValueComparer())).Snapshot(source.GetCurrentValue(derivedsId)), ((ValueComparer)(((IProperty)derivedsAlternateId).GetValueComparer())).Snapshot(source.GetCurrentValue(derivedsAlternateId)), ((ValueComparer)(((IProperty)principalsId).GetValueComparer())).Snapshot(source.GetCurrentValue(principalsId)), ((ValueComparer)(((IProperty)principalsAlternateId).GetValueComparer())).Snapshot(source.GetCurrentValue(principalsAlternateId)), (source.GetCurrentValue(type) == null ? null : ((ValueComparer)(((IProperty)type).GetValueComparer())).Snapshot(source.GetCurrentValue(type))), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetValueComparer())).Snapshot(source.GetCurrentValue(__id))), (source.GetCurrentValue(__jObject) == null ? null : ((ValueComparer)(((IProperty)__jObject).GetValueComparer())).Snapshot(source.GetCurrentValue(__jObject))), (source.GetCurrentValue(rowid) == null ? null : ((ValueComparer)(((IProperty)rowid).GetValueComparer())).Snapshot(source.GetCurrentValue(rowid)))))); + return ((ISnapshot)(new Snapshot(((ValueComparer)(((IProperty)derivedsId).GetValueComparer())).Snapshot(source.GetCurrentValue(derivedsId)), ((ValueComparer)(((IProperty)derivedsAlternateId).GetValueComparer())).Snapshot(source.GetCurrentValue(derivedsAlternateId)), ((ValueComparer)(((IProperty)principalsId).GetValueComparer())).Snapshot(source.GetCurrentValue(principalsId)), ((ValueComparer)(((IProperty)principalsAlternateId).GetValueComparer())).Snapshot(source.GetCurrentValue(principalsAlternateId)), (source.GetCurrentValue(discriminator) == null ? null : ((ValueComparer)(((IProperty)discriminator).GetValueComparer())).Snapshot(source.GetCurrentValue(discriminator))), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetValueComparer())).Snapshot(source.GetCurrentValue(__id))), (source.GetCurrentValue(__jObject) == null ? null : ((ValueComparer)(((IProperty)__jObject).GetValueComparer())).Snapshot(source.GetCurrentValue(__jObject))), (source.GetCurrentValue(rowid) == null ? null : ((ValueComparer)(((IProperty)rowid).GetValueComparer())).Snapshot(source.GetCurrentValue(rowid)))))); }); runtimeEntityType.SetStoreGeneratedValuesFactory( ISnapshot () => ((ISnapshot)(new Snapshot(((ValueComparer)(((IProperty)derivedsId).GetValueComparer())).Snapshot(default(long)), ((ValueComparer)(((IProperty)derivedsAlternateId).GetValueComparer())).Snapshot(default(Guid)), ((ValueComparer)(((IProperty)principalsId).GetValueComparer())).Snapshot(default(long)), ((ValueComparer)(((IProperty)principalsAlternateId).GetValueComparer())).Snapshot(default(Guid)), (default(JObject) == null ? null : ((ValueComparer)(((IProperty)__jObject).GetValueComparer())).Snapshot(default(JObject))))))); diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalDerivedEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalDerivedEntityType.cs index 5712ed3bf4a..38376c62829 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalDerivedEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalDerivedEntityType.cs @@ -97,7 +97,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) { var id = runtimeEntityType.FindProperty("Id"); var alternateId = runtimeEntityType.FindProperty("AlternateId"); - var type = runtimeEntityType.FindProperty("$type"); + var discriminator = runtimeEntityType.FindProperty("Discriminator"); var enum1 = runtimeEntityType.FindProperty("Enum1"); var enum2 = runtimeEntityType.FindProperty("Enum2"); var flagsEnum1 = runtimeEntityType.FindProperty("FlagsEnum1"); @@ -119,14 +119,14 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (IInternalEntry source) => { var structuralType5 = ((CompiledModelTestBase.PrincipalDerived>)(source.Entity)); - return ((ISnapshot)(new Snapshot, IList, DateTime[], IEnumerable, IList, List, string, JObject>((source.GetCurrentValue(id) == null ? null : ((ValueComparer)(((IProperty)id).GetValueComparer())).Snapshot(source.GetCurrentValue(id))), ((ValueComparer)(((IProperty)alternateId).GetValueComparer())).Snapshot(source.GetCurrentValue(alternateId)), (source.GetCurrentValue(type) == null ? null : ((ValueComparer)(((IProperty)type).GetValueComparer())).Snapshot(source.GetCurrentValue(type))), ((ValueComparer)(((IProperty)enum1).GetValueComparer())).Snapshot(source.GetCurrentValue(enum1)), (source.GetCurrentValue(enum2) == null ? null : ((ValueComparer)(((IProperty)enum2).GetValueComparer())).Snapshot(source.GetCurrentValue(enum2))), ((ValueComparer)(((IProperty)flagsEnum1).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum1)), ((ValueComparer)(((IProperty)flagsEnum2).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum2)), (((object)(source.GetCurrentValue>(refTypeEnumerable))) == null ? null : ((IEnumerable)(((ValueComparer)(((IProperty)refTypeEnumerable).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeEnumerable))))))), (((object)(source.GetCurrentValue>(refTypeIList))) == null ? null : ((IList)(((ValueComparer)(((IProperty)refTypeIList).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeIList))))))), (((IEnumerable)(source.GetCurrentValue(valueTypeArray))) == null ? null : ((DateTime[])(((ValueComparer>)(((IProperty)valueTypeArray).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(valueTypeArray))))))), (source.GetCurrentValue>(valueTypeEnumerable) == null ? null : ((ValueComparer>)(((IProperty)valueTypeEnumerable).GetValueComparer())).Snapshot(source.GetCurrentValue>(valueTypeEnumerable))), (((IEnumerable)(source.GetCurrentValue>(valueTypeIList))) == null ? null : ((IList)(((ValueComparer>)(((IProperty)valueTypeIList).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeIList))))))), (((IEnumerable)(source.GetCurrentValue>(valueTypeList))) == null ? null : ((List)(((ValueComparer>)(((IProperty)valueTypeList).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeList))))))), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetValueComparer())).Snapshot(source.GetCurrentValue(__id))), (source.GetCurrentValue(__jObject) == null ? null : ((ValueComparer)(((IProperty)__jObject).GetValueComparer())).Snapshot(source.GetCurrentValue(__jObject)))))); + return ((ISnapshot)(new Snapshot, IList, DateTime[], IEnumerable, IList, List, string, JObject>((source.GetCurrentValue(id) == null ? null : ((ValueComparer)(((IProperty)id).GetValueComparer())).Snapshot(source.GetCurrentValue(id))), ((ValueComparer)(((IProperty)alternateId).GetValueComparer())).Snapshot(source.GetCurrentValue(alternateId)), (source.GetCurrentValue(discriminator) == null ? null : ((ValueComparer)(((IProperty)discriminator).GetValueComparer())).Snapshot(source.GetCurrentValue(discriminator))), ((ValueComparer)(((IProperty)enum1).GetValueComparer())).Snapshot(source.GetCurrentValue(enum1)), (source.GetCurrentValue(enum2) == null ? null : ((ValueComparer)(((IProperty)enum2).GetValueComparer())).Snapshot(source.GetCurrentValue(enum2))), ((ValueComparer)(((IProperty)flagsEnum1).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum1)), ((ValueComparer)(((IProperty)flagsEnum2).GetValueComparer())).Snapshot(source.GetCurrentValue(flagsEnum2)), (((object)(source.GetCurrentValue>(refTypeEnumerable))) == null ? null : ((IEnumerable)(((ValueComparer)(((IProperty)refTypeEnumerable).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeEnumerable))))))), (((object)(source.GetCurrentValue>(refTypeIList))) == null ? null : ((IList)(((ValueComparer)(((IProperty)refTypeIList).GetValueComparer())).Snapshot(((object)(source.GetCurrentValue>(refTypeIList))))))), (((IEnumerable)(source.GetCurrentValue(valueTypeArray))) == null ? null : ((DateTime[])(((ValueComparer>)(((IProperty)valueTypeArray).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue(valueTypeArray))))))), (source.GetCurrentValue>(valueTypeEnumerable) == null ? null : ((ValueComparer>)(((IProperty)valueTypeEnumerable).GetValueComparer())).Snapshot(source.GetCurrentValue>(valueTypeEnumerable))), (((IEnumerable)(source.GetCurrentValue>(valueTypeIList))) == null ? null : ((IList)(((ValueComparer>)(((IProperty)valueTypeIList).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeIList))))))), (((IEnumerable)(source.GetCurrentValue>(valueTypeList))) == null ? null : ((List)(((ValueComparer>)(((IProperty)valueTypeList).GetValueComparer())).Snapshot(((IEnumerable)(source.GetCurrentValue>(valueTypeList))))))), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetValueComparer())).Snapshot(source.GetCurrentValue(__id))), (source.GetCurrentValue(__jObject) == null ? null : ((ValueComparer)(((IProperty)__jObject).GetValueComparer())).Snapshot(source.GetCurrentValue(__jObject)))))); }); runtimeEntityType.SetStoreGeneratedValuesFactory( ISnapshot () => Snapshot.Empty); runtimeEntityType.SetTemporaryValuesFactory( ISnapshot (IInternalEntry source) => Snapshot.Empty); runtimeEntityType.SetShadowValuesFactory( - ISnapshot (IDictionary source) => ((ISnapshot)(new Snapshot((source.ContainsKey("$type") ? ((string)(source["$type"])) : null), (source.ContainsKey("__id") ? ((string)(source["__id"])) : null), (source.ContainsKey("__jObject") ? ((JObject)(source["__jObject"])) : null))))); + ISnapshot (IDictionary source) => ((ISnapshot)(new Snapshot((source.ContainsKey("Discriminator") ? ((string)(source["Discriminator"])) : null), (source.ContainsKey("__id") ? ((string)(source["__id"])) : null), (source.ContainsKey("__jObject") ? ((JObject)(source["__jObject"])) : null))))); runtimeEntityType.SetEmptyShadowValuesFactory( ISnapshot () => ((ISnapshot)(new Snapshot(default(string), default(string), default(JObject))))); runtimeEntityType.SetRelationshipSnapshotFactory( diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs index 34fda62314f..0b529910ef3 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs @@ -92,8 +92,9 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas shadowIndex: 0, relationshipIndex: -1, storeGenerationIndex: -1); - type.TypeMapping = CosmosTypeMapping.Default.Clone( + discriminator.TypeMapping = CosmosTypeMapping.Default.Clone( jsonValueReaderWriter: JsonStringReaderWriter.Instance); + discriminator.AddAnnotation("Cosmos:PropertyName", "$type"); var enum1 = runtimeEntityType.AddProperty( "Enum1", diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/Cosmos_model_with_index_types/IndexedDataEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/Cosmos_model_with_index_types/IndexedDataEntityType.cs index 4985ea100ea..fc8ebc72298 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/Cosmos_model_with_index_types/IndexedDataEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/Cosmos_model_with_index_types/IndexedDataEntityType.cs @@ -109,25 +109,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas jsonValueReaderWriter: JsonStringReaderWriter.Instance); partitionId.SetCurrentValueComparer(new EntryCurrentValueComparer(partitionId)); - var type = runtimeEntityType.AddProperty( - "$type", - typeof(string), - afterSaveBehavior: PropertySaveBehavior.Throw, - valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); - type.SetAccessors( - string (IInternalEntry entry) => entry.ReadShadowValue(0), - string (IInternalEntry entry) => entry.ReadShadowValue(0), - string (IInternalEntry entry) => entry.ReadOriginalValue(type, 2), - string (IInternalEntry entry) => entry.GetCurrentValue(type)); - type.SetPropertyIndexes( - index: 2, - originalValueIndex: 2, - shadowIndex: 0, - relationshipIndex: -1, - storeGenerationIndex: -1); - type.TypeMapping = CosmosTypeMapping.Default.Clone( - jsonValueReaderWriter: JsonStringReaderWriter.Instance); - var category = runtimeEntityType.AddProperty( "Category", typeof(string), @@ -214,21 +195,9 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas shadowIndex: 0, relationshipIndex: -1, storeGenerationIndex: -1); - discriminator.TypeMapping = CosmosTypeMapping.Default.Clone( - comparer: new ValueComparer( - bool (string v1, string v2) => v1 == v2, - int (string v) => ((object)v).GetHashCode(), - string (string v) => v), - keyComparer: new ValueComparer( - bool (string v1, string v2) => v1 == v2, - int (string v) => ((object)v).GetHashCode(), - string (string v) => v), - providerValueComparer: new ValueComparer( - bool (string v1, string v2) => v1 == v2, - int (string v) => ((object)v).GetHashCode(), - string (string v) => v), - clrType: typeof(string), + discriminator.TypeMapping = CosmosTypeMapping.Default.Clone( jsonValueReaderWriter: JsonStringReaderWriter.Instance); + discriminator.AddAnnotation("Cosmos:PropertyName", "$type"); var embedding = runtimeEntityType.AddProperty( "Embedding", diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/ManyTypesEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/ManyTypesEntityType.cs index b09de98dc06..555e1d9d4b4 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/ManyTypesEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/ManyTypesEntityType.cs @@ -258,6 +258,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas typeof(string), afterSaveBehavior: PropertySaveBehavior.Throw, valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); + discriminator.AddAnnotation("Cosmos:PropertyName", "$type"); var @double = runtimeEntityType.AddProperty( "Double", diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBaseEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBaseEntityType.cs index 885d049f5ff..868e5fe5b73 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBaseEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBaseEntityType.cs @@ -54,6 +54,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas typeof(string), afterSaveBehavior: PropertySaveBehavior.Throw, valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); + discriminator.AddAnnotation("Cosmos:PropertyName", "$type"); var enum1 = runtimeEntityType.AddProperty( "Enum1", diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs index 9dec95ad330..0867bfbfd07 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/No_NativeAOT/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs @@ -62,6 +62,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas propertyInfo: runtimeEntityType.FindIndexerPropertyInfo(), afterSaveBehavior: PropertySaveBehavior.Throw, valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); + discriminator.AddAnnotation("Cosmos:PropertyName", "$type"); var __id = runtimeEntityType.AddProperty( "__id", diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs index ad75d16a230..25daec8a4a9 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs @@ -70,25 +70,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas jsonValueReaderWriter: JsonInt32ReaderWriter.Instance); id.SetCurrentValueComparer(new EntryCurrentValueComparer(id)); - var type = runtimeEntityType.AddProperty( - "$type", - typeof(string), - afterSaveBehavior: PropertySaveBehavior.Throw, - valueGeneratorFactory: new DiscriminatorValueGeneratorFactory().Create); - type.SetAccessors( - string (IInternalEntry entry) => entry.ReadShadowValue(0), - string (IInternalEntry entry) => entry.ReadShadowValue(0), - string (IInternalEntry entry) => entry.ReadOriginalValue(type, 1), - string (IInternalEntry entry) => entry.GetCurrentValue(type)); - type.SetPropertyIndexes( - index: 1, - originalValueIndex: 1, - shadowIndex: 0, - relationshipIndex: -1, - storeGenerationIndex: -1); - type.TypeMapping = CosmosTypeMapping.Default.Clone( - jsonValueReaderWriter: JsonStringReaderWriter.Instance); - var data = runtimeEntityType.AddProperty( "Data", typeof(string), @@ -140,21 +121,9 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas shadowIndex: 0, relationshipIndex: -1, storeGenerationIndex: -1); - discriminator.TypeMapping = CosmosTypeMapping.Default.Clone( - comparer: new ValueComparer( - bool (string v1, string v2) => v1 == v2, - int (string v) => ((object)v).GetHashCode(), - string (string v) => v), - keyComparer: new ValueComparer( - bool (string v1, string v2) => v1 == v2, - int (string v) => ((object)v).GetHashCode(), - string (string v) => v), - providerValueComparer: new ValueComparer( - bool (string v1, string v2) => v1 == v2, - int (string v) => ((object)v).GetHashCode(), - string (string v) => v), - clrType: typeof(string), + discriminator.TypeMapping = CosmosTypeMapping.Default.Clone( jsonValueReaderWriter: JsonStringReaderWriter.Instance); + discriminator.AddAnnotation("Cosmos:PropertyName", "$type"); var __id = runtimeEntityType.AddProperty( "__id", diff --git a/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosModelAsserter.cs b/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosModelAsserter.cs index 6624496d805..8a907e8ab06 100644 --- a/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosModelAsserter.cs +++ b/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosModelAsserter.cs @@ -19,8 +19,8 @@ public override void AssertEqual( bool assertOrder = false, bool compareAnnotations = false) { - expectedProperties = expectedProperties.Where(p => p.Name != "__jObject" && p.Name != "__id" && p.Name != "$type"); - actualProperties = actualProperties.Where(p => p.Name != "__jObject" && p.Name != "__id" && p.Name != "$type"); + expectedProperties = expectedProperties.Where(p => p.Name != "__jObject" && p.Name != "__id" && p.Name != "Discriminator"); + actualProperties = actualProperties.Where(p => p.Name != "__jObject" && p.Name != "__id" && p.Name != "Discriminator"); base.AssertEqual(expectedProperties, actualProperties, assertOrder, compareAnnotations); } diff --git a/test/EFCore.Cosmos.Tests/Extensions/CosmosBuilderExtensionsTest.cs b/test/EFCore.Cosmos.Tests/Extensions/CosmosBuilderExtensionsTest.cs index 0a7b249397b..91a680b2538 100644 --- a/test/EFCore.Cosmos.Tests/Extensions/CosmosBuilderExtensionsTest.cs +++ b/test/EFCore.Cosmos.Tests/Extensions/CosmosBuilderExtensionsTest.cs @@ -136,7 +136,7 @@ public void Default_discriminator_can_be_removed() var entityType = modelBuilder.Model.FindEntityType(typeof(Customer))!; Assert.Equal("Discriminator", entityType.FindDiscriminatorProperty()!.Name); - Assert.Equal("Discriminator", entityType.FindDiscriminatorProperty()!.GetJsonPropertyName()); + Assert.Equal("$type", entityType.FindDiscriminatorProperty()!.GetJsonPropertyName()); Assert.Equal(nameof(Customer), entityType.GetDiscriminatorValue()); modelBuilder.Entity().HasNoDiscriminator(); @@ -147,7 +147,7 @@ public void Default_discriminator_can_be_removed() modelBuilder.Entity().HasBaseType(); Assert.Equal("Discriminator", entityType.FindDiscriminatorProperty()!.Name); - Assert.Equal("Discriminator", entityType.FindDiscriminatorProperty()!.GetJsonPropertyName()); + Assert.Equal("$type", entityType.FindDiscriminatorProperty()!.GetJsonPropertyName()); Assert.Equal(nameof(Customer), entityType.GetDiscriminatorValue()); modelBuilder.Entity().HasBaseType((string)null); From c226a4bf894f8a1999f457f5a460dc8ea216c558 Mon Sep 17 00:00:00 2001 From: Andriy Svyryd Date: Tue, 23 Jun 2026 16:38:24 -0700 Subject: [PATCH 23/23] Remove IsIdentifierStartCharacter method --- src/EFCore.Design/Design/Internal/CSharpHelper.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/EFCore.Design/Design/Internal/CSharpHelper.cs b/src/EFCore.Design/Design/Internal/CSharpHelper.cs index 11fabbefa39..ff217f57fd3 100644 --- a/src/EFCore.Design/Design/Internal/CSharpHelper.cs +++ b/src/EFCore.Design/Design/Internal/CSharpHelper.cs @@ -1629,9 +1629,6 @@ public virtual string Expression( return code; } - private static bool IsIdentifierStartCharacter(char ch) - => char.IsLetter(ch) || ch == '_'; - private static bool IsIdentifierPartCharacter(char ch) => char.IsLetter(ch) || char.IsAsciiDigit(ch) || ch == '_'; }