From fff81d7c98e13445ff74edb026656b6f003b8062 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Wed, 10 Jul 2024 09:45:04 +0100 Subject: [PATCH] Stop including the discriminator in the JSON id by default Fixes #34179 There are also new APIs on the entity type and model builders to facilitate optional behaviors, including reverting to the pre-9 behavior: - Entity().IncludeDiscriminatorInJsonId(); - Entity().IncludeRootDiscriminatorInJsonId(); - Entity().AlwaysCreateShadowIdProperty(); Note that this change requires regeneration of the Northwind database. --- .../CosmosEntityTypeBuilderExtensions.cs | 319 +++++ .../Extensions/CosmosEntityTypeExtensions.cs | 91 ++ .../CosmosModelBuilderExtensions.cs | 76 ++ .../Extensions/CosmosModelExtensions.cs | 86 ++ .../Internal/CosmosModelValidator.cs | 14 +- .../Conventions/CosmosJsonIdConvention.cs | 270 ++++ ...ion.cs => CosmosKeyAugmenterConvention.cs} | 122 +- .../Internal/CosmosConventionSetBuilder.cs | 21 +- .../Metadata/DiscriminatorInKeyBehavior.cs | 26 + .../Internal/CosmosAnnotationNames.cs | 16 + .../Metadata/Internal/IJsonIdDefinition.cs | 12 + .../Metadata/Internal/JsonIdDefinition.cs | 35 +- .../Internal/JsonIdDefinitionFactory.cs | 42 +- .../Properties/CosmosStrings.Designer.cs | 16 - .../Properties/CosmosStrings.resx | 6 - ...yableMethodTranslatingExpressionVisitor.cs | 5 +- ...CosmosReadItemAndPartitionKeysExtractor.cs | 60 +- ...ionBindingRemovingExpressionVisitorBase.cs | 2 +- .../Expressions/EntityProjectionExpression.cs | 2 +- .../Storage/Internal/CosmosClientWrapper.cs | 6 +- .../Update/Internal/DocumentSource.cs | 4 +- .../BuiltInDataTypesCosmosTest.cs | 2 + .../CustomConvertersCosmosTest.cs | 2 + .../EmbeddedDocumentsTest.cs | 2 + .../EndToEndCosmosTest.cs | 83 +- .../F1CosmosFixture.cs | 2 + .../FindCosmosTest.cs | 52 +- .../KeysWithConvertersCosmosTest.cs | 2 + .../CosmosModelBuilderGenericTest.cs | 131 +- .../Northwind.json | 1118 +---------------- .../Query/FromSqlQueryCosmosTest.cs | 34 +- .../Query/InheritanceQueryCosmosFixture.cs | 16 + .../Query/InheritanceQueryCosmosTest.cs | 2 +- ...thwindAggregateOperatorsQueryCosmosTest.cs | 418 +++--- .../NorthwindFunctionsQueryCosmosTest.cs | 128 +- ...NorthwindKeylessEntitiesQueryCosmosTest.cs | 24 +- .../NorthwindMiscellaneousQueryCosmosTest.cs | 678 ++++------ .../Query/NorthwindQueryCosmosFixture.cs | 37 +- .../Query/NorthwindSelectQueryCosmosTest.cs | 182 +-- .../Query/NorthwindWhereQueryCosmosTest.cs | 320 +++-- .../Query/OwnedQueryCosmosTest.cs | 58 +- .../PrimitiveCollectionsQueryCosmosTest.cs | 2 +- .../Query/QueryLoggingCosmosTestBase.cs | 14 +- .../Query/ReadItemPartitionKeyQueryTest.cs | 32 +- ...onInterceptionWithDiagnosticsCosmosTest.cs | 7 + .../ReadItemTest.cs | 1 + .../Basic_cosmos_model/DataEntityType.cs | 17 +- .../BigModel/DependentBaseEntityType.cs | 29 +- .../BigModel/DependentDerivedEntityType.cs | 4 +- .../Baselines/BigModel/ManyTypesEntityType.cs | 17 +- .../BigModel/OwnedType0EntityType.cs | 2 +- .../Baselines/BigModel/OwnedTypeEntityType.cs | 2 +- .../BigModel/PrincipalBaseEntityType.cs | 27 +- ...cipalDerivedDependentBasebyteEntityType.cs | 25 +- .../BigModel/PrincipalDerivedEntityType.cs | 6 +- .../ComplexTypes/PrincipalBaseEntityType.cs | 19 +- .../PrincipalDerivedEntityType.cs | 4 +- .../SimpleModel/DependentDerivedEntityType.cs | 17 +- .../Scaffolding/CompiledModelCosmosTest.cs | 2 +- .../TestUtilities/CosmosTestStore.cs | 18 +- ...efinition.cs => CustomJsonIdDefinition.cs} | 4 +- ...ry.cs => CustomJsonIdDefinitionFactory.cs} | 7 +- .../CustomPartitionKeyIdGenerator.cs | 2 +- .../CosmosModelValidatorTest.cs | 52 +- .../ValueGeneration/IdValueGeneratorTest.cs | 4 +- .../NorthwindMiscellaneousQueryTestBase.cs | 2 +- 66 files changed, 2173 insertions(+), 2665 deletions(-) create mode 100644 src/EFCore.Cosmos/Metadata/Conventions/CosmosJsonIdConvention.cs rename src/EFCore.Cosmos/Metadata/Conventions/{StoreKeyConvention.cs => CosmosKeyAugmenterConvention.cs} (63%) create mode 100644 src/EFCore.Cosmos/Metadata/DiscriminatorInKeyBehavior.cs create mode 100644 test/EFCore.Cosmos.FunctionalTests/ReadItemTest.cs rename test/EFCore.Cosmos.FunctionalTests/TestUtilities/{CustomRuntimeJsonIdDefinition.cs => CustomJsonIdDefinition.cs} (82%) rename test/EFCore.Cosmos.FunctionalTests/TestUtilities/{CustomRuntimeJsonIdDefinitionFactory.cs => CustomJsonIdDefinitionFactory.cs} (59%) diff --git a/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs index 3292e43101a..f5e7c6e30e0 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeBuilderExtensions.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.EntityFrameworkCore.Cosmos.Metadata; using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; // ReSharper disable once CheckNamespace @@ -391,6 +392,324 @@ public static EntityTypeBuilder UseETagConcurrency(this Entity where TEntity : class => (EntityTypeBuilder)UseETagConcurrency((EntityTypeBuilder)entityTypeBuilder); + /// + /// Forces model building to always create a "__id" shadow property mapped to the JSON "id". This was the default + /// behavior before EF Core 9.0. + /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information and examples. + /// + /// The builder for the entity type being configured. + /// + /// to force __id creation, to not force __id creation, + /// to revert to the default setting. + /// + /// The same builder instance so that multiple calls can be chained. + public static EntityTypeBuilder AlwaysCreateShadowIdProperty( + this EntityTypeBuilder entityTypeBuilder, + bool? alwaysCreate = true) + { + entityTypeBuilder.Metadata.SetAlwaysCreateShadowIdProperty(alwaysCreate); + + return entityTypeBuilder; + } + + /// + /// Forces model building to always create a "__id" shadow property mapped to the JSON "id". This was the default + /// behavior before EF Core 9.0. + /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information and examples. + /// + /// The builder for the entity type being configured. + /// + /// to force __id creation, to not force __id creation, + /// to revert to the default setting. + /// + /// The same builder instance so that multiple calls can be chained. + public static EntityTypeBuilder AlwaysCreateShadowIdProperty( + this EntityTypeBuilder entityTypeBuilder, + bool? alwaysCreate = true) + where TEntity : class + => (EntityTypeBuilder)AlwaysCreateShadowIdProperty((EntityTypeBuilder)entityTypeBuilder, alwaysCreate); + + /// + /// Forces model building to always create a "__id" shadow property mapped to the JSON "id". This was the default + /// behavior before EF Core 9.0. + /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information and examples. + /// + /// The builder for the entity type being configured. + /// + /// to force __id creation, to not force __id creation, + /// to revert to the default setting. + /// + /// Indicates whether the configuration was specified using a data annotation. + /// The same builder instance if the configuration was applied, otherwise. + public static IConventionEntityTypeBuilder? AlwaysCreateShadowIdProperty( + this IConventionEntityTypeBuilder entityTypeBuilder, + bool? alwaysCreate, + bool fromDataAnnotation = false) + { + if (!entityTypeBuilder.CanSetAlwaysCreateShadowIdProperty(alwaysCreate, fromDataAnnotation)) + { + return null; + } + + entityTypeBuilder.Metadata.SetAlwaysCreateShadowIdProperty(alwaysCreate, fromDataAnnotation); + + return entityTypeBuilder; + } + + /// + /// Returns a value indicating whether the setting for always creating the "__id" property can be set + /// from the current configuration source + /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information and examples. + /// + /// The builder for the entity type being configured. + /// + /// to force __id creation, to not force __id creation, + /// to revert to the default setting. + /// + /// Indicates whether the configuration was specified using a data annotation. + /// if the configuration can be applied. + public static bool CanSetAlwaysCreateShadowIdProperty( + this IConventionEntityTypeBuilder entityTypeBuilder, + bool? alwaysCreate, + bool fromDataAnnotation = false) + { + Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder)); + + return entityTypeBuilder.CanSetAnnotation(CosmosAnnotationNames.AlwaysCreateShadowIdProperty, alwaysCreate, fromDataAnnotation); + } + + /// + /// Includes the discriminator value of the entity type in the JSON "id" value. This was the default behavior before EF Core 9. + /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information and examples. + /// + /// The builder for the entity type being configured. + /// + /// to include the discriminator, to not include the discriminator, + /// to revert to the default setting. + /// + /// The same builder instance so that multiple calls can be chained. + public static EntityTypeBuilder IncludeDiscriminatorInJsonId( + this EntityTypeBuilder entityTypeBuilder, + bool? includeDiscriminator = true) + { + entityTypeBuilder.Metadata.SetDiscriminatorInKey( + includeDiscriminator == null + ? null + : includeDiscriminator.Value + ? DiscriminatorInKeyBehavior.EntityTypeName + : DiscriminatorInKeyBehavior.None); + + return entityTypeBuilder; + } + + /// + /// Includes the discriminator value of the root entity type in the JSON "id" value. This allows types with the same + /// primary key to be saved in the same container, while still allowing "ReadItem" to be used for lookups of an unknown type. + /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information and examples. + /// + /// The builder for the entity type being configured. + /// + /// to include the discriminator, to not include the discriminator, + /// to revert to the default setting. + /// + /// The same builder instance so that multiple calls can be chained. + public static EntityTypeBuilder IncludeRootDiscriminatorInJsonId( + this EntityTypeBuilder entityTypeBuilder, + bool? includeDiscriminator = true) + { + entityTypeBuilder.Metadata.SetDiscriminatorInKey( + includeDiscriminator == null + ? null + : includeDiscriminator.Value + ? DiscriminatorInKeyBehavior.RootEntityTypeName + : DiscriminatorInKeyBehavior.None); + + return entityTypeBuilder; + } + + /// + /// Includes the discriminator value of the entity type in the JSON "id" value. This was the default behavior before EF Core 9. + /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information and examples. + /// + /// The builder for the entity type being configured. + /// + /// to include the discriminator, to not include the discriminator, + /// to revert to the default setting. + /// + /// The same builder instance so that multiple calls can be chained. + public static EntityTypeBuilder IncludeDiscriminatorInJsonId( + this EntityTypeBuilder entityTypeBuilder, bool? includeDiscriminator = true) + where TEntity : class + => (EntityTypeBuilder)IncludeDiscriminatorInJsonId((EntityTypeBuilder)entityTypeBuilder, includeDiscriminator); + + /// + /// Includes the discriminator value of the root entity type in the JSON "id" value. This allows types with the same + /// primary key to be saved in the same container, while still allowing "ReadItem" to be used for lookups of an unknown type. + /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information and examples. + /// + /// The builder for the entity type being configured. + /// + /// to include the discriminator, to not include the discriminator, + /// to revert to the default setting. + /// + /// The same builder instance so that multiple calls can be chained. + public static EntityTypeBuilder IncludeRootDiscriminatorInJsonId( + this EntityTypeBuilder entityTypeBuilder, bool? includeDiscriminator = true) + where TEntity : class + => (EntityTypeBuilder)IncludeRootDiscriminatorInJsonId((EntityTypeBuilder)entityTypeBuilder, includeDiscriminator); + + /// + /// Includes the discriminator value of the entity type in the JSON "id" value. This was the default behavior before EF Core 9. + /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information and examples. + /// + /// The builder for the entity type being configured. + /// + /// to force __id creation, to not force __id creation, + /// to revert to the default setting. + /// + /// Indicates whether the configuration was specified using a data annotation. + /// The same builder instance if the configuration was applied, otherwise. + public static IConventionEntityTypeBuilder? IncludeDiscriminatorInJsonId( + this IConventionEntityTypeBuilder entityTypeBuilder, bool? includeDiscriminator, bool fromDataAnnotation = false) + { + if (!entityTypeBuilder.CanSetIncludeDiscriminatorInJsonId(includeDiscriminator, fromDataAnnotation)) + { + return null; + } + + entityTypeBuilder.Metadata.SetDiscriminatorInKey( + includeDiscriminator == null + ? null + : includeDiscriminator.Value + ? DiscriminatorInKeyBehavior.EntityTypeName + : DiscriminatorInKeyBehavior.None, fromDataAnnotation); + + return entityTypeBuilder; + } + + /// + /// Includes the discriminator value of the root entity type in the JSON "id" value. This allows types with the same + /// primary key to be saved in the same container, while still allowing "ReadItem" to be used for lookups of an unknown type. + /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information and examples. + /// + /// The builder for the entity type being configured. + /// + /// to force __id creation, to not force __id creation, + /// to revert to the default setting. + /// + /// Indicates whether the configuration was specified using a data annotation. + /// The same builder instance if the configuration was applied, otherwise. + public static IConventionEntityTypeBuilder? IncludeRootDiscriminatorInJsonId( + this IConventionEntityTypeBuilder entityTypeBuilder, bool? includeDiscriminator, bool fromDataAnnotation = false) + { + if (!entityTypeBuilder.CanSetIncludeRootDiscriminatorInJsonId(includeDiscriminator, fromDataAnnotation)) + { + return null; + } + + entityTypeBuilder.Metadata.SetDiscriminatorInKey( + includeDiscriminator == null + ? null + : includeDiscriminator.Value + ? DiscriminatorInKeyBehavior.EntityTypeName + : DiscriminatorInKeyBehavior.None, fromDataAnnotation); + + return entityTypeBuilder; + } + + /// + /// Returns a value indicating whether the setting for including the discriminator can be set + /// from the current configuration source + /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information and examples. + /// + /// The builder for the entity type being configured. + /// + /// to force __id creation, to not force __id creation, + /// to revert to the default setting. + /// + /// Indicates whether the configuration was specified using a data annotation. + /// if the configuration can be applied. + public static bool CanSetIncludeDiscriminatorInJsonId( + this IConventionEntityTypeBuilder entityTypeBuilder, + bool? includeDiscriminator, + bool fromDataAnnotation = false) + { + Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder)); + + return entityTypeBuilder.CanSetAnnotation( + CosmosAnnotationNames.DiscriminatorInKey, + includeDiscriminator == null + ? null + : includeDiscriminator.Value + ? DiscriminatorInKeyBehavior.EntityTypeName + : DiscriminatorInKeyBehavior.None, fromDataAnnotation); + } + + + /// + /// Returns a value indicating whether the setting for including the discriminator can be set + /// from the current configuration source + /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information and examples. + /// + /// The builder for the entity type being configured. + /// + /// to force __id creation, to not force __id creation, + /// to revert to the default setting. + /// + /// Indicates whether the configuration was specified using a data annotation. + /// if the configuration can be applied. + public static bool CanSetIncludeRootDiscriminatorInJsonId( + this IConventionEntityTypeBuilder entityTypeBuilder, + bool? includeDiscriminator, + bool fromDataAnnotation = false) + { + Check.NotNull(entityTypeBuilder, nameof(entityTypeBuilder)); + + return entityTypeBuilder.CanSetAnnotation( + CosmosAnnotationNames.DiscriminatorInKey, + includeDiscriminator == null + ? null + : includeDiscriminator.Value + ? DiscriminatorInKeyBehavior.RootEntityTypeName + : DiscriminatorInKeyBehavior.None, fromDataAnnotation); + } + /// /// Configures the time to live for analytical store in seconds at container scope. /// diff --git a/src/EFCore.Cosmos/Extensions/CosmosEntityTypeExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeExtensions.cs index be6ad2a2bc1..6d77f1c8c63 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosEntityTypeExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosEntityTypeExtensions.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.EntityFrameworkCore.Cosmos.Metadata; using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; // ReSharper disable once CheckNamespace @@ -342,6 +343,96 @@ public static void SetETagPropertyName(this IMutableEntityType entityType, strin public static IProperty? GetETagProperty(this IEntityType entityType) => (IProperty?)((IReadOnlyEntityType)entityType).GetETagProperty(); + /// + /// Returns a value indicating whether model building will always create a "__id" shadow property mapped to the JSON "id". + /// This was the default behavior before EF Core 9.0. + /// + /// The entity type. + /// + /// to force __id creation, to not force __id creation, + /// to revert to the default setting. + /// . + public static bool? GetAlwaysCreateShadowIdProperty(this IReadOnlyEntityType entityType) + => entityType.BaseType != null + ? entityType.GetRootType().GetAlwaysCreateShadowIdProperty() + : (bool?)entityType[CosmosAnnotationNames.AlwaysCreateShadowIdProperty]; + + /// + /// Forces model building to always create a "__id" shadow property mapped to the JSON "id". This was the default + /// behavior before EF Core 9.0. + /// + /// The entity type. + /// + /// to force __id creation, to not force __id creation, + /// to revert to the default setting. + /// + public static void SetAlwaysCreateShadowIdProperty(this IMutableEntityType entityType, bool? alwaysCreate) + => entityType.SetOrRemoveAnnotation(CosmosAnnotationNames.AlwaysCreateShadowIdProperty, alwaysCreate); + + /// + /// Forces model building to always create a "__id" shadow property mapped to the JSON "id". This was the default + /// behavior before EF Core 9.0. + /// + /// The entity type. + /// + /// to force __id creation, to not force __id creation, + /// to revert to the default setting. + /// + /// Indicates whether the configuration was specified using a data annotation. + public static bool? SetAlwaysCreateShadowIdProperty( + this IConventionEntityType entityType, + bool? alwaysCreate, + bool fromDataAnnotation = false) + => (bool?)entityType.SetOrRemoveAnnotation( + CosmosAnnotationNames.AlwaysCreateShadowIdProperty, alwaysCreate, fromDataAnnotation)?.Value; + + /// + /// Gets the for . + /// + /// The entity typer. + /// The . + public static ConfigurationSource? GetAlwaysCreateShadowIdPropertyConfigurationSource(this IConventionEntityType entityType) + => entityType.FindAnnotation(CosmosAnnotationNames.AlwaysCreateShadowIdProperty)?.GetConfigurationSource(); + + /// + /// Returns a value indicating whether the entity type discriminator should be included in the JSON "id" value. + /// Prior to EF Core 9, it was always included. Starting with EF Core 9, it is not included by default. + /// + /// The entity type. + /// The or if not set. + public static DiscriminatorInKeyBehavior? GetDiscriminatorInKey(this IReadOnlyEntityType entityType) + => entityType.BaseType != null + ? entityType.GetRootType().GetDiscriminatorInKey() + : (DiscriminatorInKeyBehavior?)entityType[CosmosAnnotationNames.DiscriminatorInKey]; + + /// + /// Includes the entity type discriminator in the JSON "id". + /// + /// The entity type. + /// The behavior to use, or to reset the behavior to the default. + public static void SetDiscriminatorInKey(this IMutableEntityType entityType, DiscriminatorInKeyBehavior? behavior) + => entityType.SetOrRemoveAnnotation(CosmosAnnotationNames.DiscriminatorInKey, behavior); + + /// + /// Includes the entity type discriminator in the JSON "id". + /// + /// The entity type. + /// The behavior to use, or to reset the behavior to the default. + /// Indicates whether the configuration was specified using a data annotation. + public static DiscriminatorInKeyBehavior? SetDiscriminatorInKey( + this IConventionEntityType entityType, DiscriminatorInKeyBehavior? behavior, bool fromDataAnnotation = false) + => (DiscriminatorInKeyBehavior?)entityType.SetOrRemoveAnnotation( + CosmosAnnotationNames.DiscriminatorInKey, behavior, fromDataAnnotation)?.Value; + + /// + /// Gets the for . + /// + /// The entity typer. + /// The . + public static ConfigurationSource? GetDiscriminatorInKeyConfigurationSource(this IConventionEntityType entityType) + => entityType.FindAnnotation(CosmosAnnotationNames.DiscriminatorInKey) + ?.GetConfigurationSource(); + /// /// Returns the time to live for analytical store in seconds at container scope. /// diff --git a/src/EFCore.Cosmos/Extensions/CosmosModelBuilderExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosModelBuilderExtensions.cs index 06b41d8ce38..2becf26bb17 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosModelBuilderExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosModelBuilderExtensions.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.EntityFrameworkCore.Cosmos.Metadata; using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; // ReSharper disable once CheckNamespace @@ -104,6 +105,81 @@ public static ModelBuilder HasManualThroughput(this ModelBuilder modelBuilder, i return modelBuilder; } + /// + /// Forces model building to always create a "__id" shadow property mapped to the JSON "id". This was the default + /// behavior before EF Core 9.0. + /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information and examples. + /// + /// The model builder. + /// + /// to force __id creation, to not force __id creation, + /// to revert to the default setting. + /// + public static ModelBuilder AlwaysCreateShadowIdProperties(this ModelBuilder modelBuilder, bool? alwaysCreate = true) + { + modelBuilder.Model.SetAlwaysCreateShadowIdProperty(alwaysCreate); + + return modelBuilder; + } + + /// + /// Includes the discriminator value of the entity type in the JSON "id" value. This was the default behavior before EF Core 9. + /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information and examples. + /// + /// The model builder. + /// + /// to include the discriminator, to not include the discriminator, + /// to revert to the default setting. + /// + /// The same builder instance so that multiple calls can be chained. + public static ModelBuilder IncludeDiscriminatorInJsonId( + this ModelBuilder modelBuilder, + bool? includeDiscriminator = true) + { + modelBuilder.Model.SetDiscriminatorInKey( + includeDiscriminator == null + ? null + : includeDiscriminator.Value + ? DiscriminatorInKeyBehavior.EntityTypeName + : DiscriminatorInKeyBehavior.None); + + return modelBuilder; + } + + /// + /// Includes the discriminator value of the root entity type in the JSON "id" value. This allows types with the same + /// primary key to be saved in the same container, while still allowing "ReadItem" to be used for lookups of an unknown type. + /// + /// + /// See Modeling entity types and relationships, and + /// Accessing Azure Cosmos DB with EF Core for more information and examples. + /// + /// The model builder. + /// + /// to include the discriminator, to not include the discriminator, + /// to revert to the default setting. + /// + /// The same builder instance so that multiple calls can be chained. + public static ModelBuilder IncludeRootDiscriminatorInJsonId( + this ModelBuilder modelBuilder, + bool? includeDiscriminator = true) + { + modelBuilder.Model.SetDiscriminatorInKey( + includeDiscriminator == null + ? null + : includeDiscriminator.Value + ? DiscriminatorInKeyBehavior.RootEntityTypeName + : DiscriminatorInKeyBehavior.None); + + return modelBuilder; + } + /// /// Configures the autoscale provisioned throughput offering. /// diff --git a/src/EFCore.Cosmos/Extensions/CosmosModelExtensions.cs b/src/EFCore.Cosmos/Extensions/CosmosModelExtensions.cs index ad47182bbab..e569c83615d 100644 --- a/src/EFCore.Cosmos/Extensions/CosmosModelExtensions.cs +++ b/src/EFCore.Cosmos/Extensions/CosmosModelExtensions.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.EntityFrameworkCore.Cosmos.Metadata; using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; // ReSharper disable once CheckNamespace @@ -57,6 +58,91 @@ public static void SetDefaultContainer(this IMutableModel model, string? name) public static ConfigurationSource? GetDefaultContainerConfigurationSource(this IConventionModel model) => model.FindAnnotation(CosmosAnnotationNames.ContainerName)?.GetConfigurationSource(); + /// + /// Returns a value indicating whether the setting for always creating the "__id" property can be set + /// from the current configuration source + /// + /// The model. + /// The configured value. + public static bool? GetAlwaysCreateShadowIdProperty(this IReadOnlyModel model) + => (bool?)model[CosmosAnnotationNames.AlwaysCreateShadowIdProperty]; + + /// + /// Forces model building to always create a "__id" shadow property mapped to the JSON "id". This was the default + /// behavior before EF Core 9.0. + /// + /// The model. + /// + /// to force __id creation, to not force __id creation, + /// to revert to the default setting. + /// + public static void SetAlwaysCreateShadowIdProperty(this IMutableModel model, bool? alwaysCreate) + => model.SetOrRemoveAnnotation(CosmosAnnotationNames.AlwaysCreateShadowIdProperty, alwaysCreate); + + /// + /// Forces model building to always create a "__id" shadow property mapped to the JSON "id". This was the default + /// behavior before EF Core 9.0. + /// + /// The model. + /// + /// to force __id creation, to not force __id creation, + /// to revert to the default setting. + /// + /// Indicates whether the configuration was specified using a data annotation. + public static bool? SetAlwaysCreateShadowIdProperty( + this IConventionModel model, + bool? alwaysCreate, + bool fromDataAnnotation = false) + => (bool?)model.SetOrRemoveAnnotation(CosmosAnnotationNames.AlwaysCreateShadowIdProperty, alwaysCreate, fromDataAnnotation)?.Value; + + /// + /// Gets the + /// for . + /// + /// The model. + /// The . + public static ConfigurationSource? GetAlwaysCreateShadowIdPropertyConfigurationSource(this IConventionModel model) + => model.FindAnnotation(CosmosAnnotationNames.AlwaysCreateShadowIdProperty)?.GetConfigurationSource(); + + /// + /// Returns a value indicating whether the entity type discriminator should be included in the JSON "id" value. + /// Prior to EF Core 9, it was always included. Starting with EF Core 9, it is not included by default. + /// + /// The model. + /// The or if not set. + public static DiscriminatorInKeyBehavior? GetDiscriminatorInKey(this IReadOnlyModel model) + => (DiscriminatorInKeyBehavior?)model[CosmosAnnotationNames.DiscriminatorInKey]; + + /// + /// Includes the entity type discriminator in the JSON "id". + /// + /// The model. + /// The behavior to use, or to reset the behavior to the default. + public static void SetDiscriminatorInKey(this IMutableModel model, DiscriminatorInKeyBehavior? behavior) + => model.SetOrRemoveAnnotation(CosmosAnnotationNames.DiscriminatorInKey, behavior); + + /// + /// Includes the entity type discriminator in the JSON "id". + /// + /// The model. + /// The behavior to use, or to reset the behavior to the default. + /// Indicates whether the configuration was specified using a data annotation. + public static DiscriminatorInKeyBehavior? SetDiscriminatorInKey( + this IConventionModel model, + DiscriminatorInKeyBehavior? behavior, + bool fromDataAnnotation = false) + => (DiscriminatorInKeyBehavior?)model.SetOrRemoveAnnotation( + CosmosAnnotationNames.DiscriminatorInKey, behavior, fromDataAnnotation)?.Value; + + /// + /// Gets the + /// for . + /// + /// The model. + /// The . + public static ConfigurationSource? GetDiscriminatorInKeyConfigurationSource(this IConventionModel model) + => model.FindAnnotation(CosmosAnnotationNames.DiscriminatorInKey)?.GetConfigurationSource(); + /// /// Returns the provisioned throughput at database scope. /// diff --git a/src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs b/src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs index 62fd37c9950..ef0b3671a35 100644 --- a/src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs +++ b/src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs @@ -318,7 +318,7 @@ protected virtual void ValidateKeys( } var idProperty = entityType.GetProperties() - .FirstOrDefault(p => p.GetJsonPropertyName() == StoreKeyConvention.IdPropertyJsonName); + .FirstOrDefault(p => p.GetJsonPropertyName() == CosmosJsonIdConvention.IdPropertyJsonName); if (idProperty == null) { throw new InvalidOperationException(CosmosStrings.NoIdProperty(entityType.DisplayName())); @@ -333,11 +333,6 @@ protected virtual void ValidateKeys( idProperty.Name, entityType.DisplayName(), idType.ShortDisplayName())); } - if (!idProperty.IsKey()) - { - throw new InvalidOperationException(CosmosStrings.NoIdKey(entityType.DisplayName(), idProperty.Name)); - } - var partitionKeyPropertyNames = entityType.GetPartitionKeyPropertyNames(); if (partitionKeyPropertyNames.Count == 0) { @@ -364,13 +359,6 @@ protected virtual void ValidateKeys( CosmosStrings.PartitionKeyBadStoreType( partitionKeyPropertyName, entityType.DisplayName(), partitionKeyType.ShortDisplayName())); } - - if (!partitionKey.GetContainingKeys().Any(k => k.Properties.Contains(idProperty))) - { - throw new InvalidOperationException( - CosmosStrings.NoPartitionKeyKey( - entityType.DisplayName(), partitionKeyPropertyName, idProperty.Name)); - } } } } diff --git a/src/EFCore.Cosmos/Metadata/Conventions/CosmosJsonIdConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosJsonIdConvention.cs new file mode 100644 index 00000000000..d753f455d1c --- /dev/null +++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosJsonIdConvention.cs @@ -0,0 +1,270 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; +using Microsoft.EntityFrameworkCore.Cosmos.ValueGeneration.Internal; + +namespace Microsoft.EntityFrameworkCore.Metadata.Conventions; + +/// +/// A convention that configures mapping the PK and/or discriminator properties to the JSON 'id' property. +/// +/// +/// +/// See Model building conventions, and +/// Accessing Azure Cosmos DB with EF Core for more information and examples. +/// +/// +public class CosmosJsonIdConvention + : IEntityTypeAddedConvention, + IEntityTypeBaseTypeChangedConvention, + IEntityTypeAnnotationChangedConvention, + IForeignKeyOwnershipChangedConvention, + IKeyAddedConvention, + IKeyRemovedConvention, + IPropertyAddedConvention, + IPropertyRemovedConvention, + IPropertyAnnotationChangedConvention, + IModelAnnotationChangedConvention, + IDiscriminatorPropertySetConvention, + IModelFinalizingConvention +{ + /// + /// 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 static readonly string IdPropertyJsonName = "id"; + + /// + /// 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 static readonly string DefaultIdPropertyName = "__id"; + + /// + /// Creates a new instance of . + /// + /// Parameter object containing dependencies for this convention. + /// The factory to create a for each entity type. + public CosmosJsonIdConvention( + ProviderConventionSetBuilderDependencies dependencies, + IJsonIdDefinitionFactory definitionFactory) + { + Dependencies = dependencies; + DefinitionFactory = definitionFactory; + } + + /// + /// Dependencies for this service. + /// + protected virtual ProviderConventionSetBuilderDependencies Dependencies { get; } + + /// + /// The factory to create a for each entity type. + /// + protected virtual IJsonIdDefinitionFactory DefinitionFactory { get; } + + private void ProcessEntityType(IConventionEntityType entityType, IConventionContext context) + { + var primaryKey = entityType.FindPrimaryKey(); + if (entityType.BaseType == null // Reactions required for: IEntityTypeBaseTypeChangedConvention + && entityType.IsDocumentRoot() // Reactions required for: IEntityTypeAnnotationChangedConvention (ContainerName), + && !entityType.IsOwned() // Reactions required for: IForeignKeyOwnershipChangedConvention + && primaryKey != null) // Reactions required for: IKeyAddedConvention, IKeyRemovedConvention + { + var entityTypeBuilder = entityType.Builder; + + // Reactions required for: + // IPropertyAddedConvention, IPropertyRemovedConvention + // IPropertyAddedConvention, IPropertyRemovedConvention, IPropertyAnnotationChangedConvention (PropertyName) + + // Explicit configuration: + // - If the __id shadow property is already mapped, then do nothing by convention here. + // - If a property is already mapped to the JSON id field, then do nothing by convention. + var computedIdProperty = entityType.FindDeclaredProperty(DefaultIdPropertyName); + var jsonIdProperty = entityType.GetDeclaredProperties().FirstOrDefault(p => p.GetJsonPropertyName() == IdPropertyJsonName); + if ((jsonIdProperty != null + && jsonIdProperty.GetConfigurationSource().OverridesStrictly(ConfigurationSource.Convention)) + || (computedIdProperty != null + && computedIdProperty.GetConfigurationSource().OverridesStrictly(ConfigurationSource.Convention))) + { + if (jsonIdProperty != null + && !jsonIdProperty.GetConfigurationSource().OverridesStrictly(ConfigurationSource.Convention)) + { + jsonIdProperty.Builder.ToJsonProperty(null); + } + + if (computedIdProperty != null + && !computedIdProperty.GetConfigurationSource().OverridesStrictly(ConfigurationSource.Convention)) + { + entityTypeBuilder.Metadata.RemoveProperty(computedIdProperty); + } + + return; + } + + // Reactions required for: + // IEntityTypeAnnotationChangedConvention (AlwaysCreateShadowIdProperty) + // IModelAnnotationChangedConvention (AlwaysCreateShadowIdProperty) + var alwaysCreateId = entityType.GetAlwaysCreateShadowIdProperty() ?? entityType.Model.GetAlwaysCreateShadowIdProperty(); + if (alwaysCreateId != true) + { + // If there is one string primary key property after removing partition keys, then map it to the JSON id field directly, + // unless it is explicitly mapped to some other property, in which case we compute the field value as below. + + // IKeyAddedConvention, IKeyRemovedConvention, IPropertyAddedConvention, IPropertyRemovedConvention, + // IEntityTypeAnnotationChangedConvention (PartitionKeyNames) (DiscriminatorInKey) + // IDiscriminatorPropertySetConvention + var idDefinition = DefinitionFactory.Create((IEntityType)entityType)!; + var keyProperty = (IConventionProperty?)idDefinition.Properties.FirstOrDefault(); + if (idDefinition.DiscriminatorEntityType == null + && idDefinition.Properties.Count == 1) + { + var clrType = keyProperty!.GetValueConverter()?.ProviderClrType ?? keyProperty.ClrType; + if (clrType == typeof(string)) + { + if (computedIdProperty != null) + { + entityTypeBuilder.Metadata.RemoveProperty(computedIdProperty); + } + keyProperty.SetJsonPropertyName(IdPropertyJsonName); + return; + } + } + } + + if (jsonIdProperty != null + && jsonIdProperty != computedIdProperty) + { + jsonIdProperty.Builder.ToJsonProperty(null); + } + + computedIdProperty = entityTypeBuilder + .Property(typeof(string), DefaultIdPropertyName, setTypeConfigurationSource: false)! + .ToJsonProperty(IdPropertyJsonName)! + .IsRequired(true)! + .HasValueGeneratorFactory(typeof(IdValueGeneratorFactory))! + .Metadata; + + computedIdProperty.SetAfterSaveBehavior(PropertySaveBehavior.Throw); + } + } + + /// + public virtual void ProcessEntityTypeAdded( + IConventionEntityTypeBuilder entityTypeBuilder, + IConventionContext context) + => ProcessEntityType(entityTypeBuilder.Metadata, context); + + /// + public void ProcessEntityTypeBaseTypeChanged( + IConventionEntityTypeBuilder entityTypeBuilder, + IConventionEntityType? newBaseType, + IConventionEntityType? oldBaseType, + IConventionContext context) + => ProcessEntityType(entityTypeBuilder.Metadata, context); + + /// + public void ProcessEntityTypeAnnotationChanged( + IConventionEntityTypeBuilder entityTypeBuilder, + string name, + IConventionAnnotation? annotation, + IConventionAnnotation? oldAnnotation, + IConventionContext context) + { + switch (name) + { + case CosmosAnnotationNames.ContainerName: + case CosmosAnnotationNames.AlwaysCreateShadowIdProperty: + case CosmosAnnotationNames.PartitionKeyNames: + case CosmosAnnotationNames.DiscriminatorInKey: + ProcessEntityType(entityTypeBuilder.Metadata, context); + break; + } + } + + /// + public void ProcessForeignKeyOwnershipChanged(IConventionForeignKeyBuilder relationshipBuilder, IConventionContext context) + => ProcessEntityType(relationshipBuilder.Metadata.DeclaringEntityType, context); + + /// + public void ProcessKeyAdded(IConventionKeyBuilder keyBuilder, IConventionContext context) + => ProcessEntityType(keyBuilder.Metadata.DeclaringEntityType, context); + + /// + public void ProcessKeyRemoved( + IConventionEntityTypeBuilder entityTypeBuilder, + IConventionKey key, + IConventionContext context) + => ProcessEntityType(entityTypeBuilder.Metadata, context); + + /// + public void ProcessPropertyAdded(IConventionPropertyBuilder propertyBuilder, IConventionContext context) + => ProcessEntityType(propertyBuilder.Metadata.DeclaringType.ContainingEntityType, context); + + /// + public void ProcessPropertyRemoved( + IConventionTypeBaseBuilder typeBaseBuilder, + IConventionProperty property, + IConventionContext context) + => ProcessEntityType(typeBaseBuilder.Metadata.ContainingEntityType, context); + + /// + public void ProcessPropertyAnnotationChanged( + IConventionPropertyBuilder propertyBuilder, + string name, + IConventionAnnotation? annotation, + IConventionAnnotation? oldAnnotation, + IConventionContext context) + { + switch (name) + { + case CosmosAnnotationNames.PropertyName: + ProcessEntityType(propertyBuilder.Metadata.DeclaringType.ContainingEntityType, context); + break; + } + } + + /// + public void ProcessModelAnnotationChanged( + IConventionModelBuilder modelBuilder, + string name, + IConventionAnnotation? annotation, + IConventionAnnotation? oldAnnotation, + IConventionContext context) + { + switch (name) + { + case CosmosAnnotationNames.AlwaysCreateShadowIdProperty: + case CosmosAnnotationNames.DiscriminatorInKey: + foreach (var entityType in modelBuilder.Metadata.GetEntityTypes()) + { + ProcessEntityType(entityType, context); + } + + break; + } + } + + /// + public void ProcessDiscriminatorPropertySet( + IConventionEntityTypeBuilder entityTypeBuilder, + string? name, + IConventionContext context) + => ProcessEntityType(entityTypeBuilder.Metadata, context); + + /// + public void ProcessModelFinalizing(IConventionModelBuilder modelBuilder, IConventionContext context) + { + foreach (var entityType in modelBuilder.Metadata.GetEntityTypes()) + { + ProcessEntityType(entityType, context); + } + } +} diff --git a/src/EFCore.Cosmos/Metadata/Conventions/StoreKeyConvention.cs b/src/EFCore.Cosmos/Metadata/Conventions/CosmosKeyAugmenterConvention.cs similarity index 63% rename from src/EFCore.Cosmos/Metadata/Conventions/StoreKeyConvention.cs rename to src/EFCore.Cosmos/Metadata/Conventions/CosmosKeyAugmenterConvention.cs index 43c86da1b76..43067d8859a 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/StoreKeyConvention.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/CosmosKeyAugmenterConvention.cs @@ -2,14 +2,13 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; -using Microsoft.EntityFrameworkCore.Cosmos.ValueGeneration.Internal; using Newtonsoft.Json.Linq; // ReSharper disable once CheckNamespace namespace Microsoft.EntityFrameworkCore.Metadata.Conventions; /// -/// A convention that adds the 'id' property - a key required by Azure Cosmos. +/// A convention that adds partition key properties to the EF primary key. /// /// /// @@ -20,7 +19,7 @@ namespace Microsoft.EntityFrameworkCore.Metadata.Conventions; /// Accessing Azure Cosmos DB with EF Core for more information and examples. /// /// -public class StoreKeyConvention : +public class CosmosKeyAugmenterConvention : IEntityTypeAddedConvention, IPropertyAnnotationChangedConvention, IForeignKeyOwnershipChangedConvention, @@ -31,24 +30,6 @@ public class StoreKeyConvention : IEntityTypeAnnotationChangedConvention, IEntityTypeBaseTypeChangedConvention { - /// - /// 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 static readonly string IdPropertyJsonName = "id"; - - /// - /// 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 static readonly string DefaultIdPropertyName = "__id"; - /// /// 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 @@ -59,10 +40,10 @@ public class StoreKeyConvention : public static readonly string JObjectPropertyName = "__jObject"; /// - /// Creates a new instance of . + /// Creates a new instance of . /// /// Parameter object containing dependencies for this convention. - public StoreKeyConvention(ProviderConventionSetBuilderDependencies dependencies) + public CosmosKeyAugmenterConvention(ProviderConventionSetBuilderDependencies dependencies) { Dependencies = dependencies; } @@ -72,89 +53,38 @@ public StoreKeyConvention(ProviderConventionSetBuilderDependencies dependencies) /// protected virtual ProviderConventionSetBuilderDependencies Dependencies { get; } - private static void ProcessIdProperty(IConventionEntityTypeBuilder entityTypeBuilder) + private void ProcessIdProperty(IConventionEntityTypeBuilder entityTypeBuilder) { - IConventionKey? newKey = null; - IConventionProperty? idProperty; var entityType = entityTypeBuilder.Metadata; + var primaryKey = entityType.FindPrimaryKey(); if (entityType.BaseType == null && entityType.IsDocumentRoot() - && !entityType.IsKeyless) + && primaryKey != null) { - idProperty = entityType.FindDeclaredProperty(DefaultIdPropertyName) - ?? entityType.GetDeclaredProperties().FirstOrDefault(p => p.GetJsonPropertyName() == IdPropertyJsonName) - ?? entityTypeBuilder.Property(typeof(string), DefaultIdPropertyName, setTypeConfigurationSource: false) - ?.ToJsonProperty(IdPropertyJsonName)?.Metadata; - - if (idProperty != null) + if (ConfigurationSource.Convention.Overrides(primaryKey.GetConfigurationSource())) { - var converter = idProperty.GetValueConverter(); - if ((converter == null ? idProperty.ClrType : converter.ProviderClrType) == typeof(string)) - { - if (idProperty.IsPrimaryKey()) - { - idProperty.Builder.HasValueGenerator((Type?)null); - } - else - { - idProperty.Builder.HasValueGeneratorFactory(typeof(IdValueGeneratorFactory)); - } - } - + // Add partition key properties to the primary key, unless they are already in the primary key. var partitionKeyProperties = entityType.GetPartitionKeyProperties(); + var primaryKeyProperties = primaryKey.Properties.ToList(); + var keyContainsPartitionProperties = false; if (partitionKeyProperties.Any() && partitionKeyProperties.All(p => p != null)) { - if (partitionKeyProperties.Count == 1 - && partitionKeyProperties[0] == idProperty) + foreach (var partitionKeyProperty in partitionKeyProperties) { - newKey = entityTypeBuilder.HasKey([idProperty])?.Metadata; - } - else - { - var keyContainsPartitionProperties = false; - var keys = entityType.GetKeys().ToList(); - foreach (var key in keys) - { - if (key.Properties.Contains(idProperty) - && partitionKeyProperties.All(p => key.Properties.Contains(p))) - { - keyContainsPartitionProperties = true; - break; - } - } - - if (!keyContainsPartitionProperties) + if (!primaryKeyProperties.Contains(partitionKeyProperty!)) { - var properties = new[] { idProperty }.Concat(partitionKeyProperties).ToList(); - newKey = entityTypeBuilder.HasKey(properties!)?.Metadata; + primaryKeyProperties.Add(partitionKeyProperty!); + keyContainsPartitionProperties = true; } - entityTypeBuilder.HasNoKey(new[] { idProperty }); } - } - else - { - newKey = entityTypeBuilder.HasKey([idProperty])?.Metadata; - } - } - } - else - { - idProperty = entityType.FindDeclaredProperty(DefaultIdPropertyName); - } - // If we created a new key above that maps to the __id property, then remove any existing keys - // that were previously mapped to it. - if (idProperty != null - && newKey != null) - { - var oldKeys = idProperty.GetContainingKeys().ToList(); - foreach (var oldKey in oldKeys) - { - if (oldKey != newKey) - { - oldKey.DeclaringEntityType.Builder.HasNoKey(oldKey); + if (keyContainsPartitionProperties) + { + primaryKey.DeclaringEntityType.Builder.HasNoKey(primaryKey); + entityTypeBuilder.HasKey(primaryKeyProperties); + } } } } @@ -246,8 +176,10 @@ public virtual void ProcessEntityTypePrimaryKeyChanged( IConventionKey? previousPrimaryKey, IConventionContext context) { - if ((newPrimaryKey != null && newPrimaryKey.Properties.Any(p => p.GetJsonPropertyName() == IdPropertyJsonName)) - || (previousPrimaryKey != null && previousPrimaryKey.Properties.Any(p => p.GetJsonPropertyName() == IdPropertyJsonName))) + if ((newPrimaryKey != null && newPrimaryKey.Properties + .Any(p => p.GetJsonPropertyName() == CosmosJsonIdConvention.IdPropertyJsonName)) + || (previousPrimaryKey != null && previousPrimaryKey.Properties + .Any(p => p.GetJsonPropertyName() == CosmosJsonIdConvention.IdPropertyJsonName))) { ProcessIdProperty(entityTypeBuilder); } @@ -316,12 +248,12 @@ public virtual void ProcessPropertyAnnotationChanged( IConventionContext context) { if (name == CosmosAnnotationNames.PropertyName - && (string?)annotation?.Value == IdPropertyJsonName - && propertyBuilder.Metadata.Name != DefaultIdPropertyName) + && (string?)annotation?.Value == CosmosJsonIdConvention.IdPropertyJsonName + && propertyBuilder.Metadata.Name != CosmosJsonIdConvention.DefaultIdPropertyName) { var declaringType = propertyBuilder.Metadata.DeclaringType; - var idProperty = declaringType.FindProperty(DefaultIdPropertyName); + var idProperty = declaringType.FindProperty(CosmosJsonIdConvention.DefaultIdPropertyName); if (idProperty != null) { foreach (var key in idProperty.GetContainingKeys().ToList()) diff --git a/src/EFCore.Cosmos/Metadata/Conventions/Internal/CosmosConventionSetBuilder.cs b/src/EFCore.Cosmos/Metadata/Conventions/Internal/CosmosConventionSetBuilder.cs index 8a4ffed5fe1..f2625bf56a4 100644 --- a/src/EFCore.Cosmos/Metadata/Conventions/Internal/CosmosConventionSetBuilder.cs +++ b/src/EFCore.Cosmos/Metadata/Conventions/Internal/CosmosConventionSetBuilder.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; + namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata.Conventions.Internal; /// @@ -17,11 +19,25 @@ public class CosmosConventionSetBuilder : ProviderConventionSetBuilder /// 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. /// - public CosmosConventionSetBuilder(ProviderConventionSetBuilderDependencies dependencies) + public CosmosConventionSetBuilder( + ProviderConventionSetBuilderDependencies dependencies, + IJsonIdDefinitionFactory definitionFactory) : base(dependencies) { + DefinitionFactory = definitionFactory; } + /// + /// The factory to create a for each entity type. + /// + /// + /// 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. + /// > + protected virtual IJsonIdDefinitionFactory DefinitionFactory { get; } + /// /// 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 @@ -34,7 +50,8 @@ public override ConventionSet CreateConventionSet() conventionSet.Add(new ContextContainerConvention(Dependencies)); conventionSet.Add(new ETagPropertyConvention()); - conventionSet.Add(new StoreKeyConvention(Dependencies)); + conventionSet.Add(new CosmosKeyAugmenterConvention(Dependencies)); + conventionSet.Add(new CosmosJsonIdConvention(Dependencies, DefinitionFactory)); conventionSet.Remove(typeof(ForeignKeyIndexConvention)); conventionSet.Replace(new CosmosValueGenerationConvention(Dependencies)); diff --git a/src/EFCore.Cosmos/Metadata/DiscriminatorInKeyBehavior.cs b/src/EFCore.Cosmos/Metadata/DiscriminatorInKeyBehavior.cs new file mode 100644 index 00000000000..aa61a0e5dbe --- /dev/null +++ b/src/EFCore.Cosmos/Metadata/DiscriminatorInKeyBehavior.cs @@ -0,0 +1,26 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace Microsoft.EntityFrameworkCore.Cosmos.Metadata; + +/// +/// Defines the behavior for including discriminator values in the JSON "id" value. +/// +public enum DiscriminatorInKeyBehavior +{ + /// + /// No discriminator value is included in the "id" value. + /// + None, + + /// + /// The discriminator value of the entity type is included in the "id" value. This was the default behavior before EF Core 9. + /// + EntityTypeName, + + /// + /// The discriminator value of the root entity type is included in the "id" value. This allows types with the same + /// primary key to be saved in the same container, while still allowing "ReadItem" to be used for lookups of an unknown type. + /// + RootEntityTypeName +} diff --git a/src/EFCore.Cosmos/Metadata/Internal/CosmosAnnotationNames.cs b/src/EFCore.Cosmos/Metadata/Internal/CosmosAnnotationNames.cs index e9eab69bbb5..02e2af7ff1a 100644 --- a/src/EFCore.Cosmos/Metadata/Internal/CosmosAnnotationNames.cs +++ b/src/EFCore.Cosmos/Metadata/Internal/CosmosAnnotationNames.cs @@ -83,6 +83,22 @@ public static class CosmosAnnotationNames /// public const string JsonIdDefinition = Prefix + "JsonIdDefinition"; + /// + /// 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. + /// + public const string DiscriminatorInKey = Prefix + "DiscriminatorInKey"; + + /// + /// 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. + /// + public const string AlwaysCreateShadowIdProperty = Prefix + "AlwaysCreateShadowIdProperty"; + /// /// 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 diff --git a/src/EFCore.Cosmos/Metadata/Internal/IJsonIdDefinition.cs b/src/EFCore.Cosmos/Metadata/Internal/IJsonIdDefinition.cs index 32078af8539..da2568eb10c 100644 --- a/src/EFCore.Cosmos/Metadata/Internal/IJsonIdDefinition.cs +++ b/src/EFCore.Cosmos/Metadata/Internal/IJsonIdDefinition.cs @@ -19,6 +19,18 @@ public interface IJsonIdDefinition /// IReadOnlyList Properties { get; } + /// + /// This type is the base type when the base type discriminator is included in the key, and the + /// actual type when the actual type discriminator is included in the key. See . + /// + /// + /// 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. + /// + IEntityType? DiscriminatorEntityType { get; } + /// /// 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 diff --git a/src/EFCore.Cosmos/Metadata/Internal/JsonIdDefinition.cs b/src/EFCore.Cosmos/Metadata/Internal/JsonIdDefinition.cs index c94d957fcc7..eb886f5e9f6 100644 --- a/src/EFCore.Cosmos/Metadata/Internal/JsonIdDefinition.cs +++ b/src/EFCore.Cosmos/Metadata/Internal/JsonIdDefinition.cs @@ -20,9 +20,12 @@ public class JsonIdDefinition : IJsonIdDefinition /// 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. /// - public JsonIdDefinition(IReadOnlyList properties) + public JsonIdDefinition( + IReadOnlyList properties, + IEntityType? discriminatorEntityType) { Properties = properties; + DiscriminatorEntityType = discriminatorEntityType; } /// @@ -33,6 +36,18 @@ public JsonIdDefinition(IReadOnlyList properties) /// public virtual IReadOnlyList Properties { get; } + /// + /// This type is the base type when the base type discriminator is included in the key, and the + /// actual type when the actual type discriminator is included in the key. See . + /// + /// + /// 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. + /// + public virtual IEntityType? DiscriminatorEntityType { get; } + /// /// 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 @@ -51,18 +66,28 @@ public virtual string GenerateIdString(EntityEntry entry) public virtual string GenerateIdString(IEnumerable values) { var builder = new StringBuilder(); + + if (DiscriminatorEntityType != null) + { + AppendValue(DiscriminatorEntityType.FindDiscriminatorProperty()!, DiscriminatorEntityType.GetDiscriminatorValue()); + } + var i = 0; foreach (var value in values) { - var property = Properties[i++]; - var converter = property.GetTypeMapping().Converter; - AppendString(builder, converter == null ? value : converter.ConvertToProvider(value)); - builder.Append('|'); + AppendValue(Properties[i++], value); } builder.Remove(builder.Length - 1, 1); return builder.ToString(); + + void AppendValue(IProperty property, object? value) + { + var converter = property.GetTypeMapping().Converter; + AppendString(builder, converter == null ? value : converter.ConvertToProvider(value)); + builder.Append('|'); + } } /// diff --git a/src/EFCore.Cosmos/Metadata/Internal/JsonIdDefinitionFactory.cs b/src/EFCore.Cosmos/Metadata/Internal/JsonIdDefinitionFactory.cs index c404f9d5648..c4e8f439f09 100644 --- a/src/EFCore.Cosmos/Metadata/Internal/JsonIdDefinitionFactory.cs +++ b/src/EFCore.Cosmos/Metadata/Internal/JsonIdDefinitionFactory.cs @@ -36,47 +36,39 @@ public class JsonIdDefinitionFactory : IJsonIdDefinitionFactory } } - var idProperty = entityType.GetProperties() - .FirstOrDefault(p => p.GetJsonPropertyName() == StoreKeyConvention.IdPropertyJsonName); + if (!primaryKeyProperties.Any()) + { + primaryKeyProperties = entityType.GetPartitionKeyProperties().ToList(); + } var properties = new List(); - // If the property mapped to the JSON id is simply the primary key, or is the primary key without partition keys, then use - // it directly. - if ((primaryKeyProperties.Count == 1 - && primaryKeyProperties[0] == idProperty) - || (primaryKey.Properties.Count == 1 - && primaryKey.Properties[0] == idProperty)) - { - properties.Add(idProperty); - } + var includeDiscriminator = entityType.GetDiscriminatorInKey() ?? entityType.Model.GetDiscriminatorInKey(); - // Otherwise, if the property mapped to the JSON id doesn't have a generator, then we can't use ReadItem. - else if (idProperty != null && idProperty.GetValueGeneratorFactory() == null) - { - return null; - } - else + IEntityType? discriminatorEntityType = null; + if (includeDiscriminator is DiscriminatorInKeyBehavior.EntityTypeName or DiscriminatorInKeyBehavior.RootEntityTypeName) { var discriminator = entityType.GetDiscriminatorValue(); - // If the discriminator is not part of the primary key already, then add it to the Cosmos `id`. if (discriminator != null) { var discriminatorProperty = entityType.FindDiscriminatorProperty(); if (!primaryKey.Properties.Contains(discriminatorProperty)) { - properties.Add(discriminatorProperty!); + // Use the actual type for backwards compat, but the base type to allow lookup using ReadItem. + discriminatorEntityType = includeDiscriminator is DiscriminatorInKeyBehavior.EntityTypeName + ? entityType + : entityType.GetRootType(); } } + } - // Next add all primary key properties, except for those that are also partition keys, which were removed above. - foreach (var property in primaryKeyProperties) - { - properties.Add(property); - } + // Next add all primary key properties, except for those that are also partition keys, which were removed above. + foreach (var property in primaryKeyProperties) + { + properties.Add(property); } - return new JsonIdDefinition(properties); + return new JsonIdDefinition(properties, discriminatorEntityType); } } diff --git a/src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs b/src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs index de52cff2d77..bee88e3efc8 100644 --- a/src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs +++ b/src/EFCore.Cosmos/Properties/CosmosStrings.Designer.cs @@ -205,14 +205,6 @@ public static string NoDiscriminatorValue(object? entityType, object? container) GetString("NoDiscriminatorValue", nameof(entityType), nameof(container)), entityType, container); - /// - /// The entity type '{entityType}' does not have a key declared on the '{idProperty}' property. Add a key to '{entityType}' that contains '{idProperty}'. - /// - public static string NoIdKey(object? entityType, object? idProperty) - => string.Format( - GetString("NoIdKey", nameof(entityType), nameof(idProperty)), - entityType, idProperty); - /// /// The entity type '{entityType}' does not have a property mapped to the 'id' property in the database. Add a property mapped to 'id'. /// @@ -251,14 +243,6 @@ public static string NoPartitionKey(object? entityType1, object? props1, object? GetString("NoPartitionKey", nameof(entityType1), nameof(props1), nameof(entityType2), nameof(props2), nameof(containerName)), entityType1, props1, entityType2, props2, containerName); - /// - /// The entity type '{entityType}' does not have a key declared on '{partitionKey}' and '{idProperty}' properties. Add a key to '{entityType}' that contains '{partitionKey}' and '{idProperty}'. - /// - public static string NoPartitionKeyKey(object? entityType, object? partitionKey, object? idProperty) - => string.Format( - GetString("NoPartitionKeyKey", nameof(entityType), nameof(partitionKey), nameof(idProperty)), - entityType, partitionKey, idProperty); - /// /// There is no string-based representation of this query as it's executed using 'ReadItemQueryAsync({resourceId}, {partitionKey})'. /// diff --git a/src/EFCore.Cosmos/Properties/CosmosStrings.resx b/src/EFCore.Cosmos/Properties/CosmosStrings.resx index e4ad7e2a6ab..34dd1c970c1 100644 --- a/src/EFCore.Cosmos/Properties/CosmosStrings.resx +++ b/src/EFCore.Cosmos/Properties/CosmosStrings.resx @@ -228,9 +228,6 @@ The entity type '{entityType}' is sharing the container '{container}' with other types, but does not have a discriminator value configured. Configure a unique discriminator value for this entity type. - - The entity type '{entityType}' does not have a key declared on the '{idProperty}' property. Add a key to '{entityType}' that contains '{idProperty}'. - The entity type '{entityType}' does not have a property mapped to the 'id' property in the database. Add a property mapped to 'id'. @@ -246,9 +243,6 @@ The partition key properties for entity type '{entityType1}' are '{props1}', while the partition key properties for entity type '{entityType2}' are '{props2}', and both entity types are mapped to the container '{containerName}'. All entity types mapped to the same container must have compatible partition keys defined. - - The entity type '{entityType}' does not have a key declared on '{partitionKey}' and '{idProperty}' properties. Add a key to '{entityType}' that contains '{partitionKey}' and '{idProperty}'. - There is no string-based representation of this query as it's executed using 'ReadItemQueryAsync({resourceId}, {partitionKey})'. diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs index 56fcda77c5c..10cacb25811 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosQueryableMethodTranslatingExpressionVisitor.cs @@ -317,7 +317,10 @@ protected override QueryableMethodTranslatingExpressionVisitor CreateSubqueryVis if (concreteEntityTypes is [var singleEntityType] && singleEntityType.GetIsDiscriminatorMappingComplete() && entityType.GetContainer() is var container - && !entityType.Model.GetEntityTypes().Any(e => e.GetContainer() == container && e != singleEntityType)) + && !entityType.Model.GetEntityTypes().Any( + // If a read-only/view type is mapped to the same container with the same discriminator, then we still don't need + // the discriminator, allowing ReadItem in more places. + e => e.GetContainer() == container && !Equals(e.GetDiscriminatorValue(), singleEntityType.GetDiscriminatorValue()))) { // There's a single entity type mapped to the container and the discriminator mapping is complete; we can skip the // discriminator predicate. diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosReadItemAndPartitionKeysExtractor.cs b/src/EFCore.Cosmos/Query/Internal/CosmosReadItemAndPartitionKeysExtractor.cs index 130fbe68d6d..6dac3bc4e8a 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosReadItemAndPartitionKeysExtractor.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosReadItemAndPartitionKeysExtractor.cs @@ -21,6 +21,7 @@ public class CosmosReadItemAndPartitionKeysExtractor : ExpressionVisitor private IEntityType _entityType = null!; private string _rootAlias = null!; private bool _isPredicateCompatibleWithReadItem; + private bool _discriminatorInJsonId; private string? _discriminatorJsonPropertyName; private Dictionary _jsonIdPropertyValues = null!; private Dictionary _partitionKeyPropertyValues = null!; @@ -59,7 +60,9 @@ public virtual Expression ExtractPartitionKeysAndId( // from the tree (either constants or parameters). // We also want to ignore the discriminator property if it's compared to our entity type's discriminator value (see below). _isPredicateCompatibleWithReadItem = true; - var jsonIdProperties = _entityType.GetJsonIdDefinition()?.Properties ?? []; + var jsonIdDefinition = _entityType.GetJsonIdDefinition(); + _discriminatorInJsonId = jsonIdDefinition?.DiscriminatorEntityType != null; + var jsonIdProperties = jsonIdDefinition?.Properties ?? []; if (jsonIdProperties.Count == 0) { // No JSON ID definition - no ReadItem @@ -70,25 +73,13 @@ public virtual Expression ExtractPartitionKeysAndId( var partitionKeyProperties = _entityType.GetPartitionKeyProperties(); _partitionKeyPropertyValues = partitionKeyProperties.ToDictionary(p => p, _ => (Expression?)null); - - var discriminatorProperty = _entityType.FindDiscriminatorProperty(); - _discriminatorJsonPropertyName = discriminatorProperty?.GetJsonPropertyName(); + _discriminatorJsonPropertyName = _entityType.FindDiscriminatorProperty()?.GetJsonPropertyName(); // Visit the predicate. // This will populate _jsonIdPropertyValues and _partitionKeyPropertyValues with comparisons found in the predicate, and return // a rewritten predicate where the partition key comparisons have been removed. var predicateWithoutPartitionKeyComparisons = (SqlExpression)Visit(predicate); - // If the discriminator is part of the JSON id definition, a comparison may be missing from the predicate, since we don't add one - // if it's not needed (e.g. only one entity type mapped to the container). For that case, add the entity type's discriminator value. - if (discriminatorProperty is not null - && _jsonIdPropertyValues.TryGetValue(discriminatorProperty, out var discriminatorValue) - && discriminatorValue is null) - { - _jsonIdPropertyValues[discriminatorProperty] = _sqlExpressionFactory.Constant( - _entityType.GetDiscriminatorValue(), discriminatorProperty.ClrType); - } - var allIdPropertiesSpecified = _jsonIdPropertyValues.Values.All(p => p is not null) && _jsonIdPropertyValues.Count > 0; var allPartitionKeyPropertiesSpecified = _partitionKeyPropertyValues.Values.All(p => p is not null); @@ -126,9 +117,6 @@ public virtual Expression ExtractPartitionKeysAndId( // a params object[] argument that gets parameterized as a single array. So the number of property values may not match the // number of partition key properties. && (partitionKeyProperties.Count == 0 || queryCompilationContext.PartitionKeyPropertyValues.Count > 0) - // If the entity type being queried has derived types and the discriminator is part of the JSON id, we can't reliably use - // ReadItem, since we don't know in advance which derived type the document represents. - && (!jsonIdProperties.Contains(discriminatorProperty) || !_entityType.GetDerivedTypes().Any()) && select is { Offset: null or SqlConstantExpression { Value: 0 }, @@ -226,17 +214,25 @@ SqlExpression ProcessPropertyComparison(string propertyName, SqlExpression prope // property, a partition key property, or certain cases involving the discriminator property. var isCompatibleComparisonForReadItem = false; - foreach (var property in _jsonIdPropertyValues.Keys) + if (propertyName == _discriminatorJsonPropertyName + && _discriminatorInJsonId) { - if (propertyName == property.GetJsonPropertyName()) + isCompatibleComparisonForReadItem = true; + } + else + { + foreach (var property in _jsonIdPropertyValues.Keys) { - if (_jsonIdPropertyValues.TryGetValue(property, out var previousValue) - && (previousValue is null || previousValue.Equals(propertyValue))) + if (propertyName == property.GetJsonPropertyName()) { - _jsonIdPropertyValues[property] = propertyValue; - isCompatibleComparisonForReadItem = true; + if (_jsonIdPropertyValues.TryGetValue(property, out var previousValue) + && (previousValue is null || previousValue.Equals(propertyValue))) + { + _jsonIdPropertyValues[property] = propertyValue; + isCompatibleComparisonForReadItem = true; + } + break; } - break; } } @@ -254,22 +250,6 @@ SqlExpression ProcessPropertyComparison(string propertyName, SqlExpression prope } } - // The query contains a comparison on the discriminator property. - // If the discriminator is part of the JSON ID property, it'll be handled below like any other JSON ID property. - // However, if it isn't, we may need to ignore the comparison, and allow transforming to ReadItem. For example, when - // multiple entity types are mapped to the same container, EF adds a discriminator comparison; but we want to use ReadItem - // for these (common) cases - so we ignore the comparison for the purpose of ReadItem transformation, and validate the - // discriminator coming back from Cosmos in the shaper, to ensure throwing for an incorrect type. - if (isCompatibleComparisonForReadItem - && propertyName == _discriminatorJsonPropertyName - && propertyValue is SqlConstantExpression { Value: object specifiedDiscriminatorValue } - && _entityType.FindDiscriminatorProperty() is IProperty discriminatorProperty - && _entityType.GetDiscriminatorValue() is object entityDiscriminatorValue - && discriminatorProperty.GetProviderValueComparer().Equals(specifiedDiscriminatorValue, entityDiscriminatorValue)) - { - isCompatibleComparisonForReadItem = true; - } - if (!isCompatibleComparisonForReadItem) { _isPredicateCompatibleWithReadItem = false; diff --git a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitorBase.cs b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitorBase.cs index 7e76f163570..cd358df9eeb 100644 --- a/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitorBase.cs +++ b/src/EFCore.Cosmos/Query/Internal/CosmosShapedQueryCompilingExpressionVisitor.CosmosProjectionBindingRemovingExpressionVisitorBase.cs @@ -610,7 +610,7 @@ private Expression CreateGetValueExpression( IProperty property, Type type) { - if (property.Name == StoreKeyConvention.JObjectPropertyName) + if (property.Name == CosmosKeyAugmenterConvention.JObjectPropertyName) { return _projectionBindings[jTokenExpression]; } diff --git a/src/EFCore.Cosmos/Query/Internal/Expressions/EntityProjectionExpression.cs b/src/EFCore.Cosmos/Query/Internal/Expressions/EntityProjectionExpression.cs index fab66144c86..2ceff4ef95e 100644 --- a/src/EFCore.Cosmos/Query/Internal/Expressions/EntityProjectionExpression.cs +++ b/src/EFCore.Cosmos/Query/Internal/Expressions/EntityProjectionExpression.cs @@ -118,7 +118,7 @@ public virtual Expression BindProperty(IProperty property, bool clientEval) // TODO: Remove once __jObject is translated to the access root in a better fashion and // would not otherwise be found to be non-translatable. See issues #17670 and #14121. // TODO: We shouldn't be returning null from here - && property.Name != StoreKeyConvention.JObjectPropertyName + && property.Name != CosmosKeyAugmenterConvention.JObjectPropertyName && expression.PropertyName?.Length is null or 0) { // Non-persisted property can't be translated diff --git a/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs b/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs index 6fae101e89f..2c6cc8625ef 100644 --- a/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs +++ b/src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs @@ -491,13 +491,13 @@ private static async Task DeleteItemOnceAsync( { case EntityState.Modified: { - var jObjectProperty = entry.EntityType.FindProperty(StoreKeyConvention.JObjectPropertyName); + var jObjectProperty = entry.EntityType.FindProperty(CosmosKeyAugmenterConvention.JObjectPropertyName); enabledContentResponse = (jObjectProperty?.ValueGenerated & ValueGenerated.OnUpdate) == ValueGenerated.OnUpdate; break; } case EntityState.Added: { - var jObjectProperty = entry.EntityType.FindProperty(StoreKeyConvention.JObjectPropertyName); + var jObjectProperty = entry.EntityType.FindProperty(CosmosKeyAugmenterConvention.JObjectPropertyName); enabledContentResponse = (jObjectProperty?.ValueGenerated & ValueGenerated.OnAdd) == ValueGenerated.OnAdd; break; } @@ -536,7 +536,7 @@ private static void ProcessResponse(ResponseMessage response, IUpdateEntry entry entry.SetStoreGeneratedValue(etagProperty, response.Headers.ETag); } - var jObjectProperty = entry.EntityType.FindProperty(StoreKeyConvention.JObjectPropertyName); + var jObjectProperty = entry.EntityType.FindProperty(CosmosKeyAugmenterConvention.JObjectPropertyName); if (jObjectProperty is { ValueGenerated: ValueGenerated.OnAddOrUpdate } && response.Content != null) { diff --git a/src/EFCore.Cosmos/Update/Internal/DocumentSource.cs b/src/EFCore.Cosmos/Update/Internal/DocumentSource.cs index d479da1caa1..ac5c6ef12ce 100644 --- a/src/EFCore.Cosmos/Update/Internal/DocumentSource.cs +++ b/src/EFCore.Cosmos/Update/Internal/DocumentSource.cs @@ -35,8 +35,8 @@ public DocumentSource(IEntityType entityType, CosmosDatabaseWrapper database) _containerId = entityType.GetContainer()!; _database = database; _entityType = entityType; - _idProperty = entityType.GetProperties().FirstOrDefault(p => p.GetJsonPropertyName() == StoreKeyConvention.IdPropertyJsonName); - _jObjectProperty = entityType.FindProperty(StoreKeyConvention.JObjectPropertyName); + _idProperty = entityType.GetProperties().FirstOrDefault(p => p.GetJsonPropertyName() == CosmosJsonIdConvention.IdPropertyJsonName); + _jObjectProperty = entityType.FindProperty(CosmosKeyAugmenterConvention.JObjectPropertyName); } /// diff --git a/test/EFCore.Cosmos.FunctionalTests/BuiltInDataTypesCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/BuiltInDataTypesCosmosTest.cs index ed27624a809..d749aabc5f0 100644 --- a/test/EFCore.Cosmos.FunctionalTests/BuiltInDataTypesCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/BuiltInDataTypesCosmosTest.cs @@ -100,6 +100,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con { base.OnModelCreating(modelBuilder, context); + modelBuilder.IncludeDiscriminatorInJsonId(); + var shadowJObject = (Property)modelBuilder.Entity().Property("__jObject").Metadata; shadowJObject.SetConfigurationSource(ConfigurationSource.Convention); var nullableShadowJObject = (Property)modelBuilder.Entity().Property("__jObject").Metadata; diff --git a/test/EFCore.Cosmos.FunctionalTests/CustomConvertersCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/CustomConvertersCosmosTest.cs index 359f3f66f4c..91749bb09f7 100644 --- a/test/EFCore.Cosmos.FunctionalTests/CustomConvertersCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/CustomConvertersCosmosTest.cs @@ -184,6 +184,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con { base.OnModelCreating(modelBuilder, context); + modelBuilder.IncludeDiscriminatorInJsonId(); + var shadowJObject = (Property)modelBuilder.Entity().Property("__jObject").Metadata; shadowJObject.SetConfigurationSource(ConfigurationSource.Convention); var nullableShadowJObject = (Property)modelBuilder.Entity().Property("__jObject").Metadata; diff --git a/test/EFCore.Cosmos.FunctionalTests/EmbeddedDocumentsTest.cs b/test/EFCore.Cosmos.FunctionalTests/EmbeddedDocumentsTest.cs index 7626d17a243..1ac57f03370 100644 --- a/test/EFCore.Cosmos.FunctionalTests/EmbeddedDocumentsTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/EmbeddedDocumentsTest.cs @@ -737,6 +737,8 @@ protected class EmbeddedTransportationContext(EmbeddedTransportationContextOptio protected override void OnModelCreating(ModelBuilder modelBuilder) { + modelBuilder.IncludeDiscriminatorInJsonId(); + modelBuilder.Entity( eb => { diff --git a/test/EFCore.Cosmos.FunctionalTests/EndToEndCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/EndToEndCosmosTest.cs index 521db9b9360..839f432641e 100644 --- a/test/EFCore.Cosmos.FunctionalTests/EndToEndCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/EndToEndCosmosTest.cs @@ -197,12 +197,12 @@ public async Task Can_add_update_delete_detached_entity_end_to_end_async() await context.AddAsync(customer); - storeId = entry.Property(StoreKeyConvention.DefaultIdPropertyName).CurrentValue; + storeId = entry.Property(CosmosJsonIdConvention.DefaultIdPropertyName).CurrentValue; Assert.Empty(ListLoggerFactory.Log.Where(l => l.Id == CosmosEventId.SyncNotSupported)); } - Assert.Equal("Customer|42", storeId); + Assert.Equal("42", storeId); using (var context = contextFactory.CreateContext()) { @@ -219,7 +219,8 @@ public async Task Can_add_update_delete_detached_entity_end_to_end_async() customer.Name = "Theon Greyjoy"; var entry = context.Entry(customer); - entry.Property(StoreKeyConvention.DefaultIdPropertyName).CurrentValue = storeId; + + entry.Property(CosmosJsonIdConvention.DefaultIdPropertyName).CurrentValue = storeId; entry.State = EntityState.Modified; @@ -241,7 +242,7 @@ public async Task Can_add_update_delete_detached_entity_end_to_end_async() using (var context = contextFactory.CreateContext()) { var entry = context.Entry(customer); - entry.Property(StoreKeyConvention.DefaultIdPropertyName).CurrentValue = storeId; + entry.Property(CosmosJsonIdConvention.DefaultIdPropertyName).CurrentValue = storeId; entry.State = EntityState.Deleted; await context.SaveChangesAsync(); @@ -543,7 +544,7 @@ public async Task Can_add_update_delete_end_to_end_with_DateTime_async() var entry = await context.AddAsync(customer); - Assert.Equal("CustomerDateTime|0001-01-01T00:00:00.0000000|Theon^2F^5C^23^5C^5C^3F", entry.CurrentValues["__id"]); + Assert.Equal("0001-01-01T00:00:00.0000000|Theon^2F^5C^23^5C^5C^3F", entry.CurrentValues["__id"]); await context.SaveChangesAsync(); @@ -704,7 +705,7 @@ public async Task Entities_with_null_PK_can_be_added_with_normal_use_of_DbContex Assert.NotNull(item.Id); Assert.NotNull(id); - Assert.Equal($"GItem|{item.Id}", id); + Assert.Equal($"{item.Id}", id); Assert.Equal(EntityState.Added, entry.State); } @@ -722,19 +723,19 @@ public async Task var item = new Item { Id = 1337 }; var entry = context.Attach(item); - Assert.Equal($"Item|{item.Id}", entry.Property("__id").CurrentValue); + Assert.Equal($"{item.Id}", entry.Property("__id").CurrentValue); Assert.Equal(EntityState.Unchanged, entry.State); entry.State = EntityState.Detached; entry = context.Update(item = new Item { Id = 71 }); - Assert.Equal($"Item|{item.Id}", entry.Property("__id").CurrentValue); + Assert.Equal($"{item.Id}", entry.Property("__id").CurrentValue); Assert.Equal(EntityState.Modified, entry.State); entry.State = EntityState.Detached; entry = context.Remove(item = new Item { Id = 33 }); - Assert.Equal($"Item|{item.Id}", entry.Property("__id").CurrentValue); + Assert.Equal($"{item.Id}", entry.Property("__id").CurrentValue); Assert.Equal(EntityState.Deleted, entry.State); } @@ -1035,8 +1036,8 @@ public async Task Can_read_with_find_with_resource_id_async() await context.Database.EnsureCreatedAsync(); Assert.Null( - context.Model.FindEntityType(typeof(CustomerWithResourceId)) - .FindProperty(StoreKeyConvention.DefaultIdPropertyName)); + context.Model.FindEntityType(typeof(CustomerWithResourceId))! + .FindProperty(CosmosJsonIdConvention.DefaultIdPropertyName)); await context.AddAsync(customer); await context.AddAsync( @@ -1321,7 +1322,7 @@ public async Task Can_read_with_find_with_partition_key_without_value_generator( context.Database.EnsureCreated(); var customerEntry = context.Entry(customer); - customerEntry.Property(StoreKeyConvention.DefaultIdPropertyName).CurrentValue = "42"; + customerEntry.Property(CosmosJsonIdConvention.DefaultIdPropertyName).CurrentValue = "42"; customerEntry.State = EntityState.Added; context.SaveChanges(); @@ -1340,12 +1341,7 @@ public async Task Can_read_with_find_with_partition_key_without_value_generator( AssertSql( context, """ -@__p_3='42' - -SELECT VALUE c -FROM root c -WHERE (c["Id"] = @__p_3) -OFFSET 0 LIMIT 1 +ReadItem([1.0,"One",true], 42) """); customerFromStore.Name = "Theon Greyjoy"; @@ -1398,7 +1394,7 @@ public async Task Can_read_with_find_with_partition_key_not_part_of_primary_key( Assert.Equal(42, customerFromStore.Id); Assert.Equal("Theon", customerFromStore.Name); - AssertSql(context, """ReadItem(None, Customer|42)"""); + AssertSql(context, """ReadItem(None, 42)"""); } } @@ -1426,7 +1422,7 @@ public async Task Can_read_with_find_without_partition_key() Assert.Equal(42, customerFromStore.Id); Assert.Equal("Theon", customerFromStore.Name); - AssertSql(context, @"ReadItem(None, CustomerNoPartitionKey|42)"); + AssertSql(context, @"ReadItem(None, 42)"); } } @@ -1515,15 +1511,31 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) private class PartitionKeyContextCustomValueGenerator(DbContextOptions dbContextOptions) : DbContext(dbContextOptions) { protected override void OnModelCreating(ModelBuilder modelBuilder) - => modelBuilder.Entity( + { + modelBuilder.IncludeDiscriminatorInJsonId(); + + modelBuilder.Entity( cb => { - cb.Property(StoreKeyConvention.DefaultIdPropertyName) - .HasValueGeneratorFactory(typeof(CustomPartitionKeyIdValueGeneratorFactory)); - - cb.HasPartitionKey(c => new { c.PartitionKey1, c.PartitionKey2, c.PartitionKey3 }); - cb.HasKey(c => new { c.PartitionKey1, c.Id, c.PartitionKey2, c.PartitionKey3 }); + cb.AlwaysCreateShadowIdProperty(); + + cb.HasPartitionKey( + c => new + { + c.PartitionKey1, + c.PartitionKey2, + c.PartitionKey3 + }); + cb.HasKey( + c => new + { + c.PartitionKey1, + c.Id, + c.PartitionKey2, + c.PartitionKey3 + }); }); + } } private class PartitionKeyContextNoValueGenerator(DbContextOptions dbContextOptions) : DbContext(dbContextOptions) @@ -1532,10 +1544,21 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) => modelBuilder.Entity( cb => { - cb.Property(StoreKeyConvention.DefaultIdPropertyName).HasValueGenerator((Type)null); - - cb.HasPartitionKey(c => new { c.PartitionKey1, c.PartitionKey2, c.PartitionKey3 }); - cb.HasKey(c => new { c.PartitionKey1, c.PartitionKey2, c.PartitionKey3, c.Id }); + cb.HasPartitionKey( + c => new + { + c.PartitionKey1, + c.PartitionKey2, + c.PartitionKey3 + }); + cb.HasKey( + c => new + { + c.PartitionKey1, + c.PartitionKey2, + c.PartitionKey3, + c.Id + }); }); } diff --git a/test/EFCore.Cosmos.FunctionalTests/F1CosmosFixture.cs b/test/EFCore.Cosmos.FunctionalTests/F1CosmosFixture.cs index bbd545b8699..afba8e9af03 100644 --- a/test/EFCore.Cosmos.FunctionalTests/F1CosmosFixture.cs +++ b/test/EFCore.Cosmos.FunctionalTests/F1CosmosFixture.cs @@ -39,6 +39,8 @@ protected override void BuildModelExternal(ModelBuilder modelBuilder) { base.BuildModelExternal(modelBuilder); + modelBuilder.IncludeDiscriminatorInJsonId(); + modelBuilder.Entity( b => { diff --git a/test/EFCore.Cosmos.FunctionalTests/FindCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/FindCosmosTest.cs index f7e11ba4efc..8c4b7d1e54f 100644 --- a/test/EFCore.Cosmos.FunctionalTests/FindCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/FindCosmosTest.cs @@ -251,14 +251,14 @@ public override async Task Find_string_key_from_store_async(CancellationType can { await base.Find_string_key_from_store_async(cancellationType); - AssertSql("ReadItem(None, StringKey|Cat)"); + AssertSql("ReadItem(None, Cat)"); } public override async Task Returns_null_for_string_key_not_in_store_async(CancellationType cancellationType) { await base.Returns_null_for_string_key_not_in_store_async(cancellationType); - AssertSql("ReadItem(None, StringKey|Fox)"); + AssertSql("ReadItem(None, Fox)"); } public override async Task Find_composite_key_tracked_async(CancellationType cancellationType) @@ -272,14 +272,14 @@ public override async Task Find_composite_key_from_store_async(CancellationType { await base.Find_composite_key_from_store_async(cancellationType); - AssertSql("ReadItem(None, CompositeKey|77|Dog)"); + AssertSql("ReadItem(None, 77|Dog)"); } public override async Task Returns_null_for_composite_key_not_in_store_async(CancellationType cancellationType) { await base.Returns_null_for_composite_key_not_in_store_async(cancellationType); - AssertSql("ReadItem(None, CompositeKey|77|Fox)"); + AssertSql("ReadItem(None, 77|Fox)"); } public override async Task Find_base_type_tracked_async(CancellationType cancellationType) @@ -329,21 +329,24 @@ public override async Task Find_derived_type_from_store_async(CancellationType c { await base.Find_derived_type_from_store_async(cancellationType); - AssertSql("ReadItem(None, DerivedType|78)"); + AssertSql("ReadItem(None, BaseType|78)"); } public override async Task Returns_null_for_derived_type_not_in_store_async(CancellationType cancellationType) { await base.Returns_null_for_derived_type_not_in_store_async(cancellationType); - AssertSql("ReadItem(None, DerivedType|99)"); + AssertSql("ReadItem(None, BaseType|99)"); } public override async Task Find_base_type_using_derived_set_from_store_async(CancellationType cancellationType) { - await base.Find_base_type_using_derived_set_from_store_async(cancellationType); + Assert.Equal( + CoreStrings.UnableToDiscriminate("DerivedType", "BaseType"), + (await Assert.ThrowsAsync( + () => base.Find_base_type_using_derived_set_from_store_async(cancellationType))).Message); - AssertSql("ReadItem(None, DerivedType|77)"); + AssertSql("ReadItem(None, BaseType|77)"); } public override async Task Find_derived_type_using_base_set_tracked_async(CancellationType cancellationType) @@ -364,14 +367,14 @@ public override async Task Find_shadow_key_from_store_async(CancellationType can { await base.Find_shadow_key_from_store_async(cancellationType); - AssertSql("ReadItem(None, ShadowKey|77)"); + AssertSql("ReadItem(None, 77)"); } public override async Task Returns_null_for_shadow_key_not_in_store_async(CancellationType cancellationType) { await base.Returns_null_for_shadow_key_not_in_store_async(cancellationType); - AssertSql("ReadItem(None, ShadowKey|99)"); + AssertSql("ReadItem(None, 99)"); } public override async Task Returns_null_for_null_key_values_array_async(CancellationType cancellationType) @@ -468,5 +471,34 @@ public override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder build protected override ITestStoreFactory TestStoreFactory => CosmosTestStoreFactory.Instance; + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + + modelBuilder.Entity() + .ToContainer("Ints") + .IncludeRootDiscriminatorInJsonId(); + + modelBuilder.Entity() + .ToContainer("Ints") + .IncludeRootDiscriminatorInJsonId(); + + modelBuilder.Entity() + .ToContainer("Strings"); + + modelBuilder.Entity() + .ToContainer("CompositeKeys"); + + modelBuilder.Entity() + .ToContainer("Base") + .IncludeRootDiscriminatorInJsonId(); + + modelBuilder.Entity() + .ToContainer("Base") + .IncludeRootDiscriminatorInJsonId(); + + modelBuilder.Entity().ToContainer("ShadowKeys"); + } } } diff --git a/test/EFCore.Cosmos.FunctionalTests/KeysWithConvertersCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/KeysWithConvertersCosmosTest.cs index c06af99c669..f05d3fa6fc3 100644 --- a/test/EFCore.Cosmos.FunctionalTests/KeysWithConvertersCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/KeysWithConvertersCosmosTest.cs @@ -154,6 +154,8 @@ protected override ITestStoreFactory TestStoreFactory protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) { + modelBuilder.IncludeDiscriminatorInJsonId(); + modelBuilder.Entity( b => { b.Property(e => e.Id).HasConversion(IntStructKey.Converter); }); diff --git a/test/EFCore.Cosmos.FunctionalTests/ModelBuilding/CosmosModelBuilderGenericTest.cs b/test/EFCore.Cosmos.FunctionalTests/ModelBuilding/CosmosModelBuilderGenericTest.cs index 1eedaa164ca..063d56b6e29 100644 --- a/test/EFCore.Cosmos.FunctionalTests/ModelBuilding/CosmosModelBuilderGenericTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/ModelBuilding/CosmosModelBuilderGenericTest.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.EntityFrameworkCore.Cosmos.Internal; +using Microsoft.EntityFrameworkCore.Cosmos.Metadata.Internal; using Xunit.Sdk; // ReSharper disable InconsistentNaming @@ -119,13 +120,6 @@ public virtual void Partition_key_is_added_to_the_keys() Assert.Equal( new[] { nameof(Customer.Id), nameof(Customer.AlternateKey) }, entity.FindPrimaryKey()!.Properties.Select(p => p.Name)); - Assert.Equal( - new[] { StoreKeyConvention.DefaultIdPropertyName, nameof(Customer.AlternateKey) }, - entity.GetKeys().First(k => k != entity.FindPrimaryKey()).Properties.Select(p => p.Name)); - - var idProperty = entity.FindProperty(StoreKeyConvention.DefaultIdPropertyName)!; - Assert.Single(idProperty.GetContainingKeys()); - Assert.NotNull(idProperty.GetValueGeneratorFactory()); } [ConditionalFact] @@ -145,13 +139,6 @@ public virtual void Hierarchical_partition_key_is_added_to_the_keys() Assert.Equal( new[] { nameof(Customer.Title), nameof(Customer.Name) }, entity.GetPartitionKeyProperties().Select(p => p.Name)); - Assert.Equal( - new[] { StoreKeyConvention.DefaultIdPropertyName, nameof(Customer.Title), nameof(Customer.Name) }, - entity.GetKeys().First(k => k != entity.FindPrimaryKey()).Properties.Select(p => p.Name)); - - var idProperty = entity.FindProperty(StoreKeyConvention.DefaultIdPropertyName)!; - Assert.Single(idProperty.GetContainingKeys()); - Assert.NotNull(idProperty.GetValueGeneratorFactory()); } [ConditionalFact] @@ -172,13 +159,6 @@ public virtual void Three_level_hierarchical_partition_key_is_added_to_the_keys( Assert.Equal( new[] { nameof(Customer.Title), nameof(Customer.Name), nameof(Customer.AlternateKey) }, entity.GetPartitionKeyProperties().Select(p => p.Name)); - Assert.Equal( - new[] { StoreKeyConvention.DefaultIdPropertyName, nameof(Customer.Title), nameof(Customer.Name), nameof(Customer.AlternateKey) }, - entity.GetKeys().First(k => k != entity.FindPrimaryKey()).Properties.Select(p => p.Name)); - - var idProperty = entity.FindProperty(StoreKeyConvention.DefaultIdPropertyName)!; - Assert.Single(idProperty.GetContainingKeys()); - Assert.NotNull(idProperty.GetValueGeneratorFactory()); } [ConditionalFact] @@ -186,23 +166,24 @@ public virtual void Partition_key_is_added_to_the_alternate_key_if_primary_key_c { var modelBuilder = CreateModelBuilder(); - modelBuilder.Entity().HasKey(StoreKeyConvention.DefaultIdPropertyName); - modelBuilder.Entity() - .Ignore(b => b.Details) - .Ignore(b => b.Orders) - .HasPartitionKey(b => b.AlternateKey) - .Property(b => b.AlternateKey).HasConversion(); + modelBuilder.Entity( + b => + { + b.HasAnnotation(CosmosAnnotationNames.AlwaysCreateShadowIdProperty, true); + b.HasKey(CosmosJsonIdConvention.DefaultIdPropertyName); - var model = modelBuilder.FinalizeModel(); + b.Ignore(b => b.Details) + .Ignore(b => b.Orders) + .HasPartitionKey(b => b.AlternateKey) + .Property(b => b.AlternateKey).HasConversion(); + }); + var model = modelBuilder.FinalizeModel(); var entity = model.FindEntityType(typeof(Customer))!; Assert.Equal( - new[] { StoreKeyConvention.DefaultIdPropertyName }, + new[] { CosmosJsonIdConvention.DefaultIdPropertyName }, entity.FindPrimaryKey()!.Properties.Select(p => p.Name)); - Assert.Equal( - new[] { StoreKeyConvention.DefaultIdPropertyName, nameof(Customer.AlternateKey) }, - entity.GetKeys().First(k => k != entity.FindPrimaryKey()).Properties.Select(p => p.Name)); } [ConditionalFact] @@ -210,7 +191,9 @@ public virtual void Hierarchical_partition_key_is_added_to_the_alternate_key_if_ { var modelBuilder = CreateModelBuilder(); - modelBuilder.Entity().HasKey(StoreKeyConvention.DefaultIdPropertyName); + modelBuilder.Entity().HasAnnotation(CosmosAnnotationNames.AlwaysCreateShadowIdProperty, true); + modelBuilder.Entity().HasKey(CosmosJsonIdConvention.DefaultIdPropertyName); + modelBuilder.Entity() .Ignore(b => b.Details) .Ignore(b => b.Orders) @@ -231,17 +214,8 @@ public virtual void Hierarchical_partition_key_is_added_to_the_alternate_key_if_ new[] { nameof(Customer.AlternateKey), nameof(Customer.Name), nameof(Customer.Title) }, entity.GetPartitionKeyProperties().Select(p => p.Name)); Assert.Equal( - new[] { StoreKeyConvention.DefaultIdPropertyName }, + new[] { CosmosJsonIdConvention.DefaultIdPropertyName }, entity.FindPrimaryKey()!.Properties.Select(p => p.Name)); - Assert.Equal( - new[] - { - StoreKeyConvention.DefaultIdPropertyName, - nameof(Customer.AlternateKey), - nameof(Customer.Name), - nameof(Customer.Title) - }, - entity.GetKeys().First(k => k != entity.FindPrimaryKey()).Properties.Select(p => p.Name)); } [ConditionalFact] @@ -251,7 +225,7 @@ public virtual void No_id_property_created_if_another_property_mapped_to_id() modelBuilder.Entity() .Property(c => c.Name) - .ToJsonProperty(StoreKeyConvention.IdPropertyJsonName); + .ToJsonProperty(CosmosJsonIdConvention.IdPropertyJsonName); modelBuilder.Entity() .Ignore(b => b.Details) .Ignore(b => b.Orders); @@ -260,13 +234,7 @@ public virtual void No_id_property_created_if_another_property_mapped_to_id() var entity = model.FindEntityType(typeof(Customer))!; - Assert.Null(entity.FindProperty(StoreKeyConvention.DefaultIdPropertyName)); - Assert.Single(entity.GetKeys().Where(k => k != entity.FindPrimaryKey())); - - var idProperty = entity.GetDeclaredProperties() - .Single(p => p.GetJsonPropertyName() == StoreKeyConvention.IdPropertyJsonName); - Assert.Single(idProperty.GetContainingKeys()); - Assert.NotNull(idProperty.GetValueGeneratorFactory()); + Assert.Null(entity.FindProperty(CosmosJsonIdConvention.DefaultIdPropertyName)); } [ConditionalFact] @@ -276,7 +244,7 @@ public virtual void No_id_property_created_if_another_property_mapped_to_id_in_p modelBuilder.Entity() .Property(c => c.Name) - .ToJsonProperty(StoreKeyConvention.IdPropertyJsonName); + .ToJsonProperty(CosmosJsonIdConvention.IdPropertyJsonName); modelBuilder.Entity() .Ignore(c => c.Details) .Ignore(c => c.Orders) @@ -286,11 +254,11 @@ public virtual void No_id_property_created_if_another_property_mapped_to_id_in_p var entity = model.FindEntityType(typeof(Customer))!; - Assert.Null(entity.FindProperty(StoreKeyConvention.DefaultIdPropertyName)); + Assert.Null(entity.FindProperty(CosmosJsonIdConvention.DefaultIdPropertyName)); Assert.Empty(entity.GetKeys().Where(k => k != entity.FindPrimaryKey())); var idProperty = entity.GetDeclaredProperties() - .Single(p => p.GetJsonPropertyName() == StoreKeyConvention.IdPropertyJsonName); + .Single(p => p.GetJsonPropertyName() == CosmosJsonIdConvention.IdPropertyJsonName); Assert.Single(idProperty.GetContainingKeys()); Assert.Null(idProperty.GetValueGeneratorFactory()); } @@ -300,7 +268,9 @@ public virtual void No_alternate_key_is_created_if_primary_key_contains_id() { var modelBuilder = CreateModelBuilder(); - modelBuilder.Entity().HasKey(StoreKeyConvention.DefaultIdPropertyName); + modelBuilder.Entity().HasAnnotation(CosmosAnnotationNames.AlwaysCreateShadowIdProperty, true); + modelBuilder.Entity().HasKey(CosmosJsonIdConvention.DefaultIdPropertyName); + modelBuilder.Entity() .Ignore(b => b.Details) .Ignore(b => b.Orders); @@ -310,13 +280,9 @@ public virtual void No_alternate_key_is_created_if_primary_key_contains_id() var entity = model.FindEntityType(typeof(Customer))!; Assert.Equal( - new[] { StoreKeyConvention.DefaultIdPropertyName }, + new[] { CosmosJsonIdConvention.DefaultIdPropertyName }, entity.FindPrimaryKey()!.Properties.Select(p => p.Name)); Assert.Empty(entity.GetKeys().Where(k => k != entity.FindPrimaryKey())); - - var idProperty = entity.FindProperty(StoreKeyConvention.DefaultIdPropertyName)!; - Assert.Single(idProperty.GetContainingKeys()); - Assert.Null(idProperty.GetValueGeneratorFactory()); } [ConditionalFact] @@ -324,7 +290,9 @@ public virtual void No_alternate_key_is_created_if_primary_key_contains_id_and_p { var modelBuilder = CreateModelBuilder(); - modelBuilder.Entity().HasKey(nameof(Customer.AlternateKey), StoreKeyConvention.DefaultIdPropertyName); + modelBuilder.Entity().HasAnnotation(CosmosAnnotationNames.AlwaysCreateShadowIdProperty, true); + modelBuilder.Entity().HasKey(nameof(Customer.AlternateKey), CosmosJsonIdConvention.DefaultIdPropertyName); + modelBuilder.Entity() .Ignore(b => b.Details) .Ignore(b => b.Orders) @@ -336,7 +304,7 @@ public virtual void No_alternate_key_is_created_if_primary_key_contains_id_and_p var entity = model.FindEntityType(typeof(Customer))!; Assert.Equal( - new[] { nameof(Customer.AlternateKey), StoreKeyConvention.DefaultIdPropertyName }, + new[] { nameof(Customer.AlternateKey), CosmosJsonIdConvention.DefaultIdPropertyName }, entity.FindPrimaryKey()!.Properties.Select(p => p.Name)); Assert.Empty(entity.GetKeys().Where(k => k != entity.FindPrimaryKey())); } @@ -346,11 +314,14 @@ public virtual void No_alternate_key_is_created_if_primary_key_contains_id_and_h { var modelBuilder = CreateModelBuilder(); + modelBuilder.Entity().HasAnnotation(CosmosAnnotationNames.AlwaysCreateShadowIdProperty, true); + modelBuilder.Entity().HasKey( nameof(Customer.AlternateKey), nameof(Customer.Name), nameof(Customer.Title), - StoreKeyConvention.DefaultIdPropertyName); + CosmosJsonIdConvention.DefaultIdPropertyName); + modelBuilder.Entity() .Ignore(b => b.Details) .Ignore(b => b.Orders) @@ -377,7 +348,7 @@ public virtual void No_alternate_key_is_created_if_primary_key_contains_id_and_h nameof(Customer.AlternateKey), nameof(Customer.Name), nameof(Customer.Title), - StoreKeyConvention.DefaultIdPropertyName + CosmosJsonIdConvention.DefaultIdPropertyName }, entity.FindPrimaryKey()!.Properties.Select(p => p.Name)); Assert.Empty(entity.GetKeys().Where(k => k != entity.FindPrimaryKey())); @@ -388,11 +359,14 @@ public virtual void No_alternate_key_is_created_if_primary_key_contains_id_and_h { var modelBuilder = CreateModelBuilder(); + modelBuilder.Entity().HasAnnotation(CosmosAnnotationNames.AlwaysCreateShadowIdProperty, true); + modelBuilder.Entity().HasKey( nameof(Customer.Title), nameof(Customer.Name), nameof(Customer.AlternateKey), - StoreKeyConvention.DefaultIdPropertyName); + CosmosJsonIdConvention.DefaultIdPropertyName); + modelBuilder.Entity() .Ignore(b => b.Details) .Ignore(b => b.Orders) @@ -419,7 +393,7 @@ public virtual void No_alternate_key_is_created_if_primary_key_contains_id_and_h nameof(Customer.Title), nameof(Customer.Name), nameof(Customer.AlternateKey), - StoreKeyConvention.DefaultIdPropertyName + CosmosJsonIdConvention.DefaultIdPropertyName }, entity.FindPrimaryKey()!.Properties.Select(p => p.Name)); Assert.Empty(entity.GetKeys().Where(k => k != entity.FindPrimaryKey())); @@ -430,10 +404,12 @@ public virtual void Hierarchical_partition_key_is_added_to_the_alternate_key_if_ { var modelBuilder = CreateModelBuilder(); + modelBuilder.Entity().HasAnnotation(CosmosAnnotationNames.AlwaysCreateShadowIdProperty, true); + modelBuilder.Entity().HasKey( nameof(Customer.Title), nameof(Customer.AlternateKey), - StoreKeyConvention.DefaultIdPropertyName); + CosmosJsonIdConvention.DefaultIdPropertyName); modelBuilder.Entity() .Ignore(b => b.Details) @@ -460,19 +436,9 @@ public virtual void Hierarchical_partition_key_is_added_to_the_alternate_key_if_ { nameof(Customer.Title), nameof(Customer.AlternateKey), - StoreKeyConvention.DefaultIdPropertyName + CosmosJsonIdConvention.DefaultIdPropertyName }, entity.FindPrimaryKey()!.Properties.Select(p => p.Name)); - - Assert.Equal( - new[] - { - StoreKeyConvention.DefaultIdPropertyName, - nameof(Customer.Title), - nameof(Customer.AlternateKey), - nameof(Customer.Name) - }, - entity.GetKeys().First(k => k != entity.FindPrimaryKey()).Properties.Select(p => p.Name)); } [ConditionalFact] @@ -773,10 +739,6 @@ public virtual void Can_use_shared_type_as_join_entity_with_hierarchical_partiti Assert.Equal( new[] { "DependentId", "PrincipalId", "PartitionId1", "PartitionId2", "PartitionId3" }, joinType.FindPrimaryKey()!.Properties.Select(p => p.Name)); - - Assert.Equal( - new[] { "__id", "PartitionId1", "PartitionId2", "PartitionId3" }, - joinType.GetKeys().Single(k => k != joinType.FindPrimaryKey()).Properties.Select(p => p.Name)); } [ConditionalFact] @@ -866,11 +828,6 @@ public virtual void Can_use_implicit_join_entity_with_hierarchical_partition_key new[] { "Id", "Id1", "PartitionId1", "PartitionId2", "PartitionId3" }, joinType.FindPrimaryKey()!.Properties.Select(p => p.Name)); - Assert.Equal( - new[] { "__id", "PartitionId1", "PartitionId2", "PartitionId3" }, - joinType.GetKeys().Single(k => k != joinType.FindPrimaryKey()).Properties.Select(p => p.Name)); - - Assert.Equal(2, joinType.GetForeignKeys().Count()); Assert.Equal(5, joinType.FindPrimaryKey()!.Properties.Count); Assert.Equal(8, joinType.GetProperties().Count()); diff --git a/test/EFCore.Cosmos.FunctionalTests/Northwind.json b/test/EFCore.Cosmos.FunctionalTests/Northwind.json index ce11732f3d7..3abcbb5b8bb 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Northwind.json +++ b/test/EFCore.Cosmos.FunctionalTests/Northwind.json @@ -1,76 +1,8 @@ [ - - { - "Name": "Category", - "Data": [ - { - "id": "1", - "CategoryID": 1, - "CategoryName": "Beverages", - "Description": "Soft drinks, coffees, teas, beers, and ales", - "Picture": "0x151C2F00020000000D000E0014002100FFFFFFFF4269746D617020496D616765005061696E742E5069637475726500010500000200000007000000504272757368000000000000000000A0290000424D98290000000000005600000028000000AC00000078000000010004000000000000000000880B0000880B00000800000008000000FFFFFF0000FFFF00FF00FF000000FF00FFFF000000FF0000FF00000000000000000010000000001000000001001000000000000001010100010000100100000001010001000000100100000100000010101000100000100010000000000000000000001000000001000000000000001000000000000000000000001001001000000000000000000001001001000012507070100000001000000001000100100000010000001000000000100100100000001001010101010000000000000000000001001000100000101010101000000000000000000000000000000000000101020525363777777777777753530100101000100000000001010001001000100100100000000000100000000000000000100010001001010001000000010010000000000000100000000000000000000000000000001014343577777777777777777777777777770100120001010100102000000000000000000000000100100010010000000000100010000000000000000010010000001001001010100000000000000000000000000000001021617777777775757535353525777777777777770150120000100010101000000000000000001000000000000001001001000000000010010000010010010000101001001000000100000001000000000000000000000001417777737617376377775767771707752777777776340161210300000000010000000000010000000000000000000000000000000000000000100000000000100000000000010000100000000000000000000000000100503677577571705014000000101070717775777777775334101400010101010001010010101000000000000000000000000000001000000000000000000000000000000001010001000001000000000000000000000000010357353000000000000000000000000000171777777777470612101000000001000001000000010000000000000000000000000000000100010703010101210000000000000000000000000000000000000000000000101034350000000010653435777570477474700000107757777171000000101001000101000101010000100000000000000000001041477110131035750020040477301000100000000000000000000000000000000000000000010004014176577707000067777777776560404007371734361701400001241000001000000001000020400000200000101747767777000101073777577777775372100000000100000000000000100100000000010000010000037676476700004000577470416717477421405000434140343000565120510100301014002107171370701437777777775777777112103177777777777705757771010000000100000000000000010000100000101000470440440671007477776777777614060600742524001777777747646776752060250003021716737777777777777774747727574777001016777777777767173317703000101010000000010000000001000000000000420460200077427477767777777775677777746474656606767777665746776757151253507166737777733746777577777777572776771100517777777767776015713141030020001000000001001000000000010100067440044047761477767776706767777674765673470657505767375664746757777271252167717733771737776777677567476577577121103775777777776717027753121010101000010000000000100001010000010767060004776747776776777756776777777777042477676067777467474747676777565256531311771177376477777576757777747710110701777777767777401717340000000000100001000000000001000000101004776540666050777677657777677470774777776747664607777376747476777777677717173735377717737747777777777774774770011271077777767777763171735210121010100000000000000000000010000000300406767757676775077006767477774774777774747770476777656706746777657777777777777777777737667777476574774777771001031777777776767741371771000000000010000000000000000000000101005707442567656176006767004770476707700767770000477747734656446745677676777777777777777777375667777777777777777773100010777777777777771753521010101010000000000100010000000010007777712152503004670077774767427047247776577564700076737747670474277777777777777777367777777765777777777777434777750757775377767676770172773100000000001000000000000001000101007170701614204046007746040676167470774167743656777740077776067407465677677777777777757717777737476775716161243410303077777777577775210000011350001001001000000101000100000100002100171525675070074340670005004076700706570757777767770077744746466567777677777777777777777773776777610000000137775350317777773777737750701000101021001000100000000000010100010010300067777761650604065047604760746404776406705656776770077764750474747677777777777777777773733747777773011735777777777777777757777777777767412041001001000001000001000000010001000577744140000607406706767676776777776477756767777447700774076646764777567777777777777737373737764677747753527777776777777777776365735353513010300120301010000000000000000001000107000210006147767674646040404040066667767677775476777046644644044456776767777777777733737373776777776774244777377717712777165357577534242040010010010000010001000000100010000100300050000146664000000101030734352101100065677767077770047604774377676777767777777777373737333756477657075377100770770177776525271673001012101210301001030000000100100000001000005000060046160004000125343510110101000000000007740000047744733737377757677777777777373737377737656757777777373101676770777717775671773001010300000021021010000000000000100000000100077400000414021414000000000000000000000000000300000777777773737377677677777777777373737333735677677777377710177777717774705271767340300000010101000100000100000100100000001014005660000000737560600000000000000000000000000004730777773733373737777747677777777737337353761666777777737737017771677077353777574735310012101000000010010100000100000000010004300065400000000400141254140404000000000000000000037737776773777373733777677777777777677646746565756747777773773017017710765654352735770017010303031010010000000100001001010030704000660000000000000040000000000000000000000000007777514673373373737777777476777777777474644764666776777777772711031076117307374357477373010341050043030012100100010100100012500000047000000000046742000000000000000000000000077776677777377377373733737767777777777767645676507574777657610057121101731611574777637735105270125213010050210100001070210301650000000640000000006776406776464000040641434177777767667614737337337373777777767677777776564767474664667477761775271112116101002331211101052721016120140161034106010173075617770000570047400047400446000000467770504777767173573756767776767737737773737377776777777777776564746765477576777176700774656474731010011000001250165214716170121012011070777173777400063770040000760467600000000740760600777067777777676767676767337333373737377747677777777776767747424676747677157701677677676131331213131301371317310312161525053073077777777700047577700000006006760000640400006474046740777777777676767676737737777373777777767777777777674746767467477777743670175305325352527135335353170143414371617130131211777177777777001737770006760476677047064466400047640077747777777767676767673773373333737373776746777777765467674704747674765375610731773573752534737417017035303130101010030001427777777737770047777770047460704644064400004640067004767077777777767676767673377377773737777776777777777766565665670767767775077007563153347370731013213617034343434307031417121177773777777740257737700027447000064000000000640064006760777777776767767767773373333373737777476777777777746765674464747767763477027172753717175777757757357171717171717433616163777777735737400737773400460660046000000000004000600676747777777776766766767377377777373737777747677777776756567467746765777117100537153353773777777777777777777777777737757737573777773773772047777350000474044600440000000000040047774007777700667677677633333333333737777766767777777777667476564657476760600007353375373177777777777777777777777777777737777377733753777740007177770000664024640640000000000004646700477777007767667666777777777773737777777777777776777446467565676777535373525317137177177777777777777777777777777777775377773753771737700076737350000000474664665646644400400464000077700067677677773333333333373737776676777777777767777766767765677771713175217037173777777777777777777777777775375377173753777377773700057777004007477667764766767667467600000004770000767667666677777777777337777775677777771777772604000404067761171613131535353717777777777777777777737753777777777753773717735374700000500670446677777776777776777776561004661000006767767777333131101100777777666567777567704040505140777716536353147173135371777777777777777777577577777777777777777353753777371700000001776040404040404606076767776170000470000071101100100000000000110157177776777776470124100002530004777111301313017535371777777777771771737377773777377753773717353252165376164464265700400000000000004040040076774000440000777500750000000000000000017347766777746564100000000400300652513530753303170737777775777777777777737777777773777753757035353134317137313533000046440000004400000000053770000000000077343100000000000000000004135777775676176000700000004044213052153115353371357777377737737775777777573757777777353213503161617163521657257000006700060042400000005273710000000000007577000000000000000000531117777665447405244000000040031501313030721353537737775777577753737717737777777777777035343343131303103171317337130100000567000200000031756000000000000000077771012100101101131117133375466747465707047000071502161011531534353517753773737353777737777777777737537713503353170717173561343105307030525370047014161717433700000000000000000000101011770000006402737373767456467777777773065773510137343531317073737773775777773777577375735737577777343375377373673071316352731717173137000007737352713574000000000000000000000000464000000046733737373446647777777777740007373737110310343537171773565373537577177375737777777777773353737717175357727753717163737357770000071735371677700000000000000000000000000460004004676173737374745777777777777004631713112031213131317337177737777777377777777777777777777775377737777377371717353773571747737377617771677773570000000000000000000000000400400000000406337333464673777777777774007733373311001013135317177737775377377777777777777777777777737777573777377777736771773773716717535343373525773700000000000000000000000000000000000000037337374433373777777777700007740010313133173137337357753777777777777777777777777777777737737775375737373717367171653735727367374753737174000000000000000000004600000000000000000373733643773373777777777404073000000000012137331737377777777777777777777777777777777777577773737773757575735317273353531757535737377576300000000000000000000424400000004000040007373375733337333377777770000700000000000000000070477777777777777777777777777777777777737773757753757373737777775357273673373773535737357000000000000000000004406000000000404004037337333773737737377777700400000000000004006404043777777773757777777777777777777777777773773737773777777717371737357171752573473721777340000000000000000000006446400000000004004337337333373337337337777100004705340100016503777747717717757777777777777777777777777773757757773577173577775777577377773777373757777177700000000000660000640047674000000004000003737337373377337373737774040077760004000000044004737777777777777777777777777777777777773773773577377777377377377377537177535757373537710000000000004040004640604600000000000400073733737337333737373777700000047477420000000000435777777777777777777777777777777777777757777777777777777777777777777777737737377577777000000000004600000460064600000004000000000373373337337373737373777600000000000550043617777777777777777777777777777777777777777773777777773777777777777777777777777777777737737777000000000000000000000406400000004040000003373373737337373737373770040000000002777357777777777777777777777777777777777777775777777777773777573717775777777577377777777777777757340400000000000000040004064000000000000000073373373337333373737377750000000000057777777777777777777777777777777177775737577737777777735777773777773773775377377735735735375737737000000000000000044600406060000000000000046337337337373777373733777007460000000377777777777777777777777777777777737737777377777377777737371775353753753777777777777777777737717750000000000000000000000444404400400000000063733737337333337373377774067400000000777777777777777777777777375773777757777177177377735777777777377777777777777777777777777777777777704000000000000000000006000666066000000004433733337337377333377777700676004004407777777777777777777777777777757357375377777775777737777777777777777777777777777777777777777777772010000000000000000000040004404440000000000373737337337337377777777704600674660077777777777777777777777777737777777777773773773777777777777777377377777737777753777777777777777750040000000000000000000000460460000000000463733733733733737777777770047464067000777777777777777777777777777777777777777777777777777771737177777757377377753777777777737757773737000000000000000000000644640000460000000000073373733733733777777773750660760400017777777777777777777777777777777777777777777777777777777777373773777357173775377735737777377757777240000000000000000000606400000000000000000373373773733777777777737604746400406057777777777777777777777777777777777777777775775771733735377757177175737753737537777757777777777750100000000000000000046540000000000000000007337333333777777777771771066067674767677777777777777777777777777777777377777777377737777775737573737736373717375773777373737377777371200400000000000000000046000000000000000000073737373777777777777737700656476464617777777777777777777777777775757777777575757735773735371737357737575357635733577377577777773777775000040000000000000440646000040000000000000733733377777777777777137106606476400077777777777777775777757357777777757577377375777775737777577735737377371735773757073737175777777370000000000000000046764656546400000000000007733737777537777777777774474407467005077777777777775777757377735737717737377777737777371773737373773577535373437073737757577737353777700500000000000004676474266640000000000000047333777074747777777777776567642766027777757537775777371735777777577777777577777775377777777577577777737777577737757757373737777775777000000400000000067407604040000000000000000077777103716173777777737676665646470577757377775777375777777177377777777777357357777773737777777371735737773735753737377777773577377370004000000000000666424604040000000000000000777777007677477777777767676767474003577777777773777777777777777773773573777377773777777577773777777777771775773777757353753577357777770010000000000040406404000244000000000000000777370141477567777777762476767660067777777773777777737773777753777777777777777777777777773777777777375367377375357367767767737673477140240000000000000446400004660000040000000007737520077772757777770040047667767177777757777777777777577737777757777717753717717777777757753535357777775775777777535753735757177357005004000000000000000040400476440464000000007773401616575777777006440004764256777377375775375735737777777737737737773777777777773777777777777771771777777777777773775777377577773000000040000000000400000000000067400000000077771425777367777700400060006765377777377777377737777777735735777777777777777777777757777777777777777777777777777777777777377377353770070040000000000000400000404000040000000000077770525765777777004004040440065773775717377777777377777777777777777777777777777777777777777777777777773737371775377773775657527777500004000000000000000000442424400064000000000777724077576777700400600007000373757373775775375375737777777777777777777777777777777777777737777377373577575777777573575373733771737300700004000000000000004646440000672440000000777507567657775000444040644047777377777773777777777757777777777777777777777777777777757377771777375773737373737373773377753575377577400004000000000000000000400000040440640000004777407757777700404246044604375777757737777777777777777777773777777777777777777777777377775773575737175717175717571757253372734372773007000040000000000000000000004600464000000007772525677777004704064240124373777377577777777777777773773777777573577777777777757377737373777373777737367363727373735356171737177175000400000400000000000000004600000400000000047710477777700676006564640577777777777777777777737773777777577177777777777777777377735775775377757173717535357174352537737373717717730070040000000000000000000040046000000000000077777711357047600446500072777777777737777777377777777573573777777777777777777777737777377377177377757773777377737777343574356773737710060040400400000000000000000400000000000000771571715356770446002470757775773777777377757735735773777777777777777777777777735777377777777777777737573577177535357773777371747527710160000000040000000000000006000000000000007771353777767600056440042735373775377375773777777777777777777777777777777777777777777777777777757377773777377737777735777537577373717700104004000000000000000000440000000000000077171357777674006064214357577775737757777777777777777777777777777777777777777777377777777777777777777777777777777737777373777737577777300424000400000000000000000000000000000000777174777756765404051425373735737777777777777777777777777777777777777777777777777777777777777377777577777777777777777375777737777353777100100400040400000000000000000000000000007717137577764767404061777777777777737737777777777777777377777777737537777777777777777577777777773773777737775377177577737353753737770737100400400000000000000000000000000000000077717177777467760030065377577777777777777777777777377777777777777777777777777777777373735371777775777177753777777737717757775375753573536100050040404040000000000000000000000000771717177720767000043737737737737757737773773777777777777777777777777777777777777577777777777737773777777777777777777773773737737377357753000004200000004040000000000000000000047773537777504004104375777573757777371777777777773777777777777777777777777777777373777777777777777777777777777777777777777757777777377373777200504040404000000400000000000000000077153577770000016075375373777737177777717717777777777777777777777777777777777777777777777777777777777777777777777777777777375373577177573535300100040104004000040400040040004000177353577770070007277377777537777753757777777777777777777777777777777777777777777777777777777757777777773777577777775377537727576377717252734120050040400404040000040000000400007735353777005006535357777737771773777377777777777777777777777777777777777777777777775737777377777717377777777773777777777753753735752771775173500007000040000004004000400400000477717177775004353777737377773777777777777777777777777777777777777777777777777777773737757377173717777773577737777773777773773777773771773136343700000561040405004000400400040400775317777700367771737577537757777777777777777777777777377777777777777777777777775757717777777777737177577377777775777773777353717773771776535353716000047000404004000500050010001735717777761717777573777777777777777777777777777757375777777777777777777777773737737773753777177577737777537537737777757777777771757372537737271717100005252004004040604004040077531717777177777777777777737777777775777777777777777777777777777777777777777757717753757775377737737773777777777777777777177173777737753770775363774320000416524100000400400004773717777777777737777777777777777377377777777777777777777777777777777777777777737773777773777777777577757377377777777377377777753737753771775375757377577600000106141410143405007757537777777777777377737777773777777777777777777777777777777777777777777777777753777737777777777777737777777777777777777777377777573777777377373775373735373000000000400010000077377717777737777757757571777777777777777777777777777777777777777777777777737773777777777777777777777777777777777777777777777777777777737775777777377775777777777161612161637777777101777777771771773777777777777777777777777777777777777777777177577377577757777777777777777777777777777777777737777777777777737737775773737717717771737737537777777777777777775717177777771777777777377773777777777777777777777777777777777777777777777777777777777777777777377377777377777777777377577177537777777373757737737735377735737737377737775773777377717177777777737777777777777777777377777777777777777777777777777777777777777777777357537537777577773775753573577577537377737753757357757357571753777171735735775357537737571777771717577777777777375777375735377377775377777777777777777777777777777777777777777777737777771773753757377377777737777777777773777377737737737377375377777737573537737753773777777777177777777775775737757737777777757377777777777777777777777777777777777777777357777777777777777777777777777777773777777777777777777777777777777777537717773777777777777577777717711737777173737377777377777777177377777777777777777777777777777777777777777777737377777777777777777777777773777777777737775777777777757777775373737777773777377377537737777777710101417777757757377777771735377777777777777777777777777777777777777777777777777777777377777777377377777777777775775775775737777717717371735377575735373757175365737777773737777777773617377373775737773777777777777777777777777777777777777777777777777777777377757177573737777577773575373573737737777773773737777777777777737373777175337637173573537777577717777753775777775377777777777777777777777777777777777777777777777777777777777777773737773777573573753777737777777777773773777577577737353717353577175217437753577377377771737373773777375377375377777777777777777777777777777777777777777777777777777777777777757153471773737373773771737771737377777777777773777737577777777777377737733717373717177737777777577777375377777777777777777777777777777777777777777777777777777777777777777777773737773771757577573577377717777575717377777777777377773717353717357175717577717753777175773773537777777777777777777777777777777777777777777777777777777777777777777777777777777753473535377373717353717171735373737777777777777777737777777777777737737737353735371737737777377777777777777777777777777777777777777777777777777777777777777777777777777777777777773777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777773535000000000000000000000105000000000000C7AD05FE" - }, - { - "id": "2", - "CategoryID": 2, - "CategoryName": "Condiments", - "Description": "Sweet and savory sauces, relishes, spreads, and seasonings", - "Picture": "0x151C2F00020000000D000E0014002100FFFFFFFF4269746D617020496D616765005061696E742E5069637475726500010500000200000007000000504272757368000000000000000000A0290000424D98290000000000005600000028000000AC00000078000000010004000000000000000000880B0000880B00000800000008000000FFFFFF0000FFFF00FF00FF000000FF00FFFF000000FF0000FF00000000000000777777777737125353313731773543110105302502105313321714317343717135371373147317317171717121135301610131217777777770146765074747776567616774776565774040371737031611737710110100007777777777717435357353531713343030301103112161705353317353343717135371370317717737371734125031131352171777777714066544724767776774747657700577764774340735757100371507530210777777777777777731737317353731704311151303112110431731305317314171731717171354731713535373107131703011317177777770664576076567476404776147676777674174074740573312411002173611137777777777777353167171735337173531163125351615307173171737171707373173733537023177373737351611010113521737777775245006047474747407777777767657775747477416560075141200115351103077777777777777377143161735717353463107113131303343353171317373107177317173171477135353717370737312503173577777344760547061604760777777777777764677776007470774033001010035212100777777777777777173563535335371731053130707071351165343171701773417357717177130177173717717134101713353173777747640076047447000777777777777777775667570467760774040301010101053107777777777777773712531335337171735301531313134334135353361371350735331737137707137353731737433731717377777776040000407647604777777777777777777460547743565054776011001031213010077777777777777353561737534717337161352171712717103737335137137061373573171711073531737171710351171735373777704740460464746777777777777777777777040667746776007751300530101301300777777777777777373071713713717135241311030711317605117533517171075353357373734173173537373735373773777777770460464740406757777777777777777771777640577740457777000131035310701007777173777777775353431613717357131630731713735311637317173737171235353353535725377777777777777777773737777567404706425046777777777777777757777775246577777767711350131030311300177777357777777737350771731171337510531071351613735534317131717305737357377373077777777777777777777777777776540060405646777777777777374777377777774767777747771076035031110121000173735777777773535307131717373513243357317073171163353712571735073171733535735777777777777777777777777777704600564064077577777777777737777777777424577756771147741121161037100017357733577777773731603521725153251071335213317077071335373371732177373573737777777777777777737737777777776460464604046473777777777777777777737777567776657167647421121121103001035775737377777571711613531337353371435135351713131471731171735716171773753777777777737777777773777777777774740405674747777777777777777777377737176567757370470067070121121100010733531717577777371734173535353353107127713631735370371737173537107377373777777777773777377377171377777777444006640464677777777777777777777777777756777774747047741137112116100305737161373777737173107313531735352471713171173537017173717353731637535777777777777777737737737337177777770760650406047777777777777777077777373437777770567674776012101611210010131717135357777713253425343525353131031717373537171617171371717750537737777777777773737737733713537777777744404656440467777777777777777777377771577774764044774470717131071301210161335253077777757131035313137377534721717173537371637171733737343537777777777777777737737753713137377777764604646560457777777777777773777373001777574777764477611301121010001017135131314377773131716317353135313001717353353717165317371713573173777777777777777737573533373353717777777465404006400767777777777777377735000137776067664707640341216131300300035253521707577135271653531161773716173371375335373531717173757316773777777777777773773737377171313773777770460000440066757777777777777773700010577756764100674031311310100010103131313521073777731131052773171371310715377135737171773353353337717777777777777777773773737333131353353777776764007640456006777777777737371000013576644566565671341210131300010103521703170073735371730311173171371352735377335373725357353757177177777777777777777773737377173317173773777344564046466404444056477777537301000373405606746764011331352171001201013523152107177735303504373171357017005335217135307107317371337377777777777777777773377373137317133353353777706400004400676000640677471001000171464767444564031301052117100301001703117211617173531713035316127331710737171717731734071737171777737777777777777777777737377735333531737777717746654047046440044700465700016113000564440676653130171311303001010303152311340217173613530435313513531210717313613535312131713771777577777777777777777373735333337113713131377777344660240404740064000007003012446064000065641301430121217100303010117214341305030713521770035312153431340315251703537140713531737773573777777777777737373737171337311317171771777714540440064600464074764547407644764474661061711131171213001100121311331330433171353713107121713013170071631331353113013073173537752777777777777777773737337373131371731317707377776646600000000400464006460040000476461100121212163011710430103104341170510350307131714035353017317034353153417125240735317537717377373777777777737173537713137113133135371377737771404047400000000440040000046564612110016111211111303013012110331333130343135134352334031251210717107353213717131300131733737777577777777777777737173713737133713717131774353737777776646444600006000046442564670513430031611030301700012112131170552530043032531351307171335313137007153513035211071631535737716173777777777777737373733733531313133713707375737737757474604640746406546442411030301104111210110303104012112533130313134315113171371407135031707110712313253121520031173733537777777777777777737737373717373313533531177165373577777737777574746445652413513125110130012121121210110013152113152531725005303616343160335303521310243535161134112143537371777777173777777777777731737737313171731353137350737173717352573717737353737171343070110212100210130101013020210311612313171134121711311353134135311353531061303116113010013535373537370777777777777773777371737373331371335117340537153717352573737517340707317351130211011201712103103011001312531711725371124301253717135035215271212170171703130313030703535373777757377777777777773735733717171311371333173163537353707142570532717161352513307111211211401113502101211041713030371135363105331301212530431731135353107031100110411000713737177377377777777777773773733771733317131335353170143417217317073173535317071353250303071021120120301311303124330171711371133150435053537171703713107031316053160317031301071371717717734777777777777777377377337371331351733137124331335351700717053530700714351131501103112107111131030105001153012125363757312131303113121051707131716110210110101100300317137373737713777777777777777777777777377373331537174101170535321705713725353507331216121312110710003070125103130061213110133151317052521716161370213134310313514310303121310140307171717735653777777777777777777775341307071331313130060130305313003411310303014105310101012101214311130121103130131412130757377735213171213135105350311251212021030110101030035317337735731777777777777777777757171310101373535317100112535321610613161035110031310130103010131003030013112105007031301011317731730717031711612012135035335310503110212130104713535713737167377777777777777777737310010135153313530003011010511001212117121243001030012101103010051013100301130011030130077737771750731731631350717133031035302110211010121303533733753773177777777777777777777510100000017335331711043030312121041153010101001121031010102103010303100311012100121010010731737773731731711531300316153171307116111035031101433537533771774377777777777777753012110111000015617137200103110311121203103031210021110010030101010000103110121013000130131017771777771471352373053525313317037130612102103121312573713753777377773777777777735035355371731510001717701100314311430100101311011021102031211011010130010100312112100030012003037777737377335375317330131351631713150110311301535017353777377377177777777777773513513130111053351101771130070131303131053170161307050311101030102121000121211010010101013101101777777777716537131731570716331531352352311210713013343773777375377577777777777713171310135371315373103520010113161311032072113131110311212121012110110031101121213030003100100307737777773717137171731310315331707353014301311253353573573717377737377377777773177125353131735335357103131202521135271510113412163105211111113110121210003100111011100101301010177777377775637717331737071735213317317431734121314317373777777777757777777777317313113107173777531737150101013173031133043713353110631777377777373111001310312121030012121000210777777773733171316171611073135351731703101013171733525777777652104277777377731713535341717353537357571310100010351353250310351317377577525010505357730301031010112100210100101037377777777757335735331734353717371371707131343121753177050001040014077777737713713011331357777775337175000100010370351314771377775713400100000000000417531013130313051130100010077777777777345331735353125353310375313430521353531377770000400140014057777777351717351071353771775357331001111111353353211377777434001000000000000000003531051014110030100100210777777737735335731735217103341737137353413110313535377104700106756207747773537371710325175375777317735110110001107317351677771611013400100000000000000000703121313003012100010017777777777773433173131710735333113710305303431073737770777406456065570014777753103535113137773711771101110010100171771737777171607000010001000000000000000130110300611101010011077737777773717717353731730537516371737125313173171777575646747676566756704773757110717757777773773130000111001110771377777516101105010000000000000000000000532131101721000012000777777773777717317353431343133317171717035307173773777775747400456556756701773737711010343571513571110010010001001777777777357343034341010000050000000000000150121001121100010107777777777771635371353735343535353371335431713535377777770006047606677674073777777771711113173753000001000010100177777777535305141000000401070000000000000000313500310100100010077777777777373537037331530173537317137523173773737777777747650460447465677777777777777777777777300001100000010110777777573530530374175353107057310000000000001710071030010101010777777777377753713713573716137131733533507171353777777777774640540761465477777777777777777777575000000000000000007777777753577575031035257053007700000000000003100121121000300007777375777737343711713131716137171753533437173773777777576700766704465625777777777777777777777737000000000000000077777777773537077577561763571001000000000000053010121001000110077777737777773531733536173253717373373711717353777777777755046564476767477777777777777777777777111300000110101000777777753577753712707100142070070000000010010300713110100010000375771777373534371353317315171731717171707353777377777774766474677644747777757777777777777777717370100013000000007777777777777350574100005251007100000000000000611210030001000017737371777773716135271711732533537373737307377177777777777752424464765677777777777777777777777777141010011100000077777777777770712170710301701617000000000130010531031010101001071771735717777136131173731716173531717135353737377777777747654476744644777777777777777777777777713001011010100100777777777777570570110414161600071000000004170003071011000100000371737137773733417373171371217137373737737771777777777777777467444604677777777777777777777777771700000001010010017777777577757353052431201001015340000000012100171121200100101011735717773375353735317137131613717171731717377377777777777600742076565677777777777777777777777737100010110100000077777777777305705251525034000702100000000005037103101100010000037133710775737352135237317350713737371773777377777777777765046546046467777777675777777777777773710113110110110001777777777775730701006125010100050000000010030013103000010001010717717373737735357135117717334353537373773577377777777777567746644650477577775777777777777777750131100000100100077777777771775711753010530400001010000000010010703113100010000003710735357353737037333713317137373757377173737377777773776564745204646757774777777777777777773313010010101110007777777777577771650341252051012104200000000007001352100101000101017373171737373531617171371713435317337537357777777377377756470064404657777777776567777777777751111101000110011377777777777577161035214105200040101000000000101031013010001010000735377335773773535373173173353737737737737373737377375377777447476704677777775777777777777771371301001001011017777777777537577134104034001001000000000000000700033101000100001003171357331771737160152173171351733717373717177775371737776767460446044777777467774777777777771311111001101017777777777777577756134311012161401000100000000010101012121010000000077337335737377373137335353737363573735373737735337173177756104700046567777777757477777777777117131000100113777777777777776717351410401450101000000000000000016017110100010000010357371773177735371613533371353537373737717353173713717775654065400004677777774707757777777735311010112113777777777777777535757161252161210000010001000000010010310210001001010007335377377353773530713535337337173537373735377311713737765670000004004777765656577777777777531311010111777777777777777777536352141010014340100000000000000010000311010100000001071775335377373737170733735717537373717373735317373717775725650000474046777577777677777777773711311313777777777777777777777575757161050000100000000000000000001001210000100000000377335737737777737313571733733717373735353737731353733770567000007400077777677777577777777735311177777777777777777777777573537010116310100000000000000000000000131010010000010105335173353777371353053331353171735373737373713177737777770016140740004777757777747777777777531377777777777777777777777757347753777717400000000000000000000000010103001000001000035736317357357377317271737373735337171737353777333737377716140141003473777776757465777777773537777777777777777777777777775771757761601000000000000000000000000003100000001001010173317717377377373711373535353734737371717371377777777777502112007047377777756777777777777777777777777777777777777777777771777771501000100000000000000000000000003103010001021016317431635377377173727173373371313531373737377737737777733714005001737377777777777777777777777777777777777777777777777775777776142140100000000000000000000000000110001000101012017713173537377737353117317137137343777373737737373773737373737137773777777777777777777777777777777777777777777777777777777775011210010000000000000000000000000001200100010301211431617353717737353353613733537335373337777733737373373737373737737373777777474240567777777777777737173302137777777777777753435341410001010000000000000000000000010010003010101003173617313737573753353435373135337773333777733737373373373373733737773777756101000507777777777777776140500001377777777777753525210250000000000000000000000000000210010010210303117351314771737373371321733173737733337377333373333373373373733773773777714000404070747777777777400000000000400257777777757170714141001000000000000000000000000001003001011010100617335733135377717137152357333773337333333373337373737377373777377377777435777707477175777777700000000000000005377577777716171430300100100000000000000000000000000010021201210311314121353737173737313253333733337333373373337333373377337373337737777710777775077574707777700000000000000011007377757753717071050140000000000000000000000000000001000101310310035737171253537177317353057733737333333333333337373373337373777737777777775475725777770477770000000000000000003005777677757717070102101000000000000000000000000000121010100310311121312135353343737733337373373333373333333737333337373737373373777777777773470052574177777700000000000000000010077575777771751016010000100000000000000000000000000100030310130307171353433035353773731717373333333337337333333373733373737377777777777777747125352757657770000000000000000001250577777753571252501410100000000000000000000000000110001011013010112130313117312777733323323332337333333333737373333737373737737777777777777140016050257407700050000000000000041003777777777357103000000000000000000000000000000002030003071301213353413437017717737373333333333333333333333333373733737373737737777777777777375017257400747100000000000000001000075777577575307505101010000000000000000000000000010101211035351010313703113733337337333333323333333733733733373333373737373737777777777777777477405670067777000000000000000000007743477777737530302500000100000000000000000000000130300313121213013431353673377373323333333333323333333333373333737373737377777777777777776747640424000474775200000000000000007575707705753553141410010100000000000010000000000013011035217131301703137331373333233333323333333333333333373373733737373737737777777777777756777004774770576705700000000000002177677057777777347130012000000000000003500000000000013125035217050131353137337333313333323333233333332337333333333733737373737737777777777464644640004047406700677505000107161756505777000575357316153050101000000000017100000000000707125131213130137333273313332333233333333332333733333373737373733733737737777777777656740000074067640000575767700416500416777777775777777717535214010000001000005370000000000424133530351302130137333323233333333333333333333233333333333333333773377373737777777757474000004656504704756524057470770071257777777777777571771341431001010000010117430000000007406753071034111013273331333323332333333233233333333733733733737373377337377777777774246740047000064704706760077077574774774577777777777777775347131020500010000035210100000000675740243103130303033323233331333333333233333333333333333333733337373337373737377776564404004064000474404004104747724740776776777777777777774735317435102100010015035700000000004642440043101010101331333323333323333233333333233332333333733373733373737373777777706400000670400000000070470477777577074757757777777777775675775701520510521001431500010000000700040056103121312103233333332333333213333323333323333333733337333737373737373777744470000004041640560046747477757556777417677707777777776567467171353413001006143043401000000074000004640210101001033323033333231333333233333333333333733373737373737337373773774676740460000640646406756777477776775774675447407776774052467747257253143525012107100000000000464270047040121303121333333323333323333333333332333333333373333333333337337373377640444004000004004000046777770707756767775677777657574256477567057357057177171410507110100000000054640676740101001003033333132333332332333033333323337333337373737373737373777774040000600004640000470047677434475034774434774750676705657740400645717377753430001214730000000000600004404042101301333323233333333333333333312333333333733733333733373373737376420000004006040420006406767767477042457707407047765774067764740064163717575251010000573500014425604450000046500210130333131323313233333333333333333373333733373733737337373777745400044004040000405447747747577774050604077447747465765044747604776445777775200010101350102467406470640000046041030113233733312333323323323323333233337333373333733737373373774664400000004000000460467767676776770675424770747725046565677654004476064065351777777777770005470474004000600470001012031323333333333333333333333333333333737337373373337377777000400000000000040000006767477676777765702576004765406770464004604700440000577777777777777750076000000000007407646001211733330332332313333333333323333333733333733377373737373744040000000000040647400477676765657656564047645076567656440756425674004704047777777777777777710400007647600540044650030123333333331333233233231233333337333373733737333373737777000040000000000040004000445740400676472470041674004740400042447560470424747677777777777777777760004047044064600000640171130337303233333333333333333333333733333733737373737737765400400000000400046004600064000400400540470047040076000470047646404004740004377777777777777777040077047707400740000740121333331373323333333333333233333333373733373337373733777046400040000000640040074006004367400407601647400764045607404650470576474040654777777777777777770404400746440044674046002117303137133133233231233233337373337333337337737373777704640000040004040000004400440674400046764064740040410065247000006746645647704427777777777777777700600047004704670400674013031377032323333333333333333233337333373733733373773737400000000000004040074567202400460000007400564706776656065646406004007247044046577777777777777777040460057706000400005674001137117313330333333333333333333333373333733737373377740400004400004000004464044047004747440046564006004454045640474654004744064760006777777777777777777400400674147700707604060307032313733333233233213233333373373337373373737377737740004000040000040400070004406640460707656475004006020064047441600474007476500077777777777777777740000000047464064074004400117313073333333333333333333373333337333337333737373770600460004604000007006464640045061046404650640560056440540064674070465647400406477777777777777774000420000760000434007060003313753533723331333333333323333337337373737373737777704700040640004000044050065000460460074004604006544640046700470640470744006647040047777777777777000400404007704000467444044013073312713330323323323323333373333333333337373737377466400404400654060006460460447474050060000460046064740004474400564464024045240640004777777656744000640074047777047446056700053531713733333333333333333333337373737373733737377774400000000047676404746540000746447465440047406704504004467404046746540470564004740046567765656424064040060777744040610674003312731353333333333333333333333333333333333737377777400004440000464640004044604464647676766746560404046000476776767677776004646400404656676646464644400400640404777600004400460011713000000000000000000000105000000000000E0AD05FE" - }, - { - "id": "3", - "CategoryID": 3, - "CategoryName": "Confections", - "Description": "Desserts, candies, and sweet breads", - "Picture": "0x151C2F00020000000D000E0014002100FFFFFFFF4269746D617020496D616765005061696E742E5069637475726500010500000200000007000000504272757368000000000000000000A0290000424D98290000000000005600000028000000AC00000078000000010004000000000000000000880B0000880B00000800000008000000FFFFFF0000FFFF00FF00FF000000FF00FFFF000000FF0000FF00000000000000113330735737777704000000000000006060000252000014131315311716037070021240161075371617637506357172512171357170173537160000025214002070000012436167777777173333737171773737377700001111131330131357737700000000000010000050040006331131313310705073430040000003070761617433514356537571773171771716167170604076776775677064253437177777737357531737373753537337113313111111113131235777000043712006767773677777711131531311777377077043125361707171177773563737373563777177371374735716771707717735637700016777476777737531333733537371373717531111313130131316131112163035371350007753477177311137133171331777777770734772516177777717777352575777357377717537533173777160277767777777043635673717737533337171353735737353773713111271131130317013111111131131670073677776771733113113135137777777771470777616777777777175377375377357177773573757073577775677777677770365635777677533753537337371737353377377313111123130131313103131313131711770477670777353533133531331177777777763777177717777777777735357377757777737777353353553737737777777777761771637535733533333135317373753371317371271131111313521313310112131171337003717377771313117113171131777777777177716777777777777777777735353773777777777775773365777777777777767160677747673173717117337335373777177775311123103121113130371131317113313143047765767171715331313133137777777777677777734377777777777437577777357777777777737357530735777777777776071777737317371733733531737177313733737131113313113303511130153311311317343077777773131331171353153137777777735377777777777777777777537737177777777777777777737777767777777777717061617717331337313173371737737373573773103111313103132130133071311311313000617277173171731331313111137777777777757175377777777777736527577173757775777775257537171777735361777253525616717373535333171371737717173753713313121011313113113153131131371310000604167113131171131713131177777775353737736535777173773753752767757377737737777736757777177777776165206353735331317337133335373753737373773111311131311301312130331303113131701070127013353133131713113113171773737773571753773527657765274371717737737777773773753637177777707177716535273533173731713717133717377317177373121131111121130313131031313313531600076507711317153131313113117777777717163763777767753717373136161634777577177757757777567075717776353613437473353131737313313353373731373735311131103111131111301731115313313131120012507317133317131713113137773577737753753435373777675756537535736173777737773773577377736777777677617437173337331737313353353753771335337131111110131303121731073131071313134107612771313535313531311313573757373535375377777567743527253473434357677537577375777735717771717171771707167317131733537317311331373337137131103331313113111113113312133131313503071650131313131531311313173757377757777737437773717377775367343717773537777375773737777777777777777167736535333373173731313133537311313313311111121353011303310335313111331312161677373135373133131135311777377777373717537717777777777725357343634777777777773757757777777777777777716573733171317171733313713317331331313331331130313311113311133173311531371753777717131171117173131311777777777757737717777777777777776347757737777777777777377377377777777777777773777173133333373531313313313331331311121773313311031341373053105313171773777771313537133713131311137777777777377777777777777777775357777775777777777777777777777777777777777777777773313713535373313313131331110103131137701710113113131317331333131337777177731731311311317171131177777777777777773717777777777377737373737777737777775777777777777777777777357777131331313331373131313113111010111773371600771213011305313171143171137777777131713131731313171131777777777777777777777777773577737777774770737777173737375777777777777777777775737331313313137353113103113331111117701677000071513131331353133131331177737753131313531371313131117777777773777777777353535777377771773773775737177777775377777777777777777777377735313313131313373113110111131113171607777000072111111134337113131133771777735317113371310117113177777777777777775377777773777535377357177377777777537777735777377777777777777777133313333131313131101011131113111677077700000000003373131013353533713777373131313135135313631317777777777777371737573773777373737717337317737537373773777773777753777777777777737331311113133133313111131353353137777343400000000000113113111312111717357713171313133131717531177777777777375377773771771717171713707531753573735371777373777173777773777777777713173133313113013313131113377377177701353700000000003113713121313131317371371311317173171317131377777737357377735371771373737371771333533723171735373777577777777773777777777777733133113111113101313131757173173343410111313410000041371353135313537375335131731713117135377177777377757377577173773777773535333171713531117373537173537373777737171737777777777313313113131111111311173337357131353131301111343035363131317133113317137133313113313313531631177377753777773313717353121013131717171312113331313312113777753737777777573777777771331333111000101111130311771733110111111110311317525753173113153035337713535317317315313171533157773773735375353717353113313131331310110110131311313101313773573737773771773777771133131311111131331131371373713131313013111311313737371173713131317137713131315317313531373513353577757771337317313133313121111313110110131111111111313033173753773777773577377733133133331331331331011171717311111111303111131353537737113312171313713713135333713713171173711313737331371731313313111111113030101210111110010101011111110313371353737753077777313113131333133131131313373775313011031113013131317777713371713131131311353733171371313107171131131135777137113111101011011011111311113100011110101000010111121131377777377307377131311331013113133713131117131111313503113317035303177353131713171131731311171137131353131213171153131137313313010101001011010101110101111000111010101010101101111317377357757077111131101013313713331133110171031131352115213131313131317131353031311353373371137171313131713133131131331310113111131130121111110313101211310011010101010101100011337177737737173131111101011173735333533331313501013111631131735353173533533313135313135317137313313171713111111111111101011010121012111110101011011131101011001101103710112110101117373773777653113101103137173133533353133131313171313113073130331213353135353131303531733711535353131311313131313170101101111113111101010101101101010311010110110351310153501011237175377771377111130111313313353335373311013113101213713103131131317335131352133533171711733313313131311111111211331130110101010110110101000101101101013030010131031131313531011137337135370527131111333331353335333171313177307335112153171725353711131713313513530337331717317171131313113311017521012110101110010101001101000101111211111101013170170103031210135337377737147131331311133317335373731113111711533113313331131310317131311713313171537171371713131311331311011313113111011101011110101100100110101011131301317010113131311111113331713317777323131131003131331333131337307131130310311213533173131131317173171253133353137131313131131110101353531010101110101101010100111010010101112101101313131310101010312111113351731777507111110313133133113373111711103131135371713413107112111313131311353571373537131311103101013531131211110101010110101010110001011010110111101310101130113111311113010311331733537707331111310113113313171131173171533131313133173133713121713535312133171173533531313111111031121111301011101101010101110111010011010131031310111110112101010121013110311331737737707713111113313013013131103113131013131313111353171353171353131113517137317173173773301013113130311111010101301030112110101011010110103101010101010111101211111312111031173131717127731303311210101313173171311131701616017337335331331313317130353373531733317717311113113011131030301010110131111011010111300101011311131110100110100101101010113101133317173777077775775311111130117113170706070700005200101731731535351731171353173171757733717310313011011011111311110111101031013110101300001011010121010110010110110101100101311111313353177577737737713131111371311777777777716705347253531731313313731135353171373317753311351011101011101010010110101311013101011011101011013131110100010100110101001110100230011311377137037777777777777377770707725777777610634305277353535353731737137137137177731310131331310111010111111310113111011101131011700101101010110110101001010010101000011031371011373131717777077737575775777777777773677761071777520735373713171773535353717313713131013011111011001010101101031101011010110101073113110111011010010100101010113010311301107333013313773770777747773773437577725777777777707767036571737753735371353137353731713731101311303013775311011101111101111011010111111710100010101101111010101001011011131121100331311011311171771777375777777537777776776776777707716537371713717135377377171713533111331113011111313377751001101011100101011010101013311111010101101010011001010101010121101100110101011033735377777777777577777777777777777777070773535373773737735317177373733113131101711300101101113733100101101110101001010111011010101010110101011001110311010111101100110012110103117377527777377777357776776777777777770525313371717353713171737335371713311133133110111110131310357710010101010101100110101701110101101001010101110001101010010100111011111010010335317777574777777775377771725707777772531715373737373717377535771737351311111011310100111010310313371011010100100110010103101010100100101010101011131111011010111211001011311111131237777375777757777777704725707436531713737177173753535377637371713331313111101111101301111131011133010101100100110110111010101101110101111101013013011011010011011111011101313011753777737777777771725073520717753431353537317351373777071757373311111111301110101110110310113101013110100110110011011031001010100110110301111301101101101011001010101101110101071371777777777771704720742577634367125313531717377575707737375311131313131101011101011011013010111010111011011011301101101101010010111011110310110110110110101131310100101011113117177717577753577073512753471777707531753773717737737735357777731113113133101010101011011011110011010101001010101110101100010101010101010110111010110011010101113130110101101013031777773437777770742616343061617707672717177777777777767377371713113111113110101101001011101111011010131011010101010101110110111010111010110101010111011011010111110103101101211771777777577777712755257777777770735357677777777777771735735737313111012111010101101111100110101001010111001011101101010010010101111010110110101010011011001031011010100112111177377777777777757616327777777777777567773577777777777777537773535313100111101101100110010111010111100111010111100110010110101010110101111011011103111101010371713101113111011107313537771717577775257507777777777737377777377777777777773777377331310113121130100110011010001010010110101011010111011010110010111010101013013121101610101217130110101010101103131717771777777171727777727777777777477777777777777777777771735375331010101121110110111010111010111010101010101010001010100101010011101101011011101311371311525110110101013101111310317775257377777507776577777777777777777777777777777777737737137131310171110010011011110101010001010101110101011301010110101011101101011011101131311111703130310110101010110101031753777775777777727353777777777773777777777777777777777353753713571013121011101101101010101001110110110001011110111010000101110110110101010313010112121353411011011011111211113153775375377535776574347777777777757777777777777777777773713331313353535131000110101313110101100010101011101100110101003110110110110110101111011352111531113701101101001011130113317775777777777353774377777777777737737377777777777777757717131777317331031110101101101110101111010111010101110113111577777370110110101100101013131613536111305301011101011010317017737777777774347034167361757772757777777777777777777737313133111371531113111101110110110101011310101011101010301077377377710110110101110113111531353113635130171010173101131713777577777777774373436756572773757737777777777777777773737131011311713101035010101011011013107101011101100101311117737775773130001011101013101213317134311113717217073110113131317777717777777034141617373777677737777777777777777777777777131310303103131131773730101011101313111010110110101010137737727170131101000101101311311037135031701315313152111013112757777775777773436216167567535777777777777777777777777717373531311153110110737777537131031311777713110110110111110737521717310101371310101110311017101131431315311713313011013113737777777777741615250716352773777777777777777777777777777313130107301031013513353173511111035331717017010101001011713537371011135377510101011101713110353171301301110111011101357775777777777216102527777777777777777777777777777777773735773513111111101101315335317301035130101311311110101117727773777710112112537371301010330110317131135311113071121013137775777777777775250753477777777777777777777777777777777775733133717730101121101031535121331134111301711212511121713513773531312113111305377771735110101213170101303011121171101013777735777777702527673477777777777777777377777777777777737717113317531121101311131121711521131215131251113031112513411777701111010311310135371121031117152131310111011103171331357735777777777753473743777773777737777777777777777777777371737353533101110101012107111031110111133111312111103013103121331310101011010533531121113101213111110110101101353131111377777773535777673757777777777777777777777777777777777777773131313305311011101311311213101211031251031011101351710101111010011011101311351317111301531113012111011010101311301257777775777773773747763477777777777777377777777777777777737777131315301011301311131211101311131111131011101370130351310101111071103110130310313161713121013110101011010131301111377777777577777757737573777737777777377777777777777777777177353101311313010110121051303101121012130111010777173111210731101011031101130111310113131211113101112101011031101121071777777777717577763572757777777737777777737777777777777777777777131317101111031111315310101111111011011377353117121177101100101170101111030131211111121301101011117017521113113137777777777777737577257277777777777777777777777777777777773773731121735310101013030130531130301211301777717171303110310110111131371100101111101113030110110301010731713112111735777777777777777572775357777377377777737377377777777777777737753531171717010111011110113130111311101137777131171110357713010101011130111101010111011110113011111310173717110131737777777777777777257276353777777737737777777777777777377377177373713537313510011010131010131010301101777371731121110373053510111010113121101110101010110111012101311173137313031777777777777757775355717777777377777777737777777777777777773777713137717131311011011003111011311110177735331071152117771313210101011010110101010101010310101011101437113717353137777777777777777276373777377377737377737777377777377777777735777313171312535301101101111301301101037771731153121211735311435112111301013131101101011111011131121313310301371311777777777777777775717777777777737777377777777777777737373737737777130317113031710110110101101100101771731521311111317731213112112101111101030110111010101010101105015315301377137777777777777777773777777777737737377377773777777777777777777337777531313111131312110010101101110117771731131303110173111010717117112101101111030103110111011101131211313171313777777777777777777777777777737773777377773777377373777373737371777773131350307105351011101101101010773121121010110017211011313130311251310101001111312113013101301011121371313777777777777777777777777777777777373735737777377777777377777777737777777112131113130107110110110101137112110111011013771101014352535211130713111131271011101110110121130113137357777777777737777777777777777773737771737737777717373777717373737717777773113573773531310351011011101713111011001101073570131313113131213113152121051111101111010111110135711153777777777777777737777777777777777737373437737737777777377637773737377777777313173573535310311211010173010111011100111773171035253143151707352111113121031101211130101735737373377777777773777777777777777777777737717353577777777735737737737377737177777311177777317353535311121110111010011001131077735303513101313131311113030101113103135121413131733757357777777777777737777777777777777773573737377777777777777777771737373773177777173733531735371307030111031001011101110503171521711213531703703130311111313105314103531316113715331737777777737777777777777777777777773772737370777777777717777733717377777177777311773771531735317110101101101010103013113773111211713121311110110121210101121131713535317313331737777737737777377777377377777777777770753573534357777377771717752737377777777777731531731735735317312101101101031111013410717031701107111303110111111311121125371773535371711777777777777735377773777777777777777777377373727373734377577777771737377777777777777773173531737173535351330100111103013101311211101130313030110110103010101113537137177377171377777773777377777777777777777777777777777707773534365737716375357163717377777777777777777313771737753535373513171010101110131071112113011101111011010111113103071717753717717335377777777777737373777777773777777777777773707167335327777714177371727377777777777777777777711335353737137153717177711110311011130113011303101011073711012103113131313353773771737777377777377777773777737777777777773777773737376335353517730115073537377777777777777777777731537353537537371737137370710131030130113101101101033717735317177571615353353573777173777737377737377777377777737777777777737773435317237277735341617317377777777777777777777777773535373537177171717537731313017113513050310110117575773535353713731331357373371317777777777777777737777777737777773777777777773363735353773777535371637777777777777777777777777713137717177713735373573534307121703035371031037773737173735373777171171331317527777773777773737737777777377777777777777377777777170736357353032525637377777777777777777777777777777513737737771773533573531717171753537173537537173537753577717137173131171637177737777373777777777773777777777777777377777377777372537236353533531377777777777777777777777777777737353537531771737537773571777731373537173537537153717373335377173537170675242477773777777377377377777777377377777777777377777773712717737252163777777777777777777777777777777777577737737773173513717353777371435753717173713173735375357533133317373001024107343777373777777777737773777777777377777377777777777371210101217377777777777777777777777777777777773677753537317131371735371777713773335373571717717171737733113100137100000100074347735777377377377773777777377777777777777773777777773737377777777777777777777777777777777777773471757373717707175371735373711757357537173737713737335353531216174213000000000160137737177377777377777777377777777377777777777777777777777737777777777777777777777777777777775773472777573717707025371735353733717337173537531717175737373171706353471000042107162473637376373777373737377773777777737777377777737773777777077777777777777777777777777777777737753577777777770735317171737371753735717353713773737333531370070714253600000010616150377177177377377777777737377377777773777737737777777777307777777777777777777777777777777777777767177777777775040603121317177377173311317777131311010343107347435341041061061777276536363717737173737371677377737777777777777777737773777017377777777777777377777777777777777777167777777777727371707576713177377311060131313371763434340347737767761207161007077573713173771776375675271735377777377777377377737773777707677737777777777777777777777777777777777177777777777525677020753673135311677166072147777140774340377677777741676167077773767776172723377373737377377777777737777777737573777370761737777777777777777777777777777777777777777777777777773577527777172531770167107757375676372537734777777777275347712777677777037017757137373735235237377537773777372777353537777173577737773777737777777777777777377377777777777777771776172577777777607077070777677777314775610477777777720536710657777777770503303323743707073773577733637777377773436777670007677377777777777777777777777777777177777777737777777774176142770776777307077070773776777430637270777777777512416370376775777727765301703353737371212537771703774371773535213170001077377737777777777777737777777777777777777577777777736012147777753574007052525777717763410505003437707176012140505717727035001000600343303030035353637163775377763477637767007000375273773773777377377777737377777777777777777777777610400030707276301000000072504761700020000077410776701600210063600534720000201006304343037020071707707127525353703170716100007737777777777777777777777777777777777777777777777101073001675250534060030104352430170507016125703676010000050002714177043401401400751437070500143163740707703727343767070700001437735373777777777777377377377171777777777777777777777777705207772521014060707617767070305204036571717771610012415636707371423000210727052572002007707307007707163701010070760002053677777737773737777777717777777077777777777777777777777775307077560210110717617167761615314172776707761670717271610707671507014252572572570500740700434300707161677677770107001671737373773777773773771677777717171771777777757775357777777525252105060601671616170105204216357071770101034725777777771060701610777777777252070307077700071616177777777770707707373777777777777777777373777777777777177777777777777070777777777770707171777777777777773573577777777777777773577777777777717770777777777775257770434000000000000000000000105000000000000E1AD05FE" - }, - { - "id": "4", - "CategoryID": 4, - "CategoryName": "Dairy Products", - "Description": "Cheeses", - "Picture": "0x151C2F00020000000D000E0014002100FFFFFFFF4269746D617020496D616765005061696E742E5069637475726500010500000200000007000000504272757368000000000000000000A0290000424D98290000000000005600000028000000AC00000078000000010004000000000000000000880B0000880B00000800000008000000FFFFFF0000FFFF00FF00FF000000FF00FFFF000000FF0000FF00000000000000777777777777775773775737773773777777577777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777173434716174361735707353436571717377235700007777777737777737777737653777757377177737537537777777777777777777777777777777777777777777747657252103060206042434777777777777777777777777735777375374361705253432163617075727777777737777777737777777777777757775777773573777777777777777777777777777777777777777772524141210000040604004000000000004061677777777777777177763534736175370773527577757777737577777777773777773757717717717717373737771777777777777777777777777777777777777777777127052430200400604200000000000000000000000000077777777777771776773717237077052707271735735677377737357775773577737777777777777757753777777777777777777777777777777777777775251076502410040600600000000000000000000000000000000000007777777777171756757577307371717076734737177777777777773577777777377777777777777777777777777777777777777777777777777777777676107412042000000000004000000000000000000000000000000000077777777773773637075352525617357737576177357777357777737577777775371735737777777777777777777777777777777777777561600000016700604004004004000000000000000000000000000000000000000000777777777177777377677773765725772737777777777737777777357357377777777777777777777777777777777777777777776536177777777650060000000000000404000000000000000000000000000000000000000077777777757377671717075377777577573777377777777777777777777777777777777777777777777777777777777777777172577777777717777040040000200000202004004000000000000000000000000000000000000777777375775777777727171777373577777777777777777777777777777777777777777777777777777777777777777567537775767775600247142006040404040404000000000000000000000000000000000000000000077777777737370707567677774772777777777777777777777777777777777777777777777777777777777777757572536577727757700000164250400000000000000000000000000000000000000000000000000000000007777373775673773717353773577777777777777777777777777777777777777777777777777777777777756376357616767577777700000025020000000000000000000000000000000000000000000000000000000000007777777777174347777775352717777777777777777777777777777777777777777777777777777777777374357635737576167061652007560400000000000000000004020000000000000000000000000000000000000000777757377737716177767757777777777777777777777777777777777777777777777777777777777765374357434777077752161257003434246040000400400000000404004000400000000000000000000000000000000477377347563777071737377777777777777777777777777777777777777777777777777777777775161434243652527777756140007403400004204000000000000000000200200024040000000000000000000000000000377757737356177777756777777777777777777777777777777777777777777777777777777761636342707165256775777777777777000000000425200000040000000040040400402004000000000000000000000000000077373525617271617735377777777777777777777777777777777777777777777777777771775414340564167014707777777343576100000000004752440004000400000000000004204240000000000000000000000000077567773615777725777777777777777777777777777777777777777777777777777777770736340703167047025200777757202172507060000000652060004000400404004004000000040004000000000000000000000077352353634371737177777777777777777777777777777777777777777777777777777670504250746014304004043434275710050725100000000047004000000000000000000404000200000000000000000000000000077775743537477476777777777777777777777777777777777777777777777777777071072435274212420424200240041427060030052473400000000420000000000000000000000404040000400000000000000000000077172353653717353777777777777777777777777777777777777777777777777177477043425010410400004040043607404140061253043612000000040640000000000000000000000040400240400000000000000000176775253777777777777777777777777777777777777777777777777777777776537043471724202420424003043405607024240040243043416100000000060000000000000000000000000240000000000000000000000735077253434353577777777777777777777777777777777777777777777777773467743424014040040000604306521604000000000000100216034000000042500000000000000000000040004000000000000000000000527014343537072777777777777777777777777777777777777777777777770743535360500606034034070434702040000000040040042410501434020000000656504000004000000000004020400000000000000000003714363527707357777777777777777777777777777777777777777777777775347765160610014024072452400504042000400000000000200203030506000000000616160000000000000000400000000000000000000001634107107717777777777377737777777777777777777777777777777577767347724100424204070452521602002004000000000000040004000030314700000000042470040000000000000604000000000000000000061527077316703777777777777777777777777777777777777777777773752577716524612500563472524040040404000000000000000004000404004212520000000000047002400000000000421400004000000000000172016125613757777777777777777777777777777777777777777777765677741607521040256056152434306120102040000000000000000000000000040357340000000000650040000000000060000000000000000000705253573757277777777777777777777777777777777777777777775371777760524747025617256250004404464040000000000000000000000000000000000716707000000065242040000004074000040000000000000725363757257777777777777777777777777777777777777777777765671671702503244707657050656125212120350000000000000000000000000000000000001616520001060546006000002070400000000000000070707577277777777777777777777777777777777777777777777777371677564652645217771616070216525674774301000000000000000000000000000000000700712107700112034610000040470000000000000000170707257753777777777777777777777777777777777777777777776565352535214120747774343417470753537531000010000000000000000000000000000000070041650030677400046000253640000000000000007070737773777777777777777777777777777777777777777777777717374240607420547356534343743773676573000000000100000000000000000000000000000057252121013577777000040643740000000000000007071757777777777777777777777777777777777777777777777777656534343416520347736747343743571777741010000000001000000000000000000000000000217010000203177777742041677740000000000000725242737537777777777777777777777777777777777777777777753737470042430476770571734775376777177300000100000000000000000000000000000000034161001210102777777750000567704000000000003525375776777777777777777777777777777777777777777777777765743004341043177177365777167571677770000000010010000100100000000000000000000003002100010617777777600600000425600000000056102527377177777777777777777777777777777777777777777775363742524242147576525365777772773576710100100000001000000010000000000000000000000100210211037777777007000000000424000001200614357176177777777777777777777777777777777777777777775752542505252167537565372573577577357300000000000000000000000000000000000000000000010010201077777770077000000000000000025300020216177777777777777777777777777777777777777777777727772142525042536743534757777772777774100000001000001010000000100000000000000000000001210121777777700000000000700000000704034175777737777777777777777777777773777777777777777777577054252420356771776777273477777477710010010000000000001000000001000000000000000000000012107777777400000000000000000434303403434341577777777777777777777777777753777777777777777077025241504252563575257577775777177300000000000010000000010000000001000000000000000000001217777770000000000000000000000701612537363777777737773777777777777777777777777777777777167061626143473576377727573777777747100000010010000000000000000000000100000000000000000000357777770000000000000000000000761612535777777777777777777377777777777777777777777777776714161416007076175673572747377777730001000000000000100000000100001000001010000000000000000277777000000000000000000000000170777763777737357353757357777777777777777777777777777753422507241707716437757757775757777500000100000000000010000000000000000000001012400000000000021776000000000000000000000006707343575777777777777377777777777777777777777777777777767450615242506717653672771777377737010000000000010000000100000000000001000000001000000000000404070000000024000004000000016107777377357777777777777777777777777777777777777777777173070625042516705657757767167575770000000100010000000000000000000000000010000001010000000000000040100000176000377000770352525347777777777777777777777777777777777777777777777777656071425252435635270777777772777710010000000000000100000000011000000000000100000000000000000040252400007610004740007077602537737777777777777777777777777777777777777777307757775307406160043463527577757753577707000000000000000000000000000010000000000000010000001000000000025240000007000037000007761757777757777777777777777777777777777777777777774716773776502534165241756752707677767757770000000000000010000000000000010000000000000000010001001200061420000000000000000000003161207052777777777777777777777777777777777777377717617747777702436125260743657753777777257730102100001000000000000000000000000000000000000000001001000061400000000000000002506061657127052777777777777777777777777777777777775770777065707776561405601416165252765777577777100010000000000000000000000000000000000000000000010000102567060000000001773774352100001206107357777777777777777777777777777777177777073701752756177347360560605257653563477777070000100000000000000000000000001100000000000000001001010216100000000000606043437777777777535771677777777777777777777777777777777777775777720253617056704076161425241652577736577710100010000000000100000000000000000000000000000000000001636160000000000000000000424343437763071777777777777777777777777777177777777721747570257077717725036163425243652525777777700010001001000100000000000000000000000000000000000000101404000000000000000000000000000001757277777777577577577777777777777777735773577737051207430653524507041425241616525074743101000000000000000000000000000000000000000000000000010202020600000000000000000000000007477375777777773773737377777777777777775773576777752025070161347770240724340160652567371773300101001000000000000000000000000000000000000000010001040040000700000000000000000000077767777777577777777777377777777777737777777717161743507076146161657070524176050065256563673730000000010000100000000000000000000000000000000001002040075017700003740000020000077772507777773777773573757777777777735777737777007007342100170352573657070524016070024343571733733210100001000000000000000000000000000000000000001000077760077200007600000750000743756173777777773777357373777777735777777765307701635250610616070052725242525607043410706074773773610010000000000000000000000000000000000000100000777777700774000177000017600077774216775777777777737735357777777773777707534160060070521061001725250577752520140707060407434373333321000001001000000000000000000000000000000010137777770007700006770000777005777425621777773737777717373737777777743777777034177171030060125614165252552752576034043470702434277773732301000000000001000000000000000000000000000377777770017200017700003770027777001567377775773537351717537777777705053770436143434070104030612101612416070757434343434707056173773737321210000000000000000000000000000000101007777777430000000035700007761657777023057737736153434370703777777753027777072534341603436737410707061613611616252524340610707256173773737361000100100000000000000000001000000000177777777000000000000000075425367700456375773717273537073171777777361417777050616030141410041271527170040065255352534161460525024377377373337312000000000100000000000000010000103777776740000000002020340702576770612734736157777577577174341777770521257772171616577273430034020142534352101207614216167376167534217337377737631210001000000000000000000000100377777777700000000000140000252753470434717717235377363777373771777770525277576507177775001412535160342100052405205214704175070177777777773337333733733000001000000010010000100007777777576700720000002102141652752430525637777777535757375775277770702525777773777717120302050767050104777253721610610212527416777777773777737773772733312100100010000001000003777777777770057400000056000200256341402527535377353773735777377774030050177677177777772514101200103777777775705050161241470412707777573777373773337337373733250010000010000010177777777767700272000000374000175770002016752777557671775777375775377470276717177777773712037400142057740217737727060041020003040775773777357373377737737372373333431010001010037777777765776105750000007770006027740012452777353353771737177777377737775357777777777657571763002100212710612410535161061434343000737777577777777337333737377373733332303003037777777777777576002700000007740305057730003052557677771777477717377775777777777777777757373070104104000417651251243420107072534000437775737717377377737773737333373736373373377777777775777727770371000000777000026777400006357353777176717353775777777537777771737777377740170000630000377025724103416000057052573775737777777535733773337373776373733337377777777777777477577000000000003770002517772000534727771777717777777777773777777777775717777571270030010750304161407100617070012006100777737753535737773777377737373337333773737777777777777777777777000000000000300142437740002437577177777717357353717777777777777777777773751734000007614300037707010074010401000703717773777737435353717373737377337733777777777777777777777767765200000000300030303474340107437777777777775735777777777717777777777753567721737000000037430070707352037421000125075761777177717737271737373737337731437777577777777777777777757700000000000000404043076120001747777777777777777777777777777777777777777730507430001000753401000006004143100340003773777537712771717535277373717531343777777777777777777777777774100000000100003034307410002567377777777777777777777777777777777777777771752013410025037700000100104002016070000001771737753757172713617116352733077317777777777777777577774777772016000006000007000743600012074777777777777777777777777777777777777771612052412410735700772000000030100010170100070775717371736173753737353711653107057777777777777777775777777750275000016000007000347000074377777777777777777777777777777777777375377775210241277727777050000000000000000700000375363743563537152317071253731357317377777777777777777777777777061760000770000770024370000035677777777777777777777777777777777177777771421434120500143417007006005000000001600017527357377353716375613535352534331707777777777777737777777777776174300007700034740535770003473777777777777777777777777777777777773534163503430752142100025001010206000000000003073717717535341735133573617353531743177777577777776577777775777700374000077700077702476710043657777777777777777777777777777777777577672507701617742104371020060000100100000000000707352712737371736532535343172521343777777777777777777777777777740770000777000777012577600143777777777777777777777777777777771737761743700161614100630407050107050610020102500017716353753525361713533533172531717117777377777777777577777777774300000000700007770607775004256777777777777777777777777777737777770017171700000030601750300216100210061412517211473471735377173534352570347153170707677775767777777777777777657730000000000000017270537760021617777777777777777777777777777777771710024361614000001700250757576014070121612745763771372573433053713753177132352171311774377777577777777777577777430000000000000005027060000525677777377777777777777777777775771671600015300031200000010003002016030052410417320177774173437577070712352117153070352707777777177777577777777777777420000000000000205007030000435777777777777777777777777777737777161001020502404116100700700351701403001243524177777537073713137171751357216357171351377777757767577775277777777770105000000000000125614000161637377777777777777777777777775777712716000012100300600610601617206060340704100617777777253535256517343136131735121214325777357677776776777757757757616720000000500002070200000027477777777777777777777777777377717050705000400100101010071610404101100120120701777773771617037313725307717251123717335167777777775737771777737677777007700000027000014070000025017777777777777777777777777777737773010300001242520002000000030300607740165100777777777771617147707135301717367510714325377777737737757777677777777777475600000077000030770000024247777777777777777777777777757777340200030301010143414003416500010161034020773777777777771707331352717375215313671635101777717577777775777577577777703677000001770000047740000107377777777777777777777777777737534100100000020030201021343212177060002503177775777777535770731475251617031736161101016367777777657777277777777771777077340000077700000375200016074777777777777777777777777777777730000010001010001021000153534317173412147717777777777737771073031631617070517036373614177777777774775761777776775770054300000377600007777000250077777777777777777777777777775735701000001000001001003012153535637173577357777373777377777777071611613435272035014010337777717717777777777734777777770200000000777001007770001607077777777777777777777777777377773000100000010000000100017013531353572717737177775777771777717161631611201017037737775777777677777777537775773577777061000000000000020077700007007777777777777777777777777775773500000010010000010010001213343175727353773577757777377177777776173052163577777777777777777775347753777657777777776776100000000001070000024000700777777777777777777777777777773777000100000000010010001001715317031717757177173737375777777777712141253577373775737777277777777737675777776375777717716000000010020000030521430601477777777777777777777777777775373100000000010000000000121303535371713737177357575773735777777752173773777777737777775777777777577777577177776717777616000000200001210002402417423777777777777777777777777753777700000000100000000010000116152135073752577356737373775737777777777353777357377777573777777777776357276377777777777777017000010000024000052503402547777777777777777777777777777770100100100000000010001010311313437305317125373567175733477777777777771717735777777757777777777357777775777707757677706774000670001434005200342704377777577777777777777777777771734000000000000100000000035230533111735737737173537737577777777777777777737777777777777777777757707757777657777737577707770001775020777205274305216777737735377777777777777735777130000000000100000010000111531417251235017153537525737137777777777777777717777777777717777777777777771617777777577777052770027767403775600774704257577777777777777777777777773777000100001000000000000103030121301375137352370713737537577777777777777777777777777777777777777765727777777775367777770775216177703477761657770705237737777777777777777777777775301000010000000000000000013517171717013615357173757717343777777777777777777777777777777777773777537577777771777777777616563407777442577524377707027777771777777777777777777717373500000000000000100001001312303112317351361307153313717177777777777777777777777777777777777757777777777775777777717777012142147772106776106776524147777777777777777777777777774352101200000000000000000000111116116112351353533747717335377777777777777777777757777777717777777777777757777767777777756042142052142507706107770707071777777777777777777777777317016161100100000000000000016125213513515361353453313635707777777777777777777777777777777777777777777777777777777577777734304343252052052050617070607777777777777777777777777101521613016134301000000000001713531701212121116171335757171357777777777777777777777777777177777773577777777777775777777777400434344047025205261602434167777717637717777777777777702503507107010521210300000035371161735753534312134530317353777777777777777777777777777777675777777777777777777777777777770703434034307504361420410706177777777577771637777777777753503016107030505250103000071673535331361735717133517107103777777777777777777777777777777373757777777777777777777777777770600616034202704161430612506717677773777777577777777777777775210703503031216101717171163525677171723527507343712577777777777777777777777777773577777777757777777777777777777777401771616005614306025070416017777777777777777777777777777777777771410307041610777777777717171103525357353735371717777777777777777777737777753777757777777777777774777777777777776167760414777070615706003601677777777777777377777717777777777777777774101301777777777777777777771717015253437161777777777777777777775777777777577375773773777777777777777774777702570772430776061427741605261777735371777757777777777777777777777777777761777777777777777777777777777771717107127777777777777777771777777777777377737777777777777777777777777777742400412477775243477341615067777777537173777777777777777777777777777777777777777777777777777777777777777777717577777777777777777777717577777735677777577777777777777777777777777053761610077705243777600260135377703677777737777777777777777777777777777777777777777777777777777777777777777777753757777777777777777773777777773537777752577777777777777777777740276160607770425257740165016777577753177777577777777777777777777777777777777777777777777777777777777777777777777777777777777777777676777777777777757772777777777777777777777777705070501607721605277342032407703777777377773537777777777777777777777777777777777777777777777777777777777777777777777777777777777753535677277775773771753617777777777777777777777200020601400401240160104052777757777771437777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777773535757377777777075777777777777777777777774343430703430705216070612410777777777773777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777777377777777707377777777777777777777777700040040240060420400000007067777000000000000000000000105000000000000D6AD05FE" - }, - { - "id": "5", - "CategoryID": 5, - "CategoryName": "Grains/Cereals", - "Description": "Breads, crackers, pasta, and cereal", - "Picture": "0x151C2F00020000000D000E0014002100FFFFFFFF4269746D617020496D616765005061696E742E5069637475726500010500000200000007000000504272757368000000000000000000A0290000424D98290000000000005600000028000000AC00000078000000010004000000000000000000880B0000880B00000800000008000000FFFFFF0000FFFF00FF00FF000000FF00FFFF000000FF0000FF00000000000000777777740043734074373737370737777043707777777777777743777777777000534040673577777500740000400050040042500000777770004217073737373773777730040407073377307373725000043374053000003737373777377604074377777347737377047637777777777777547777777777400750250573177777505350700050000000040004000577770404033773737373773370400040407071214377373736100372000073777777777777377704404427437307377777734341777757777757477077577777771040075000777577777040614340000000040000000003777700007773737737737377040040000007061637373773536173040004003737737373737520404040453774777737373777777767777777777705777777777770004770477737777770051004100000000000000000047777700737373773773737200004004040407173737377373737340004000777777777777736440406404247073737777777737777577777777745761777777777750017770777537777750065000000014000000001040005777733737373773373771604004004000063773773737373730000004040737373737737700406040604007777773737737777777757777777770742777757757777777757777577777601734000000213000000040004167777763737373773773021400004004005373737373737373400404000007777777773753652444040404737373777777777767567777777753475757777377774077777077713777771561410504351750000000000000017771000437373772007003040000400737373737373377240040000040473737373776345340042440573777777377377777577777777777767527077357777717737775775777777770140040037077100000000000040477770703373772253733704304000071637737373737603104000404000777777773617370744044043777373777777777777775777777777577757477737777717777777737177777740000005753176001000000000000077710007373351273773334304037361603737773773506000400000407373373653773773734040772365777373777777777777777757777756770577577777705776177777577777005000127357710040000000000400077705011340361433071214015730001061733770003717000040000377777765343763770704077344032737777777777777777777777777775752777377771377704777737777773001057517375000000000000000007777001340004373737370033723710360273773173733733434004037373640436777377070773734537477777777777777777777777765777525257777777175754007775717777740070030777700000000000000050477775377310000073773207373376004005336036007256352000033507765060470737737707377772407073777777777777777777775775767775417577777737600017737117777101400573777000000005000000000007734170771371052371337373337010033404017373337253434372040430440475617707777737352507775277777777777777757777775775637777777777771404077777357777003537157700000000000000004340007734351005021050077373777373773700004007177373003737370060440440427603737373777777773465657777777777777777777777565547777777757770000077717777775007167375000000000000000000100577515335701507130036373333373340040400436334307773735300440040060471777777777377373746175767777777777777777777777716377357774277040417773777777710731717700000000000500000040000750072571173053711001067777324000000400435430773373723440444044040463737377377377743475677777777777777777777775375657757777714074000617753537777715731775000000000000000000140006734150163413041405031100337004040400400423077377737373040040044041777777377777737443475657757777777775777777567477777777777737434005747777777777777777701000000000000000000000017737350141741030017521110100000000400400437337373737374044444040773737377737377761674367767777777777777775656757777777777777400405521077371777777777771000000000500400000041043775775214170171413710052177111040400440053737737373737340040004376377777737777752574577575757777777777777777771777777777777753540436040777577777777777100502500000000000000104167527101507006121477105010713040000040007377373737373716444074407354241737737372777772567767777777777775777757565775777777777770714054050777357177777777010050050000001000004707573517040350514140717010711771310040040737337373737376300004016777365347737777573737777565777777777777777777767777777777777777777707016177377373535777770500160004014040000015707777071357300717152503537700103610000337024253737373014074407737374074327771636777777777777777777777777775777577777777777777775353757757657777753777777710143505000000000000420077505357314141361050341510153533000707700500273737043233016773777734004776167717777777777777777777777777777577757777777777777777777777735704777735777777052050000056100000000504573417215614170516135170077352700373373042125377352373577737773737737773534407777777777777777777777777777777777757777777777777777717777407707777737777701050000400014000000050030753751701016153050434037135310137377352104037304250732373777777737737772404406572777777777777777777777775777777777777577777777777777777045177777537777701000500050400073040070577053653507317053171714177534316373373734317304000303737773773737773772444061652775777777777777777777777777777777777777677777777777777775067577377777771070050014000077141017500773141250714705257371304712411017377733637724000404343717777777777377040407440657777777777777777777777777777757777777775777777777771777770572777777777771052500400007104040470077714105073531505346525035353104313523773370004040000340273733737377174042443470747777777777777777777777777777777757777777777777777777777770571771777777770014300007314000010140534107014143560734110505107173117703161137004000004040301777777777776377440641474377777777777777777777777777777777777775707777777777777777777765777777777710014005054000000404007717053430501141416350167125776143535377100000404000040773737737371616525341464077777777777777777777777777777777777777776577773777777777777704077735777777771401420000000000000771752140410716100715371711507010000705734340040000400033377777777563773736442537777777777777777777777777777777777775757717477777577777777777507105777777777700040500004004005271456105313410415351040507170100571050143410024000400017377737371736173777753544777577777777777777777777777777777577677657743477773777777777777057604353553777040170500000000005473116535441710430701313507173100071016110037100400403736337777760416773737763777777257777777777777777777777777777775777756543577777777777777777075070402741470004070400007504071457717731061770415061701161775014014017340336030000370034271730406635377761777377347777777777777777777777777777777777757777756777777777777777777743040057121741405000005500007700370571414141051734140534135301731421410037713005377003001760440440576527377777777777777777777777777777777777777777757777561635777775777777777704354100177717353400050520070577144007061735305301531073417770141040143000000347733330040020406044042437757777777777777777777777777777777777777777777777777775777777737777777777507377770377757771004377750525305335711507535377042561717101710350140053053100003777610040340444004040407377777777777777777777777777777777777777775777777575775657777777777777771777777777577737774005770061775254177721703405171010141712500404250143750414000100037361353044044424404777737777777777757777777777777777777777777777777777777777377777777777777777757171737353577700376107577771034351570514176053416077141301001104141000001004000737373204004400440563777773777777777777777777777777777777777777777777775657757777777177777777740257777577677377357414773777777514043052412511241710535035101070004100711250031003737204044420444243777377777777777777777777777777777777777777777777757777767757777777577777777055614016141014014707617571777777717107113414341530417101430417171300001071351410173714000400472405773767777777777777777777777777777777777777777777777777757577777777773577777770061616140164400071417773531743777777577414341041410716101410000471711400050031007373210400444041773743527377777777777777777777777777777777777777777777777777747577777777777777147141450706100165065675353435357077777701617134301570510700005710040043115004140002405200072407773774256577777777777777777777577777777777777777777777777577775777677777777777770434343070414147707173537753777717177777775353410467313050100053050010000401000015013303504041773777375616177777777777777777777777777777777777777777777777775777757777777777777750541404050404165047171653717777777753537777771711107507170521414070140100007100030077372007773777377737777774257777777777777777775737777777777777777777777777757757777777777777070043434252177165377531353717777777777571777777777173516530570101050101710417104103307353073777377737777776174767777777777577775777577777777777777777777777777777775753771771777057041405057416717171775353357777777777777174765777170253501071404340561013710000073733200777377737777372416477777777777773771777777777777777777777777777777777757777777775067774707143077257771777077137714777777777777777735173477535140407400101000104050000005343250177377737777377454657575777777777577773777177577777777777777777777777777775777475707575735707354145735371717357717371777777771734777777753507777311403140540505010000010002143027377737773777773652477676577777737777575777777777577777777777777777777777777577725707725675747777377775377717353715377737775775735775777777717174001571003100005610007710402007737737773777356165257747577777777757357773535777777777777777777777777777777777757577757575377571311177777761757357731177577173777771777777777777717161035040530001710510000053733737773777376737777756777777777757777777357777777177777777777777777777777777777777777777737753361037717171177335371107777737775357777777173777777717537571001041140040004000377373773777377717773777775777777777777577375371777777777773777777777777777777777777777777775771375113117717177175735737717777577777717777777571756571607573431405040000110000172137373777377436727777777777777777777737357775357357771777757777777777777777777777777777573737771133513137777177375734117371737717371717777777777717505170541401210171043500036373637377377700453577777777777777777777757777334357777777571771777757377775377777577377777357535177152103577777717537537701777571775777735777777777707352052070535050404173037100003737377430464367737777777777777777775737715153717717773777777777775777777577377777573571713117310311313735371773753771177777377537353077777777777775757715000143100130103724000073737700440404407777777777777777777737717734357777753571771753535371717777777537753777370171301711311017771717171717537357177537757775352577777771776717771571077300510733100700303720464040604745777777777777777777757771735353573753171773777735377777537177753751775373015311210313117777377777713517777177537371735352567777777717750773700571412513772300007340040404404524277777777777777777775377573537777357375357177771717535773757777353777531117131731533010717775717117752713777777757577137153177077777777104144353000751273373533700000040640460475777777777777777777777537357717535771521737573535353773775353577771753371713073503151137771731753771371477735375373717712714717577577777310000411410303737373360000004404140474377777777777777777777177757717537773173171717171716171757731073775377357130371753710370177775777375377173175777371757713717717052537177777771110061041737373360404000040466340477767777777777777777777717777737153577177175777713531071717771171775317357171171717711310777737175375317171371757573717717537777050547535777777710171103737375300004000140475253777577777777777777777771777753537777357717735371713171173753537771335757317173303711310117777777377175737177777737757770531773777770107677777525752570373737020000000406340527777777777777777777777777175777371753535371353537573017017315373753177573731713511535370311377777535717733531257353577773137373047377377771505043504005017737200105004000075257777777777777777777777777777173575716357771775353753153717171731353737173757171713033531110301777777777735753571377777753757535350004377377777777140105300373610373320000400527737737777777777477777777777757177773515353571371713773717113035775357173577353537171531437111177777777177737713175353537757337535314000377341273777361005343243043343734000037777777777777777577765777777777735717773617777375373757753535301537135317537317131717131353173031777777777717753716377777753735753530704044204377777377777735004004337333000373737737777777777476757577677777771773757771573717317571737373130121717531713753531053530107317513107777717771775353535377757373571373531000003537373737737773400000437432700137343777777777777777756767775777777775757377573577757137377575173511535313531253713413103113115313711377777771717737717375777375753775173530404043737373773773640040400003352177373377777737777777777757576777777777777357773537777357175173735013301317130313535713177117103710353217777777777717535717377777773775377171700017373737373373730040000404040012337373377777777777777777767757777777777775735353507517317777171373515311717115153530353533503111035211177777777773777731717777577777537534371007327373737377342504004040000037373736373737777777777777777757777777777775773577371731371775317177111321703130312135351313571313503531317777777777757377177777777371713717371521720500737373730301600400004003737373737377777777277777777777777777777777773577357535171701735777177771511353510116171310112131103111353135777777777377177717777777777757735173173700300373732161733400004007773737373373777773747477777777777777777777777773717353735301717317777177373771313135317171731717171313071301735377777777577377777777757777371735341373004003725240372733704002120063737373730777244345657777777777777777777777575775757134353715777777777177171617101137371121130131015353137777757777777775777777777777177535121737214001730000127337340003737003003737730003747434727777777777777777777777777737537371711135773777777717537171711312577133513713171331330757357377777777777777777777777753103571733733732040040613730034373500404373732013344346454750747777777777777777777777537575353716135356177753773535313035111352513711711350171117377377377377777777777777717153737171333773737040000000343430733736300003372000272434707256776777777777777777775777777537377717317125310177771535371715137305313153713712135330707537175775737373777777777737357577357773373700000000040000737773737030370040000336454745614757777777777777777767777777757535735711535317717073537011313411137171211351353531175353757737377757777777777777775737317333377370000404000000733733373733770004004037307257165677777777777777777777574777775373537571373130171711353751371371373571315353125313713537777373757737775753753777777773775773777307000400000400537377377377370004000000000745677725777775777777777777777777777777573537377177517170535353131071511053534331353535710172571357753717577373773777577577675033373337030710000000021237337337337000000404004007165747777777777777777777777777757777777777535777173135133531353571123713353135530353137313573767353777773777753577537437737070073777003733250040021373737737377316000000004000377727377777777777777777777777777777777775353537757171733513175271317151351357133535317111777171717775353777577777737773535753007340030733437300003724000323737300401600000000037747777777777777777757577777777777777777177777717737175351343531152531337135373171313535373707771771737777773717371717177737377733000030373730073771000007373702533121000040613737377777777777777777676777777777777777777737717517757125371353171353515113435353535353313571771770775653537577775777377171657173573400437233070373270000037342503363707000031343077777777777777776757575777777777777777775757737717777135357353171312312513133537173171703471771771637777777753737175377173377173773500005030373373303407340002527373000121720000777777777777777675676767577777777777777777777571717717107135352171715353710513113177161771347167171753537537375757377137757176170773700030737373737373300000043713250727372004007777777777777777567757576777777777777777771753773771731713535317073537131131251347537177175737717777377757777572735717771737717735357340373737373737304000040000605233737215000277777777777777777756776577777777777777777777777771717471753537531153513516113161337567177637571707175717736173757563707173535217537717170737373737376000400004000303773737321211777707777777777777756577777777777777777777537175775313531317777773533752137153175773574175737371717377777577577353575352527535737537763737373737373300000004000007733773737373607777777767777777777777777777777777777777777777777777531775777535313571317113317177577377537575670716177777352537777165753517172516153535717337377034014000400005733773373737300007777734347777777777777777777777777777777777577171753175713773771757173531735777777375734347371171617617575777757016133134361615217277173752737303703000400002733377337733734000777775674756777777777777777777777777777777777777773775303753757171377177171777717175775775174777071717763777534357715756717535125017137343737021633737300404310242337733470000007734241434757777777777777777777775777777777777777753777153757317775353353777777777777735734371771617717577773577357020115213434171257417353535001733730700037700004337733032420075676564743647777777777777777777477777777777777757775717717125777735353777757775752535767577576171771773717777147707152527571007055213735373730061673700373730000033610403713100241450470745357777777777777565747777777777777777775373771753537177173777753777773777776117717717707077175775707370535211357000505321756171617050033030377373600005340002372372006564773464767777777777777777767775675777777777777777753573717537177777575775777777534157434717757717167737737757173531525353410125570716135317304043437737373735320000405373310150473775341777777777777777775747675477777777777777777773573737577777577025677777577777353534357375777175775771616516503134353434121534357434315300073733737333734000400020342063773477434777777677777777777777757477777777777777777567777757777777777707571775777757525257357075776177737177141753713040535251000572515235315235173737773737770000000040004017333775773777777477777777777777770743777777777777777777756577775777577777753675777577737753525707777717753757734004005340017253505035251637512521163033733373733120004000004033337777437477773773717775777777777777777775777777777777777777657777577777757775777777357753747734100775701657370400005341153415343005071071410710507115063777373560000000040000377733773737777777777777670747777777777777727777777777777777757777777777777775771435777757775357534175377751774340000007342161617141000570161710712527031003373712134000000001373323737477773777777777741674777777777777777757777747777777777777777777577777777777777577377177735716107577377775100000014105141707107000000101071351117140377250073733000000360307373737777777777777761765453437577777777777777765777777777777777777777757777775777777775756717563475777657717534000004770506170716500100014303125306736037000007372730000173000003373773777777377777560563647467777377777777777536577777777777777777777777757777575777777735763753535717347777400100001536514175010140505211141507510517340040437373730033270000037207777737777773636561441641773777777777736464756577777777777777777777777777777777777775771757777770755353537500404167536170177710100005250003103712500040000043700037731300003000077777773777747573464344377777777777736753574356747777777777777777575677777777777775377077777577775277747743452525353516156150741410001000304341250040004040000737732736331200000737743777737737377504437563477777774757746065670777777777777775657677757775254777777717717357757535705371757341757765251617275100040000100517165000004000004373773373733120000007773743737707777703737776173437777777737357561477777777777777777775757675777734757777737757776376777775777357350717175071757524050100100052050100404000004006377377373372000000043770377604737377747737374467777370737777725477777777777777777775677675777757770757174757753575357717725257657756756177161613531214015000050040003304004003717337373377000000000743777704061677343737777737173706577777774773773775377777777777777565777777775777277731343777774735771757705770735717056140561405001700041000005373030403720727737377300200000000377700404043714377777373777744656277373737777774767777777777777777777777777777575757574315777173577775075773577571653535257170500534001100400337340003171000013773720031000000077707440442404277737377777340614045077747737777773577775777777777777777777777777777777535777777577765777373477537775256525507414341710406500016737370737234040273370177273040000700406160040405377777377377704607064343777777773777774725677777777777777777777777577536525735771077561775753567525775375707143705376501010400030400373737300007340060335370014137440604454040737737377737434740544144777377773777736161475757777777777777777773777777753416567167707176576757357577777525716141735710040400040403777373737737704004075737203633606160100600437673777773563434042424637377737777777456576706777777777777777777475777777777771714141414753571775737252777571657177525705040004000737337373773340000000020201737373604437340443700047373772537737404417477777773773617252414750777777777777767477767677777777777777777770777774165475757773477377470521400004000433737737737374004040404070737373730100737003737070027742563737717707737070737777477777756740777777777777777757475757077777777777777777574757777737773774161037373073773160000537527737373770034000040000073737373737347700737734043770406177734707373742563773743737371614377072777777777375253434257777777777777770707070737737773777352407740407073237000343600000377361073434004040717373737373737077737373737370000404361773777777356177044377777777777777757777777777777747475777777777777777474565654657777777737373700000007373703173373000037302527373300400030233737373737700000000000000000000000105000000000000E5AD05FE" - }, - { - "id": "6", - "CategoryID": 6, - "CategoryName": "Meat/Poultry", - "Description": "Prepared meats", - "Picture": "0x151C2F00020000000D000E0014002100FFFFFFFF4269746D617020496D616765005061696E742E5069637475726500010500000200000007000000504272757368000000000000000000A0290000424D98290000000000005600000028000000AC00000078000000010004000000000000000000880B0000880B00000800000008000000FFFFFF0000FFFF00FF00FF000000FF00FFFF000000FF0000FF00000000000000733431247777777777777777777777777777777777777777777777777777777777777777777777772577777777777777777777777775677750043507777777717677777776343737737172736373635337373373727300002407477737777377377777777777777777777777777777777777777777777777777777777777777777777777777777777776767777677777775247757777776775761707373737237372737173717377373777363737733477777777777777777777777773777777777777777777777777777777777777777777777777377777777774777777377777777776777767677760104357777775673372737373737737373737373737337373337173732407777377777777777777777777777777777777777777777777777777777777777777777773777524000000000000004165777777777777777527750435677777773734737371737373173737373727372736334737337377777777777777737777773777777777777777777777777777777777777777777777777736140000000000000000000000000040507777777777777770041757777777733737273637376373736373737373713733737637777377777777777777777777777777777777777777777777777777777777777777777734000000000001404160746740040000000040657777777777775241677777377737373737373373727377373737353773737237377777777777777777777777777777777777777777777777777777777777777777735210000000044767773777577353777777652040000043777777777774161577777737725373735367373737317371737233373737737377777777777773777777777777377777377777777777777777777777777774371600000006177737534247043414747416171777737000004077777777770043777777773737373737337371737736372737776373733737777777777777777777377773777777777777777777777777777777777756370700000004577616506461407404740043406060407437760000005777777775241777777373737363737737373633737373733335273573737777777777777777777777777777737777777777777777777777777312777700000407773052507005040400000040040414052525041775340000537777775340777777773727373731737373773737373757337373637777777777777777737777777777777777777777777777777777753434777000000077757047040404004000400040004000404040406524177704000477777774177077777377353772773637373373737373237737373733777777777777777777757777777777777777777777777777437243772500000477725242404000400000000040000000000000400050412407772000057777777407477777737373337337363736537343737773373737377777737773777777777377777777777777777777777775373607346750000047750404140004000004000400000400004000000004040443400577700007777777001477777737277737737353733637373733377363734377777777777777777777777777777777777777777176372577747770000077725257040404004004000600606070745424040040000000400561617700004777777403777737737337337173737737373727771325373737737777777777377777777777777777777777763617253476347370000067745040400000000406574757577577577777577777704000000040040407770001777777754777777737537727372733737373733367373657477777777777777757777777777777777777535375361767356776000047710343400040042456535377777773752713637777757774000000004043430770004777777037777773773633737373773737337177735657727377777777777777777577777777777773537270365763565252710040775644040040042457373765725730577757757577577777777640004000040450776000777777414777777373773737373172527536725727373577777777777777773777777777777373436071675364743363770000077205340040006577707161775735476177343777373776773777740000004000434170400777777434777777373373737363733736717737776563477777777777777777777777770325253437767164733256577400047705404000004753520712577073527717707775252572537575775774000000040042573001777777057777777777373525737747773770771737373777777777777777777777352137563767743706733565777700007714742000407573672171657617161753770773537357357757777777776000004004050774000777777077777373716373737743737167077273434777777777777777777737716376562570752743712567776776000477600144000256171353435753707167370753073435257743727737777577400000004250376007777777007777773737477773776577737717773737777777777777777750730707077576772703725777747776700007705640000057177071253437617343572534771717077717353531653737777700000040040577005777777757777777773716577373727537772377733777777777377301273472777616312171774777567677770000770561040004347712165617561340177353473563435752717073431307171777400000004340370007777777077777777777673635365373673757773777777737163434767747374161631676765677667747776000077524004000534712161731347317037725347172153772710725343574716167177500000404004770007777777517777777773777777737737377337377377777727073777706347436373477777767675767776570007700534000004716774352164357075053534363717257713770125352131616107037600000000700770057777777657777777777577737377737377737375337164177474617716303434767675675675767577437000077564040400034353316171356371237773057170717717703073527074777777777757700000050601740077777777727775757477777737377377737737377727077607273630716777777577567767676747237760007702014000004770774317070757071407307277353653631717143577777777577777774000004041403700577777737575777777737577777377163763576374177670734307076657677676777676775370737461000570655600000061177130707165217121770775317075377143434377757317177775777770000000040477100777777777777777773753777737737771777735777601271616777777767477476767757363437073770007341600400004576174353160177707525371737613777316317177777357736134361677770000004161077007777777777777737170300777735673773737777670761677776776567777677776567347163477477000477041400000037716334343170537103525356535616357316167770537305070537171777770000000040077007777777777773507140500777773777777472731271777567475656776767727037352736752707630043707560400004547357435252077416343036373721775325217577072534373172534361757740000004340770047777777773052500100005777775617617357761677676777767777656350343761674775274731400074040000004056371753121735701735171715717177733535773713535215257053437173773700000404107700777777775705210434770007777773773777777777577476767777257316377341765770725321633041734304000000775772765343521763532070737677375343436570761253725217343107252577400000042407100777775210705070057750007777777777777777676767777652707306716407665361635325333700077054704000007525351734303525172553035253534737353577731743071717053167153173777500000141077005777775615250575257770007777777777777777477773435270724735673725326121633736173000734214000004756572737571613472573257125777273171257713430353521613707316361616176000040060530027777771614377725437741017777777777777767774347361437573467342530713373361337300067425400000401653715257303425357705302537717577617776161735252535241736534171737750000004106700577777777435477752577704777777777777777773337325277462567134312733727353373733400171443404000741745635217753524735737171637773713777717161435353431360512712073577700000004217300777777771603577743077700777777777777774346164775637572126127373633733273370733006721040000000747375735250717134731707031527565703757725363434361655372510717073077400004054075007777777775743477747077750777777777777337357736473402163713731733573537316333700017547040000051617436525377616571743717563577377775737170153537171325052070707147375000000001720077777777777051777705777005777777777776164625653343337373373273273233633737373004770605000004060471753752171770367125752317777537167771617637053436503735371737335700004007427100777777777777476577500777007777777777757735733252373731327337335337373523731734007701424000007147430743717071755707737357707777777771721613537073513752525252525777000000401437007777777777777053577614774047777777777625620707373361727336137337335333731723300037525004000007057717147677072705353434375735775775375717617073527703717173533521774000000400730077777777777777456777403770077777777775733737337353733731737327336336373723737300772434000000447675637717177153652757737073577777777737731743577170750707052503577000000402407500777777777777777251777147770177777777720703333613273363363733732533735233371730005705405000005357177170743416365351271577356377777771653565317217371273735271777704000000050532007777777777777775467776017740777777777737336173377317317331271373373333537323700067007244000004776574173577355734777172357375357775773763737635634375353435370777000000404002710477777777777777777147775077700777777773333337373337237337373363373072732717733700177141000004034717372532516375734352541257377773777777177535735735271617070777740000000025057000777777777777777776147774077704777777736177336374337336327337373273373373323173000716064040000473617577053617527757773375375307177777177737773734377173753777175000000000404330077777777777777777777077770577437777777337333713333631731733633137337317373737270043705500000004775776175301712557765357432525777777777737657257537707161677577770000004040033400777777777777777777774177770777077777777336363377373723733371372735732733631733320047406040000005723573077770353253177273573737177717777753735363753777771777303400000000050471007777777777777777777774077770777577777733713372336173732730373373323733613732737300017014204000025707170014774353043417753575777776777777777777577777777777774353000000040403700477777777777777777777775077743777777777363373173733371373737327373731733733733517000770605400000477716527021775707353771763736573535357777777777777757317777530740000040020070007777777777777777777777770577747777777373372336333536336132733533163363373363172270004350500004000571205710170120775735077170717253777771775777773707374775743070000000004507100477777777777777777777777770777773752536773177337363733737371633727337337343136175370005704244000000775207770052501030437177777777777567777777777757756177777352500000040400071007777777777777777777777777777777763777757336337137333713337333733737137123347436327570007705340040004375301772102161430525071717775363717777777777777777777352017400000002401700077777777777777777777777777734373577777777337723635363727127373731323612547323575716300053404044000004770707170014121043035377773537577777777577777777777775251700000000450070007777777777777777777777777370777577767727337133373337333733737300272561252361756363637400077007000000005771616570612525352527753777777777777177777777777771725364000004040007100677777777777777777777777534777776777353756723673353633773733030735073076777776777735773700437405604000004771610771701020353717677577777777577775777777777773537100004000404370007777777777777777777753736777777737257777773373372333730312163434261677353535737775777773400437005040040000771630777775753757617537475777757145735777777777777774000000400017000777777777777777777773775777777161757777767773353373733437256143737163534372737573777777777000570524140000045775771614361674217343563777777534735777777777777714000004040407710077777777777777716353653677753437776777767777372334330343704307234256352737353773757377377777000770416004000007777577777577535747773757377516043577757777577753400004000005370007777777777777777777777777772777777777777777773373336161720736714737357737537373777277777777777000572407404040007777775777777773731777374777753557577777777757741040000650427100077777777777777777777777473757777767776777767734334072525734716300077371737737353773735777777777400353416050000407777777775777777473475377753502537577777577777361040400407710047777777771657777777777777777777777777777775337336137252721630616737717673633437361773773777777777040770407060400057777777777757777753777575752757757777537717775004161400771004777735256161352535777777777767776777777353637474072725256163073733752773317173737737177377777777777000777054142400077777777777775717777777777175535777536575757534704142573100776150505001050041430375777777777777777257677777737253525236177173477771353737317131737377777777777777400177206414240047777777777777777757405147537777716553577777405256053700007150000000040041001414125377777777737177777777777725207337177372373773777353014307471657075373777777777424057516414340000577777777777777000065217575777616757177707074017770006500000000000010000100210525275777777777777572534333525737373337337377371301201637737373737725477577777777500077701654045042525743452540500400534577777775751777750474057770005010000000000100001050215050105177777777777763773737707333707377273773737525034373731737777771513707757777777740007774006524004000000000000000007507357577771777754707017370000100000000010000010100001000030712107577777777537377373737373736335370343533125373501434143113170755757657777777774004377500416504040434000000000043565737777742570525405775000040000000000000100000010140121411053503177777373773237373707373737336172777043731003471077756740010217717777777777777004137770416165240404040400400043575757775756164007773000141000000000000100010110010100501421052507177777773775737373737371725616252127530047741647077657777435005775757777777777400407773404054165210207040404247177777534004537771000460000000000000000000000001000010121143017107137737777373727373730636163735717753057777064704775357477706135777777777777777740000577771600404444540525041404757752407573752000447140000000010000000000101010011410416105710713577773737373737371671437170763653007004374014707764652574404431577777777777777777400001777773500000004040600000001757777740000477740000000100010012011000001001000121103530171053117777773737330631637436370343743704074774060565735656571606470757777777777777777774000041777777776716350747777777725000004477777400000000101010510010350101041034143501537171070737737773737671477073616177770340416007706560077440617764040435377777777777777777777440000004161753757775352507000000407777777700000010110121013013525201705103501210712507071171773773772731637212525777777075000610477040056775775776504746475777777777777777777777777404000000000000000000000404777777777770400101001201010701210111171013041035070351717127147777377173777077777777777770524041470775076005761474756765777677777777777777777777777777777765616442406146567477777777777777410010101010101010105112530172053171417155071717503177377737373212577777777777735004200420764054065767470757776577771777777777777777777777777777777777777577773577777777777777734010000101010000000000010035153101731713071352513543777737737377777777777777774360404041457704204074543474765677656577777777777777777777777777777777777473043547777777777777777410001010000000000000000001403016171071653161717752177737773637377777777777777735040004160077004702524246056565765656777777777777777777777777777777565173516170034173777777777771000100000000000000000000000105010001711317170735017737773737373777777777777777470040400070774000404004147677775777775777777777777777777777777777777777052710734537575777777777771014100000000000010001010000001061520343435353537017773777373777777777777777777354002404040770400474256157577777757347577777777777777777777777777777777150705010527771775777777775210100000010100001000001010001000140151435357153073773773723777777777777777777004040016016040040005057677757675775734717777777777777777777777775374347070034273417347777777777777530000000000010100010100201601014134303534307705374373173577777777777777777752400040640404004140524775775775777535553575777777777777777777777707535712016531750774737377577777777740001000101020014010011101125030411753411711077737567777777777777777777777712404040160404424240534175376175357563743525777777777757777777777000473417013400301717574577777777777775000300001010010014004004101413061071701077377777777777777777777777777777752400040525024141700434165757075347577577577777777777774777777770071403016701250077073737707575777777777700170500410010010101030521615171307777177757737773737777777777777777777300040000406502524141435716175717537573743757777777777777577777025420350011077006516174771777777777777777750010011041043016161052141034377777777767727777377777777777777777777777174246740440750050343570717521617757575757777775757577777777777503505000000734717217717577717777777777777777161000100105010105214377777577773777773777777563777777777777777777777014777777700050304101034161755705277777757777777777716377777777740300000401413714770737057735777777777777777777770716125252525777777777775777773777717373777777777777777777777777125777777570340102407537161617775417577777777777777757077777777104034000720407217714717365771757777777777777777777777737777777777717637737737757357777777777777777777777777763536535074752050014251716757173565777743757577777777777777535777756010010037053505771771657717677377777777777777737377377777777772536777777777757377777770777777777777777673717176777034347205007061125071307545773777775737777777777777777773777703400007041272125367165341773575777777777777737777777777773773777777377777377377777370777777777777775253747776776777735075703414104025347753731757357776577777775777777777757777410000171005714734177177743577767737777777777777777777777777777777377537367777677347777777777777673677657776773717074777714710034375373312301610307707577575777377777777777773773474040061730037716170773776177177577777777777777777777777737773775737777777673577777777777777777577577777253475677777767771067377337107351171310110713577777775777777777777757752100000173407750777077357717777737757777777777777777777777773777377777771735777777777777353673676772763617767767776776573425736530712730303601013031165375777777777777777777777605200716152570177716534777775177577777777777777777777377377577177777773777777777777777737777577777773757657777777776777571773533377731713101173011103125375777777777735777777777005721712073706136173525347767707737777777777777777777777773777777772577777777777375737777776777437477777677767677777776077373563167723010767753031101134377777777777777777777777701703417161177417761777177177077577577777777777737773773777777253777777777777775377775677777777777777677767777767717617725363353713111771110101410310135357777777757777777775770340147350167701673577707737777757737757777777737777775777677377777777777777277377777477177437776777767777777371716761771737135361774765213031713371431016777777757777777777777774034217236530777143761772577177377577777777777777777777735377777777777772737167767167337677777777767777767757677777343737037635330135771011101215073537353777777777777777777377377041605753053770757177752577757707777777777777777777737777777777777377375777777577737477776777777777707777677767675775277717325136127773012115301102114353777777777777777777777777353731257770177307771777073777777777777777777777377777777777777376377777677673725777777777777437777777777753717327537177735373517157741311210125311613077771777377777777537777735671477730077716571277717757777537777777777777777777777777773717357747777171765777677777777777776777770737363737577373637103016330371770121313530567101777567575777777773777377777167301677716377347571773437777757777777777777777777777377257677777773737777777777767777477777777773373437372733735253127353710534371353101017713533125777777677777777777777777777716771771617771737077577707777777777777777777777777774377777777677365777677777657377777777777353743733737173727773353530343773135161253531277030103527777777777777771777777777777717670777741677525723757771777777777777777777757353777777777717347776777777437371777777737257273737773737373577716303771717170121311727031731135312577777777777771777777777777777771771717377177773577377577777777777777777773727777775763527777777777777373707677777773477737373737336373737377331734770307353177163513177503031253777777777777177777777777777777777072777716177177057777777777777777777757377777777277177777777777732537347777727737777373737737637773727373343523131371307773477353703437313431477777777777125777777777777777777777570707777167777376177777777777777737377577777477377777777677637773657777735773477377777737373737373737367373561343071703477375301713101713167777777770125777777777777777777777777773752537171777177777777777775737777576777773757776777777735737577777347637777377737373567353737371737337373316131371173773537730353330350717776101577777777777777777777777773737775377776772577777777777753777747776777352777677777773437737677737776371777377773777773737373537373537735335731352536313572163531234117077771717777777777677777777777777777777777777716173757777777777773777777777737737777777767777377752777377761735777777733753737373736372736372733363730525373535273173173435137253677777777777753777777777777777767357777777767777577777777777753777767777767735677777777735377172757757725377777777773773773737373737373737373763731731125737331343152173727101057357777777753777737777777774377377737777737177777777777775637777777777737177777777777737736167777777361777777777773753773773727373737373737373373727352112521637336377353116167777777773637777777777377773777757777767527777777777777773737777777775370777767777671771707777777572343777777777775373777373253735373537353713735373736377250575350531710705617377377376177577777377776573577773777767737777777777777772777777776777377777777777777376377777773772357777777777777737773777377373727363727327363736373737337333016177161071737777776356177773737377775373776777776777717777777777777373771777777775377767776777775277717677773752177777777777777253637373377377373737373737737373737373737317373737074377777737252177377737777756717377777777774734377777777777777275271777747743767777777777776375347773770743777777777777716357375777377737377373737373733737373737073034725616527377434361617377733737773737373777777777373737777777777777773707377767767373777777777777712717277736577373777777777777713737737737377373777373737373737373737373737377773773773737773737373737773777737377777777777777777777777777777777773777777777777737777777777777373777777777773737777777777777373777777777777737000000000000000000000105000000000000A2AD05FE" - }, - { - "id": "7", - "CategoryID": 7, - "CategoryName": "Produce", - "Description": "Dried fruit and bean curd", - "Picture": "0x151C2F00020000000D000E0014002100FFFFFFFF4269746D617020496D616765005061696E742E5069637475726500010500000200000007000000504272757368000000000000000000A0290000424D98290000000000005600000028000000AC00000078000000010004000000000000000000880B0000880B00000800000008000000FFFFFF0000FFFF00FF00FF000000FF00FFFF000000FF0000FF0000000000000033273373337373373373172177765677143477212657777776567776777777747077777777777777777777757777754757777777777777777777377777777777777777777777377777777777777777102136770007770000373373373233373373372173613777767773617717725777776777777677777777771777777777777757777777707746757777777777777777777777777777777777777777777777737777777777777752412576706033277337317373737237337373303763470777675672730737677777677767777777777777777777777777775777740447575677777777777777777777777377777777777777777777777777777777777777771252637616373333733733373333733737337373137377565777574777271756777767776777777777777777777777757777706070047565477777777777777777777777777777777777777777777777777777777777777777701043777337733732737317373373233737337375236377276777617677374347777777676777777777777777577777777405771065772577777777777777777777777737777777777777777777777777777777777777777777300333733732733737237373173733737363373535275752777775367377774777777777777777777777577777777404177774065746577777777777777777777777777777737777737777777777777777777777377777777770733773773373373733273373773733373373733123375656767574737377767777777777777777777775777406546746750074756577777777777777777777777777777777777777777777777777777777777777777777773732333337337333737337333233377377373737734373777776777477737357777777777777577577777560654257757750475656577777777777777777777777777777777777777777777777777377777777777777777773777373732733773337333773737337333372733737343707777777616577737777777777777777777760475604047770640465756567777777777777777777777777777777377777777777777777777737777777777777333337333733733373737633373737337376373773737373770776777777777777777777777777777770045253404047475240434756152767777777777777777777777777777777377777777777777777777777737777777373337273373372373333737337237327337373373737377377717777777777777777577757757774040404645256561764571656747671374767777777777777777777777777777777777777777777377777777777777737333737337137337237373733733737373733737373737737737777777777777777777757777771404250041435614044406774475475277635177777777777777777777777777777777777777777777777737777777377337273337337237337337337273773737337373737373733737737737777777777777777777777642404040040404044000447770477465635267252477777777777777777777777777777777777737777777777777777773737373737337337317337337333733737373736373737773737737777777777777777577777741450404241000000007440777770475747475257353701777777777777777777777777777777777777777777777777777773333373337337337336337337733773373373737373733377373773777777777777577777704067000014104000000740067775740474747765624721676577777777777777777777777777777777777737777777377777373737363733733633737373733373337367373737377377737777377737777775777777770474757645650000000444005776563704657452777752567312047777777777777777777777777777777777773777777777773373337373273733373337333727372737337373737737737737377777777777777777774052474775347050100557000477757447750076544347772524677300677777777777777777777777777777377777777777777737367737373333737377337373737373737373737733737737777377377777777777777006440424675747446577604077774607446774476564342477717077731257777777777777777777777777777777777777777777337333337373733733337237337373373737373733773773737377777777577577777404704250450476400247400407777405440045704056547707047677404673025677777777777777777777777777777777777377777737377737373273363737373733737373737337377377377777737377777777777400474040405246750045404040757040640045426504674763736342567773447312107677777777777777777777777777777777777733333333737373373373337337373373373736737737377373737777777777777740045404040464144244343440577644044040060456714074454775256347477256256313077777777777777777777777777777777777377725213737377377373737273727372737337733737377377773777575777770004061604040564044047440777740040000444040444654565275677365267347356346243066377777777777777777777777777777773333737721235337333373733333737373737733773737737737377377777774004240474104340404004750775674074004140000040407706565477767537124765674716527135677777777777777777777777777777725217470773733733777333777773737373733377377373773777777577774004414043414004770040047777465047504070400004074757744656565777652532126167653652463150767777777777777777777777777737773773470723730337773333373737373777737377773777377777773400004647751000004740000467774164074000500000007404777714742567677777656116347747677167273705777777777777777777777777470163573777561735323577773737373773373777373773777737777740434004041601000016400005777704157700414000000040477777604756565677777776617307247167734203630357777777777777777777773777743675273776727173333737373773777373737777377377777740000470004351140004440007760746576770400000000004077777775504654747676767477765325727756565743070727777777777777777777163572777437577717777637753637737373737777777377777777770004047416405040000400005774054056507440040000044424777657652447565257674767646777430347656376347632531677777777777777777743353437777252773537656371737777777773737377773777777000000507471401100000400776140424075600770040004000577575750657006565647765777776777777737274074771643673134777777777777772777737125277777476777377777737377373777777773777777777000404404743400004000477547465140005405640044000477764774250756506565677767776747677777701277160677743466330147777777777353473777737132537777177777777777737777377773777777777777000000040040004400057706704100000561404040000457760536047740640456474767764765677676767761216770043777114636334176777777737777373777777771777777777777777777777773777777777777771000040004050400047777444410400004044000000057671457654565340477047474356777767647677474777610036764647673652437213677773773337773777773777777777777777777752544644647777777777771000044004770004774340007410000400404250747775440675000044000477447437271667777765777676777773531212716471673707243177777377777773777777377777777776756040400000000000657677777776000004000400177454740001000001400404777777737400770000040404770567473475375677767777656777767470712616674747657343063337733773737377777737777775250000000000100500400040147777771000040000577407604044140000070000077777414440475010000000077774047747276167347767675675646767677251213434717274767377777777377777737777777765000040500725656572571414004004537770000044716565604500401000000404005777750640057105000000447775704776775616735636567767676777747677767343732667477356733776177777777777777775000400070775777777577677777525000405770000004774041406470700000070004064777740040247105000040777770400775677671663570747777676777747477774761617136346657777377373777777777775000002577775774757776575656757777741600570000004704040414040500000440005074477140044041100000077774400043737765675743632342771656766767665676767616137353676177777777777777771400007777656565777773577765475647577774140470000004042407404400000040004774405676564004100000007754000007377771777767765656353077674777767567777677776530343377377777777777777040007774747775777757056175357640757675777701040000004040447340050004004474040065750400471000004750400007777777777070756565361607603436747776677574767777677337777777777777777740000747774145770775311110535375744654567775765000000005040047740400404034074161440675040044040757440000577777777777776372765677761743613716777676776576767464777777777777777770000777744776452577525343010105071741650575777777450000040400440404000004465406560045640040000777400000067665677677777756753774360767253652716056776776756777776777777777777777000177543474453457757115115014100165665676565657777000000040040040000474047500040045000474004757400000054745064040604656777674377574707675247273734677777677777677777777777777100457756744045657775315773701211400157575757575777777500000044000007577404710400005240043777574340000747664646476474464042407777406373465436734342437147677656665677777777777774003776054656161657775771775351521014377777777777565777740000004405047473404400000044160447616504000044747475675656476566546404467770437327657474773432737167657767777777777777000577056404047577757735775571353510015777777777777775777710000000777407446100000000074400775404000056767656674664676474566474424064776035307276676567476163437277777777777777740017747475675774757777773430014116171077777777777777776757740000044750605014100000007040475040400047747474656477475656666747467464046475727307135256353617253617477777777777771004770747477577177777775351117113105105777775357757377575777700000004740560400000004754707504000005674767677777767767677574746746546400066435332523725665765670723030777777777700077775777177177177777775071010141107127777777717777777777757740000007704071000000414604740400004677777777776767777777767676774746656464047663733703071725661671747677777777774007774775777176175357777711075531305105577757175717577777777777700000045704461405040405714400000777776776776777776776777777776767656656474040561733373030721765467253677777777700177577777177535377777771035312150110127775737370753517775657577740000074400040060407740400000777777777777777777777777677676777777765665646044642737373372163127345765777777770047757771717717777577777701515715310300577777754153534775777777777000000470004004047754040000777777767777777777757777777777777767676776566564600470733337333312525272567777777500077675777735717573577771103031710514100775771731356571717775775777000000040040405777400000077777777777767676466656747477677777777777676566564640463737337173733321252777777777007775777535707773577177761511430713012102777775534317775635734775775400000470400777540000077777777777656404405416414707407460656777677776566565604460737033363737373303777577700077577753771717577356177530161151715351057535773515777711577475777770150000405777400000077777777776400441753777111373511701454206467776776506746400452337373333233337337777775004777777775075777375711573117111214311110777777150377717077775777577704770000044540000077777777764004167377777710535751305157335501044677776640656540663733337335373533777707770077757571735717575777771056111715315707017717157357753471757477167777700770000000000007777777764000535357737773131173315121717533757100406777746066400473372536333233633775077500777777775701772535777777157141215217500007777357777413575357477577577505770000000007777777774014171717375777771121753121525733513317711404776756164640407333337337333737770770007775777531771517573577777731315131530011075777777773777307777757757776007770000005777777760407773131617737737131113351151173153051713771004277674674404633737333733733377507700577777717057053756357777777141717077501000177577771715715757575677777750577770000777777764053577115171353777753010377101217351313131353177300467764067404373733163352337770077000775775771317161715777757757170717537011100177777775735777777777575777700777773477777777412537177312135357377331111311315353311511050117357710007777446044333277373337337700770047775777575017571777715353757175753501070100577775775725771777577777577705777747777777440513537371117131335377112117311130357131311317153737737004767065044373333373337377007700077477757353573577775121514377173750351010017777777777577475777777757775077777777777740713712575730311435137313111035301115331011011503717113535006776442407373737273733770077004777777775357757777531510135757775357507103777777777777353527577577777704777767777764171371535337111131303531713013131134337113135303171701711777000767640433372333332377700770007717575777777777773010034131777777773101157777777777757504153777775777705777577777517371113537737312531713433111015131111517111111153531131537377500774640673371737173377007710077777777777777777751711010415377757575177765743577777773534747777777775167777777744357371703111171711311111053131037121303131313012173111103577373700677440173373333373770077400777577775737777777131001011205777777777770171715347777741417175777757760577777774173735121153737331310121101316113753111151111011717310301773317577104767046373373637337710771004777777177575377750100100501577777777777417501534157775350747777777777157777777413535737113131101171113112111111353735103134353131311111173115353777106764413336333732777407770007757575377777777171010013101057777777701777701010015735250153757757774077777734171733713141053171035317313134135371773110113713535312103171301353777107762437337173733771077740017777775075357777171001075317137777577577775340311025775340757777777754777775431311753711313111131131357717131031737777131713773771111173111301353777006740437333333737770777300077577177177777711101005315014577777753777530111400537534110777775777417777743535371371731111210113101373311111173573731713743157131107111311535253777007643337373633377747775000777775715257777170101173503173777777377710153701300753515257775777711777770311317137373110301131315377315313035317353121071317337101311301113131757775076073732373373777377771000771537771177777170053510150157777775747105341141101773705357765777647777541735213530353311110110131117331111013737313513135311577717311312134173777770065233737373377775777770000777575756177777710153100050357357761710717101370065757165777777775177776171313533171353313131311073717121313103533512153535313777771211115135777777775265233333373377777777700004756377375757771753010010315375775110531717161517737357737775777507777705353531353131311317711171113731311111353713111213130777777771130537733535373700703507173373777777777700005304735171777147710105001435047137351741410117777575737575177752577770537313131211312135771103105371153112131331301137173535313131131013531151317577146742333216337777777777700004004577017743105310111011161077505301101014357777777577767777741777543717135171131311037771111301173313111101711112113173313110131117773171314317177106374247313277777777777500004000537417101005710001071540473525357100017761775777577577775177777013737133133111311717373011131153113131317313117373111111311010177113110715377537014377342061777777777777000004000753504110771011353561317751050012177757175777577657777507777701713533113110311173737111131013110771101777101735313130110131137713510351351737770673434356167777777777777000040004775311657170777410110477777535757775777107777755777764177777071713435311131013353537301011311053713377353537531110113013113571713135135277577700343473616377777777577777000005000617571777577751757751177777777777777057753576777775517777741313531316133171353133531311010101373735317337773111313153117077731105137135173777506363061617777777737277777400061000425655377777701777765777777777777757053577557775700777777525713153131531131352513531311010153735737317135371301113353317777735317175735777777417163563607777777777536773000057000441657577771777777104777777775774777770747777560577777770533171317133113113113170171031311253533135313135771135271315351753531737331737777770277352341677737757777771775000007500044753771417775750407777575777577553575777716153777777437117125313110312101353113017125135373717131351177313131101121131377373511153575777717737735373777733777777777737000000771004465753507770142407777371753573747177777450777777777477313111313531111171303111311130117371335311301257011131131111101577711312110313777003733333377757773437377777777140000577300042571153750054465775771770541177777040177777777750771713131713131301131153011311110335371313711311317131131011213533771301111311141777433777727333773373716777767777300000057535014304351005243543477474071777777404177777777777707113153101313101133413111301031017173134311311131313512131371353571311110130170113501373733737773477373737177775777740000007777535011000464444644450517577775040435777777777770771353317130113135311311301131101737317331130103535353335317135373331112533511113577127327373333373337273737253736777735000000477777735315141615353777777770404001777737777777770171315213135311135311211310101317317311113131317737335317135131775112113513737713174007134377377377737373737370735735773700000004057777737777777777777744040005777777777777777561335313517131313131311311131101775717371311111777717135313131577737113533511535777771216337257337233737373737333723527377770000000004056575757474440400000017377777777777777777057113153335353501773531031113177573313131310177731131131716173777713513101313073777007634605327737377373737373773773372537177700000000000000000000000000567777777777777777777770731705315113131357773113105311577371311210137773113103111177777531311311131115357770773561362533737337373737373373377373736371773521000000000000041074777777777737537777777777704711131336317111373535351331130375775311131737353713113121157777131131131112101777506167374356377337373733737373373373737373727777777770707134373777777777777777777773772577777707731141111113017777331011170117131177375777531313713113113017737171161135111101776072525276377337737373773732737373373737373733077777777737671777767777777777777777777777737775077713135313111357735171371131433531357777713105111135311301057713131113533530177717352527525237373373737337373637377737373737377307777777777776537373777777777777777777777773770477713111310131373713011013113353101771337711131213733131111377353537377751111771477777352161737337372733737333736333373373737337737077756777777777775375777777776777777777777730777353301531171171311317311317313111035110353111110177531301577737353531377777770777777777373373737373773737733737772773737377733737343773477377675777737777767777777777777777714757353131171121171711111301735353313131311353131131037371107777373313110177777477777777777737373737373372733733733373373737333773737370347374777776777773477777777677777777777433735317133131113131031311173573311111131111317131101353131377735311300115777750777777777777737373733737737373773377377337373773337737377333433073777777777737377777777776777677057131713511101017131110173373331731307113010731711311173537777131130111217775277777777777773737337373733733732337337337737373377733737337373737352352777777777777777767777777777037531310313110217131313177171731111137311111531311121177757733131537311777765777777777777773737337333773773773737377337337373337737377337373737377373437777777737777777777777775013535311110111371711177373371373107173531037171311110171317531031777711777077777777777777337336337773333373373737337736337376333737337373373373337373734356777777753777777677760713131131010351131373717171331113533713101177317131131311113113177531777707777777777777777337313723337777337373637733737737333773737727337337377737373773735775777777343777767710771717113135303513535313173533313177131137577717173531521301315737777771777777777777777736336363163712337737373733773733737373273733733637736333737373373737273677777773737777740773717353731713103131353113535371317713512577717173531111101337777777747777777777777777313777176163737337337373773373733737373737733773337337737373773737737353736777777771767760753507353531113107171117103531371317773713577313537135311105777777770777777777777777776363737777752527316737373373373763337373733773377337733737373373733373737171777767767173100753535373531711131313311113171131135353151253111107131131137777776577777777777777777777177476377377756733173737377373336737337377337333733377373727737277737373736161757777777400711535313121107135351130107313121777315305351030117353113577777717777777777777777777737737134347777373567133737337373733733737337737273377337373733737333737273737373637777677700773535353131317131253131117371111375311311371110017317101777774777777777777777777777476777773725277777376753437137373733772737733737373372737373737377737273737377373752735637740771311353111317131311101017331307737715341351310017131137777077777777777777777777737137373737737167737735273327237373733373733773737363373737373735333737337373337373373433477300777131313053535351353111735310117771701315331101617135777547777777777777777777777777770737373777373477777756537430373737373773377373737373737373733773373737377737377337373307500477711111301313131311333531311777173171537110101777777540357367777777777777777777373737677577777377347727737473774343537373377337373737373637373373357373737333737337733373733730077773535353711171310573711113777353112157110077777734376347377777777777777777770733437033237377373737527773767377727032353337737373737373737367373373737337733737333777373737370006773131111353011131713713011777353513773110177770457436343436177777777777777737677777747537377777773716161777773777757273733733737337373737337363373637323733737733317373737371214375313531311317565351311177177311357775377700063767757777716252773777777773437716577372761716373777737373436747737725252173373737737373737737373733373737363732373637327332737000435713111131537773121013777753535777777550475353617676777271634343434777777777737074771772737373737377773713707477777777072373533737373733737373737337733733377373337337373733730000757777577577575113577777777777776740247677761707375675674777616732617716577777370777777747743477373777773737343773777756172733737373773737373737333733773337373737337333737373700050577777777777577777777777777010747777677767765271671676347774770727737777777773434743737373725361737337773777074736377252521637373373737373737373733373733733733737373373373371240441675777777777777735614045676777676767776777763434354776076576577777777777777737377777777777373777773777737737777777777773733737373737373737373737373373373373337337337337337333161434565747475656561616377777677777767777677777677637257777677777700000000000000000000010500000000000092AD05FE" - }, - { - "id": "8", - "CategoryID": 8, - "CategoryName": "Seafood", - "Description": "Seaweed and fish", - "Picture": "0x151C2F00020000000D000E0014002100FFFFFFFF4269746D617020496D616765005061696E742E5069637475726500010500000200000007000000504272757368000000000000000000A0290000424D98290000000000005600000028000000AC00000078000000010004000000000000000000880B0000880B00000800000008000000FFFFFF0000FFFF00FF00FF000000FF00FFFF000000FF0000FF0000000000000021312121001212103012101120511213001003031000000000001001201000031434130127125003036131617112161707121633525212434101612140103000000001000010000001000000000000010000000000000000100102120005212143012525002070011030101770000000000001001200070431030521125306171134303436170643125351431717043523421052136001002010020100200001020100010000000000000100000021310316114104031050307010303401035203003073000000000001002101000031071430161771407072535353717341752534363761634352153525252411700000002100000100000100000000000000010010003000100114211021201343030103430100312121010301710000000001020010001007007021316161302717353434371734367377371717173525257616137171360000100104002100007000000000000000010000200000100316211203104250103016101125061614121201437600000000000103003004101313534313177500717373535773534717535377777174071301216516165170070600030100000000100000000000000000001000000014211251007100212107012306121001303410301371000000000000001001006124252134343137437775373737777707737775375377370477777532735327124010100000001000002001001000000000000000001000211230303112041352101214130106121071211037500000000100010020102043513353437177703753737753537773477777377737537563010103471634716412520210121020001001000000000000100000000000001251014304204120016125013016001413001243772000000000012001012054303614353717371747377777377777347777777777777756357777777177171610252141060000000000000000000000000000000010210130303030311006171212130305210121341301317710000000000000120010025351734353777770777777777777777577777777750602004000000016124371675252161010410002010000000000000000001000000000014316100253000125050030301204120300341377000000000300100121034070361373753777377777777777777767672525004241447420704046004100400435353070212000400000300100000100000000002100003030310351204352121217050341420150350337770000000100010210103007171375357377777477777777777752705464464604766640446464644606460704024347125001000010030000000000000001000010003016100021021001214130103030120013021037577000000012010010121610657375737377777777777777774040644466567600406400040006000000476746424400212534120430000000000000000000000000003000310313521705241212016310161003503143533770000014010030216101341735737777777777777774740404647460406040042040004620040000000440240467504040025000000000001000000000000000030000000021001001200214316110701030402143031777700000212010010107161347737737777777777727000606676764000000047047640000444644640002040000466464040020041200012000000000000000000001010013523121311041310112530303042112035373770000001010201034312170773777777777777600444664404040070416000000750000000000000000046400560000046744004200001001000000000000100000002000001000525060120430612011610015217135377700000520001121011071737777777777774040476767400000206400640425675200000000000000064000046440000046767400101000000000000000000001201010043121312121124131031215201216025125371770000024012120161637353477777777770464676440000700004740400777777700000000000000000007747600674640000446740002000000000000000000001002000000520012121006030011211201007021317377700003070010121311717353777777524476777600067046404006730331777716101031000000000000047777704040000000044664014121000000001001000000100421312113041706011413705205312101350717373000104030120534371717347777444676460420000464006421171531537133131313133130100000000077700000006740000067400002000000000000000000030041000012241130001321300121130404034333717100000603016113137173775775647767400047400470000703417133113313713131135313133100000000160000000000000650467460010000400000000000010000020013041302112430520712161033007135353637000131430314343537371737674766765000420476000065713337113301311317337333737313110010000100000000000000640046540000002000100000020010001010241101306110431110353125013002537351710000161410331353535377747664004067607400404777521111113101353313337737373337333301011300110100000000000000006620100000000001000100200020001302305112003161212102533404353353737000137061371535373777764677000702444660000077760103131212133337311773737377717310313130130213011000000000000476400060100000000010010040010001300121216142125350713001025335371700003703173173737777767777640046740000470527777012112101317352710033773331773001331371011011101301113000000006774000000010000000201200121020305116125000351210330107124137173527000713547357377777777746464000006460000677777730113111203131311300013777373172101073131030121301313011200000004674004000000000001000000000100121301031250215214136103106117173531001733717377777777676400000075000000057777776101313311133737337310003777377317271373130113101310312111100000004460000002001000003004210000016121031304071211213012507017373617000371753777777777767670006746460000773737377300131373733773001717000003377733721037310131213131213013031300000006740000010000001200010003030301007061002121025341703300737171700017537277777777777767400074006777377170737735013137773373100000330000017177773103373013101303031311301110000060474000300000000301000200100001031131121417017110303114343537373016333771777777777664000066470171331333331737720013177773770000000730000002003773737330003121131313331303310000006764000000001000000041002010007060021520013012730707210073777771017533777777777675000000002533131737173737337100113377773773310100110000010001043735300101133133735371101210040047764000100000030001200100210131135132106107251013101777777777073713777177777747760066000173307371313331337373000311377773777770017200000001000331031000031313737731000131012774066400012000001000020120030000021012010612310123716173716577717171777717777777776006500077317133333373733737710013133777777777310031000000000131303130001313373750000000101304600474000000000000007010101001035131215300114313501210370712530777373737777777666440764617337333017371313730333700013113370737777301170100000013131373010001337377300000000310000000460100001001200000020021020012021210706030612353017710712531377777777777777400064001737131373213337331371733000013013510437377773332101007770131343000001777371710170000030040476520012000200041210010000101215141210013011215213710131253075777373717777760000000073733737371217133521333770000100313000347777307310207777100600010000131777373737310013104607764000000001000100061201200021213030300705321521435207701347777777777777766704760007333533733335313313337173300010010312000103773731031177310211111700000127773777777001210070067600010010000420210101000100141203150430120512121370070077131677377777774776007461033733733717333335317133337000000013113000053717731003375311303373700003113777377737101004670447400200000000101020000300303030142130433130717037001701700771177737777766000006043173733733737371303033525373000000013113131313331031177731311153777710003031000077733714000400642000000000012041012100000003152112103050031211770070070077007377777776400474404333733731733331331313132133331000000013131130311213037773131333377777771311021001373773000000076410100000005001020000210100142111250241307125377103107701700377737777740000060031753353373735337130303013353530000000011313311131131377313537377777101107003112121777300600027640000010000020303012100020002112341304170314313770077073037007737777766700067427533373377333337137131313352333531000000131311333123537373313137377777373713103011100070067600474600200000010100400000010100011250301202170307317300701700700137777777777400040442153773337371333131303052317121212100000001311131133137773313777373737737717133313100040047000674101000000202121030120020000341330701407035317770073070077007737377776400200000053333373737337173130313313312131030231201301213523173377111217377773737737733111210000645644046600200001004110102040010100400301010300313521737205701701701773777777460047400601317177373313713313371361371213002113173130331303353337733333137373337373723734331001000066427641001001200210602010121000020330703431140703171771031063077003757777767400246407643737337353733371711131331335213112030217313071301337777310103123777737337370330101001000400465603000000001201050020000200410010303072121717373702560500700173737777767004006046013537333313531333330731731213030317131212353303737337717313131113230717735350733100101000000764000300000001021210101210401213431103100431217177053017037007173777774676470000700533737373733373171731333131303530303031313210313333713731210130311010313133333130100310000064003010000000702500002000000034003070710613353737301300700700173777777767406464046653353735331317137333132712521313211313035311337373731217371000000000000000000103010005600054404300205210210010012000100243413103111210417353535007012071037373737777640006700004217313333737333537317313131303011730301231230133133131213773000100000000000000000420064046676030535301001021212010142041012200710217302412173730300710300435377777765600056400744737371713137313317335313031713231313331331337137131311337777003500000000000000007406400076434777777777773500016030100006015011211210143371217007013007053173737777767000600064072531333373713737337333733121311030310331217133313131337710001003000000000000560040670004677777737337373777353001002000413421217307034215071710700700700317353777774764000052006653535353373373333733531353312133135337131333313131353770000130101000000000466460000600247773733373737337336165102500601200121210117104333173001030042143717377777767000006650040033333371337373533733733313713103033112173131313121333000177773301100000016400077404444777373373333333333337326100010301430007032121214127171070030140313035377377764000000600005735373371737373733731717331373131123312133131313133771137777777721300024600004660067673737373373737373373333107202410421070117110710433512103035000007161737377777400000046460463533135333733733533733331731333733131313073121131373377777777733131110400004640004767777373373333333337337312301401203007012121071243341253070100702317173537777747600250000000771353733373373373373737173121731353533131310076037177777773421713131201240007000067777773737337373737333312330020160500707010713031041371343134310505303173537737766704640400066121273735337373317137333313131373333353031771771002777773770001313101000000046146777777373337333333333327206676160120121021071217070250361343130700305352173717777576000006700041111353337333735337317373735303353131331377777770017777070110313131311101000476777777737377337373733367764747476764106161403031013004335170307071021734317353773776640047606000131271237337373131733737313131313337121035777737701677700016131313131000300006777777773737333733333376767656476747416010030317073701631433031713125052131635373777774000064000003011313533737333731373137337333537313131777733777740100000013131313000310000677777777773737373737276767767767676765601243400013010301433143431617006316171735377357776604000067053073133353337353737373737313533313313137777771777700000000001313111310160647777777777777737333337770746776777777760341212103701711600523131613037105317034377177377756700000006000161053371733333337331337313133353130013733137770600000000000012301316777777777777777777777777575652105274777677740250400010301271073516161343500612527173537357477764600076400007117373333717373537377337335353130017373707310040000000000000311130676777777777777777777775252000040705010677764705203000711635004301235317171253171717353717737373560000640404771331371713335333335333533533313121231131313000470000000060004003447777777777777777777772524040406170707061057776124100041271037125371521612534247373717377737477777744000007600135371333737331737333733313113131001137171057200674056000400067746777777777777777777777440442400004070707165207474030000035005030425231713713716171753777777777777777747640040007131311713537333317331717333717121021121200064004604600000005666777777777777777777775652560404004124143507175707074000430037133516135353071253714373777777777777777777746700000717135331313137171735373331513331101000040006500670067404204467777777777777777777777765646046527424470743707070706021402005030150243534373535734637777777777777777777777746000024373313513173537333333135133371012121000675004646560042777466777777777777777777777764564654746440407065254525257750000010133512335061350353731735777777777777777777777777774404400071313313113313171717133171707000464064460067006000047667777777777777777777777774776565646142400041525273535253774020000150215307073371717777777777777777777777777777777776767600000113537353353313131171060000007604700000040047444677777777777777777777777777777777777746440604061615067617057734161202335721607171737373777777777767677776767676677767774465600007117353371313313132006504640000006000000007766767777777777777777777777777777777777777774740402525637141747257700014115303171617177177777777777647777767677774747766776777464047776025335313171317750076467000000000666040666477777777777777777777777777777777777777777777404041653450772535777701202721617125373737377777777677777777777767676767777677677777464674001731313137004600000046004000007777647777777777773777777777777777777777766676567777777774065257274357707770205013171735205371777777777777777767465445465446506447677676777774646476775210476400004762000676744664677777777777737373733737377777777777720456446474676777777075257174717157750020017121735373737377777477777746476766767466746652704667677677777747647465467674206476740447464767777777777777777737373773737777777777720456444747665474777746165705253676777701012735273707777777777777777476777775777676774765644470047767767777774776766746465447464764765777717777777777777373773737337377777777774046646676765646464777707560725771517770207001735353567373777777777476777777664765656465644767474000767767777774777777777767672574567773777777777777777777373373737737377777777004654656767665646444677563570573472777750106173703733537777777777767777747654765647656065644646476444247677777777777777777177576727137777737777777777777773773773730707777777740076647676767664746404477562537473557777030300353571743773777777767777774764264424244406424740656446765647767777777777777167707717536537773777777777777737377274340577777777774006656767676764746442460656156743143777752505213733373353777777777777746466404402465427650424074240474765007767777777777016750770773753567777777777777777777414121437777777777000765676776767674644644040771635356777772010321471747374777777777777764670404720744067406470004656560464767407767777777756777360777753763577777777777777777616034103077777777740056767776676746465464464640775774357777417070521373317377377777777767464400004446700467400656706606474240767647777777777007757177777761742577777777777777765010121410777777777024667766777676776666464440460734357777770203030527374737177777777774760000464420044474646744642474577065064777427677777770757767774752577173737777777777776121216030301777777747567776776766766674400000000047577777774010141430117373777777777777464404600002466067067476464747466646566540677647777777652775775737377617756777377777773010104101050167777771676776767676677675000000000000077777772000252020343737173717777777746400474606444044040046440046046147416740670477527777770077737737057017727737777777777750306030252120177777647656777777777767664000000000000777777410010000140143777173737777776564020640407600000000006056424066706465724470677477777752477747573077077177017773777776100101011010520777771657677777742460000000000000000007775610000010100212073717735777777746406440060440474241200046460404744470724477465676477777007077773777107716776777777777710342125203021013777567767775402050004014000000000000061430020100202001000173733777777776400044246404604665424000004656476467656452742564777777774747777771710637777517737377773020105010141101257760776776020605224707421604200000000042014100214010000057735753777777747400240040604707466456000004656647647677656740770774777737777777737731777136743777737341052120302124210777756777040414524570617461670700040000010020310010010000233773771777776046074740044424464467601000004656465640477600700646777777477777777777703776537771717776121010150510110703770777740016724724256425641474700007001250100612030030041753773777777754604464600606406470440464000000647467042763476525756777770777777773373377733743173733753403430212030201057547760017605434165070520742434760400000030701014007000303771373777377660472000614040646464706072000000046746174147616476677777777777777777777777775737353175200300101001410102736370056760562506506076474257425700470010000125210300070473775375777775474444044644004044046440640000000037777776747477077477777777777777777773777372517377737500010217030216105756561614163416470616052435607424760670030107100210061031373737377777764600064000607400060076745676100000337777777777477477777777777737777337777777773617137737214210001010012121770047607407430434075250461643560704740042007000430061605375371777377740046706064464006746406046004200004777777765406747767777777777777777773721377353737753744001070120010000167043650743470463434424427074346165647301010301012040301337377177777777460044446446060474404006774761000710677777767677767757777777777777777775014777737527377700000012503021014352525270343434341643430745616434706574000250002010071434371737357377774470604650654042464240046464047100671077777747567476777777777777777777733133573573577773700000000104102034607470564742434060743465261653461656771210303010061021037177173657377376465624644644644004600424065246301277077777676565777777777777777777777737773173773771777560000002112150135616526160743434343461605652470743477701000000010071034037353717377777746564406760674240647407000464777040577777777476167777777777777777777777377777657375377737140000000000212461616507074340656146165770470475256775242101012061025031173673477737377706400676404604404060244052677765330777777776774776777777777777777777737777771335737736770606100000301005356461647006165216705256043063424077721014200004016112143717173437777777446004440604006000444424645667777731777777774076577777777777777777777733777776521617716165752561614161764253461605745275641674252565147077777521210121007212052373477357735377737164002404656444646460464644567777731377777774676777777777777777777777777777737537703353063773777777777756470343420204025250614052066340477743050240103001413050173435253537737777470404740640065646444040606476777713737777677477777777777777777777777377773712501705252573771617617435607444652547525000605256056140077777161211303040703043037357525277773777777646466440006646000600464650477777347776774747777777777777777777777777777773070372525247075271771342570442700056200605670524203616047777706134124050030301303435253347137171737375744000024454040040400044666077777777746776777777777777777777777777717777773070503121437735370377070374240642005470725052535654007777770135216113200414160521525257077173777757367764560406600740766400004506460677777676747777777777777777777777777377777771032506161435370357071470314040404200404024242400025747776120417136141212030130523347307077353737375737576600040464644442464076406574477777654777737777777777777777777777777777325052317063536177217302171634000404002104000500776567774116153212512300417012012157071707134735735727573744406400042000047402440656647777777727777771734777777777777777777777737012341420707253521771657061010400004040612570674657656161601205071614043121705214307030613531731733563773777747604740000046440604644746777777457371777735777777777777777777777015250123505371361171210303112521000000040442467477525252121125303003300352501211211707616563434735734143353775347564600240400604004246746777776377771735737777777777777777777777210270503607071725275346160703071300100000640507472420105025001617141000212161205230611003113531612527375371737736165644740664074644756357737616717373530777777777777777777771705251030340713521735324215130141024070210420170703010052021103161212300615214305301616534707343071371617136173617056577734765416567173635371771653734717371747777777777777771021030343435025252170530501632070212140305021017021050041201104216113434071120121030431003001310317070140617535353737037353435373777073717135275347377137343527077777777777777761525350343025435316172573061053071250210121003021103030210142131030603100016170143413034703424250313136341230370317124437253734353771473716735337047357135307134217537777774777302120352171302525312533070163010010304250121001421701000710300070113143043012170303430001300711214242510061535035617102517352535271243170711635720735234363537004730737737137750714170353070434316173525306107071241000121412121121030400030171034207104216121034130143424070125031311206112303703124253734353073525216171277170142537537153616173071777343046321033034307170713735252534010303000134252102001016107002103143003031530201012507103052000714036130070525053614341716105252531617343704352125217356072530703617100717173773352010507143530703024343431712125630503030000212110307212100012502125341403014303611212143043070124112532132120003310321213407171613071717061353535343314173531713037060703273070316030302100713571435353431617001430341071050500610010510300410341301231343000501201252103004036434350152516142505251525070243061707034370070343070347025252160707502431705347171404341716170343242703421743524343070303024212121210712030012030305251425316070341705214340724110121030301210003121212103005317130713537007135307135310437135313531241352130312120030121213071735071353170312100301010101001210101030301000001010121303130000121030121030030434300000000000000000000010500000000000094AD05FE" - } - ] - }, - { - "Name": "CustomerCustomerDemo", - "Data": [] - }, - { - "Name": "CustomerDemographics", - "Data": [] - }, { "Name": "Customer", + "Container": "Customers", + "DiscriminatorInId": false, "Data": [ { "id": "ALFKI", @@ -1350,6 +1282,8 @@ }, { "Name": "Employee", + "Container": "Employees", + "DiscriminatorInId": false, "Data": [ { "id": "1", @@ -1542,258 +1476,10 @@ } ] }, - { - "Name": "EmployeeTerritories", - "Data": [ - { - "id": "1|06897", - "EmployeeID": 1, - "TerritoryID": "06897" - }, - { - "id": "1|19713", - "EmployeeID": 1, - "TerritoryID": "19713" - }, - { - "id": "2|01581", - "EmployeeID": 2, - "TerritoryID": "01581" - }, - { - "id": "2|01730", - "EmployeeID": 2, - "TerritoryID": "01730" - }, - { - "id": "2|01833", - "EmployeeID": 2, - "TerritoryID": "01833" - }, - { - "id": "2|02116", - "EmployeeID": 2, - "TerritoryID": "02116" - }, - { - "id": "2|02139", - "EmployeeID": 2, - "TerritoryID": "02139" - }, - { - "id": "2|02184", - "EmployeeID": 2, - "TerritoryID": "02184" - }, - { - "id": "2|40222", - "EmployeeID": 2, - "TerritoryID": "40222" - }, - { - "id": "3|30346", - "EmployeeID": 3, - "TerritoryID": "30346" - }, - { - "id": "3|31406", - "EmployeeID": 3, - "TerritoryID": "31406" - }, - { - "id": "3|32859", - "EmployeeID": 3, - "TerritoryID": "32859" - }, - { - "id": "3|33607", - "EmployeeID": 3, - "TerritoryID": "33607" - }, - { - "id": "4|20852", - "EmployeeID": 4, - "TerritoryID": "20852" - }, - { - "id": "4|27403", - "EmployeeID": 4, - "TerritoryID": "27403" - }, - { - "id": "4|27511", - "EmployeeID": 4, - "TerritoryID": "27511" - }, - { - "id": "5|02903", - "EmployeeID": 5, - "TerritoryID": "02903" - }, - { - "id": "5|07960", - "EmployeeID": 5, - "TerritoryID": "07960" - }, - { - "id": "5|08837", - "EmployeeID": 5, - "TerritoryID": "08837" - }, - { - "id": "5|10019", - "EmployeeID": 5, - "TerritoryID": "10019" - }, - { - "id": "5|10038", - "EmployeeID": 5, - "TerritoryID": "10038" - }, - { - "id": "5|11747", - "EmployeeID": 5, - "TerritoryID": "11747" - }, - { - "id": "5|14450", - "EmployeeID": 5, - "TerritoryID": "14450" - }, - { - "id": "6|85014", - "EmployeeID": 6, - "TerritoryID": "85014" - }, - { - "id": "6|85251", - "EmployeeID": 6, - "TerritoryID": "85251" - }, - { - "id": "6|98004", - "EmployeeID": 6, - "TerritoryID": "98004" - }, - { - "id": "6|98052", - "EmployeeID": 6, - "TerritoryID": "98052" - }, - { - "id": "6|98104", - "EmployeeID": 6, - "TerritoryID": "98104" - }, - { - "id": "7|60179", - "EmployeeID": 7, - "TerritoryID": "60179" - }, - { - "id": "7|60601", - "EmployeeID": 7, - "TerritoryID": "60601" - }, - { - "id": "7|80202", - "EmployeeID": 7, - "TerritoryID": "80202" - }, - { - "id": "7|80909", - "EmployeeID": 7, - "TerritoryID": "80909" - }, - { - "id": "7|90405", - "EmployeeID": 7, - "TerritoryID": "90405" - }, - { - "id": "7|94025", - "EmployeeID": 7, - "TerritoryID": "94025" - }, - { - "id": "7|94105", - "EmployeeID": 7, - "TerritoryID": "94105" - }, - { - "id": "7|95008", - "EmployeeID": 7, - "TerritoryID": "95008" - }, - { - "id": "7|95054", - "EmployeeID": 7, - "TerritoryID": "95054" - }, - { - "id": "7|95060", - "EmployeeID": 7, - "TerritoryID": "95060" - }, - { - "id": "8|19428", - "EmployeeID": 8, - "TerritoryID": "19428" - }, - { - "id": "8|44122", - "EmployeeID": 8, - "TerritoryID": "44122" - }, - { - "id": "8|45839", - "EmployeeID": 8, - "TerritoryID": "45839" - }, - { - "id": "8|53404", - "EmployeeID": 8, - "TerritoryID": "53404" - }, - { - "id": "9|03049", - "EmployeeID": 9, - "TerritoryID": "03049" - }, - { - "id": "9|03801", - "EmployeeID": 9, - "TerritoryID": "03801" - }, - { - "id": "9|48075", - "EmployeeID": 9, - "TerritoryID": "48075" - }, - { - "id": "9|48084", - "EmployeeID": 9, - "TerritoryID": "48084" - }, - { - "id": "9|48304", - "EmployeeID": 9, - "TerritoryID": "48304" - }, - { - "id": "9|55113", - "EmployeeID": 9, - "TerritoryID": "55113" - }, - { - "id": "9|55439", - "EmployeeID": 9, - "TerritoryID": "55439" - } - ] - }, { "Name": "Order", + "Container": "ProductsAndOrders", + "DiscriminatorInId": true, "Data": [ { "id": "10248", @@ -15909,6 +15595,8 @@ }, { "Name": "OrderDetail", + "Container": "ProductsAndOrders", + "DiscriminatorInId": true, "Data": [ { "id": "10248|11", @@ -33154,6 +32842,8 @@ }, { "Name": "Product", + "Container": "ProductsAndOrders", + "DiscriminatorInId": true, "Data": [ { "id": "1", @@ -34160,6 +33850,8 @@ }, { "Name": "Region", + "Container": "Regions", + "DiscriminatorInId": false, "Data": [ { "id": "1", @@ -34182,791 +33874,5 @@ "RegionDescription": "Southern" } ] - }, - { - "Name": "Shippers", - "Data": [ - { - "id": "1", - "ShipperID": 1, - "CompanyName": "Speedy Express", - "Phone": "(503) 555-9831" - }, - { - "id": "2", - "ShipperID": 2, - "CompanyName": "United Package", - "Phone": "(503) 555-3199" - }, - { - "id": "3", - "ShipperID": 3, - "CompanyName": "Federal Shipping", - "Phone": "(503) 555-9931" - } - ] - }, - { - "Name": "Suppliers", - "Data": [ - { - "id": "1", - "SupplierID": 1, - "CompanyName": "Exotic Liquids", - "ContactName": "Charlotte Cooper", - "ContactTitle": "Purchasing Manager", - "Address": "49 Gilbert St.", - "City": "London", - "Region": null, - "PostalCode": "EC1 4SD", - "Country": "UK", - "Phone": "(171) 555-2222", - "Fax": null, - "HomePage": null - }, - { - "id": "2", - "SupplierID": 2, - "CompanyName": "New Orleans Cajun Delights", - "ContactName": "Shelley Burke", - "ContactTitle": "Order Administrator", - "Address": "P.O. Box 78934", - "City": "New Orleans", - "Region": "LA", - "PostalCode": "70117", - "Country": "USA", - "Phone": "(100) 555-4822", - "Fax": null, - "HomePage": "#CAJUN.HTM#" - }, - { - "id": "3", - "SupplierID": 3, - "CompanyName": "Grandma Kelly's Homestead", - "ContactName": "Regina Murphy", - "ContactTitle": "Sales Representative", - "Address": "707 Oxford Rd.", - "City": "Ann Arbor", - "Region": "MI", - "PostalCode": "48104", - "Country": "USA", - "Phone": "(313) 555-5735", - "Fax": "(313) 555-3349", - "HomePage": null - }, - { - "id": "4", - "SupplierID": 4, - "CompanyName": "Tokyo Traders", - "ContactName": "Yoshi Nagase", - "ContactTitle": "Marketing Manager", - "Address": "9-8 Sekimai Musashino-shi", - "City": "Tokyo", - "Region": null, - "PostalCode": "100", - "Country": "Japan", - "Phone": "(03) 3555-5011", - "Fax": null, - "HomePage": null - }, - { - "id": "5", - "SupplierID": 5, - "CompanyName": "Cooperativa de Quesos 'Las Cabras'", - "ContactName": "Antonio del Valle Saavedra", - "ContactTitle": "Export Administrator", - "Address": "Calle del Rosal 4", - "City": "Oviedo", - "Region": "Asturias", - "PostalCode": "33007", - "Country": "Spain", - "Phone": "(98) 598 76 54", - "Fax": null, - "HomePage": null - }, - { - "id": "6", - "SupplierID": 6, - "CompanyName": "Mayumi's", - "ContactName": "Mayumi Ohno", - "ContactTitle": "Marketing Representative", - "Address": "92 Setsuko Chuo-ku", - "City": "Osaka", - "Region": null, - "PostalCode": "545", - "Country": "Japan", - "Phone": "(06) 431-7877", - "Fax": null, - "HomePage": "Mayumi's (on the World Wide Web)#http://www.microsoft.com/accessdev/sampleapps/mayumi.htm#" - }, - { - "id": "7", - "SupplierID": 7, - "CompanyName": "Pavlova, Ltd.", - "ContactName": "Ian Devling", - "ContactTitle": "Marketing Manager", - "Address": "74 Rose St. Moonie Ponds", - "City": "Melbourne", - "Region": "Victoria", - "PostalCode": "3058", - "Country": "Australia", - "Phone": "(03) 444-2343", - "Fax": "(03) 444-6588", - "HomePage": null - }, - { - "id": "8", - "SupplierID": 8, - "CompanyName": "Specialty Biscuits, Ltd.", - "ContactName": "Peter Wilson", - "ContactTitle": "Sales Representative", - "Address": "29 King's Way", - "City": "Manchester", - "Region": null, - "PostalCode": "M14 GSD", - "Country": "UK", - "Phone": "(161) 555-4448", - "Fax": null, - "HomePage": null - }, - { - "id": "9", - "SupplierID": 9, - "CompanyName": "PB Knäckebröd AB", - "ContactName": "Lars Peterson", - "ContactTitle": "Sales Agent", - "Address": "Kaloadagatan 13", - "City": "Göteborg", - "Region": null, - "PostalCode": "S-345 67", - "Country": "Sweden", - "Phone": "031-987 65 43", - "Fax": "031-987 65 91", - "HomePage": null - }, - { - "id": "10", - "SupplierID": 10, - "CompanyName": "Refrescos Americanas LTDA", - "ContactName": "Carlos Diaz", - "ContactTitle": "Marketing Manager", - "Address": "Av. das Americanas 12.890", - "City": "Sao Paulo", - "Region": null, - "PostalCode": "5442", - "Country": "Brazil", - "Phone": "(11) 555 4640", - "Fax": null, - "HomePage": null - }, - { - "id": "11", - "SupplierID": 11, - "CompanyName": "Heli Süßwaren GmbH & Co. KG", - "ContactName": "Petra Winkler", - "ContactTitle": "Sales Manager", - "Address": "Tiergartenstraße 5", - "City": "Berlin", - "Region": null, - "PostalCode": "10785", - "Country": "Germany", - "Phone": "(010) 9984510", - "Fax": null, - "HomePage": null - }, - { - "id": "12", - "SupplierID": 12, - "CompanyName": "Plutzer Lebensmittelgroßmärkte AG", - "ContactName": "Martin Bein", - "ContactTitle": "International Marketing Mgr.", - "Address": "Bogenallee 51", - "City": "Frankfurt", - "Region": null, - "PostalCode": "60439", - "Country": "Germany", - "Phone": "(069) 992755", - "Fax": null, - "HomePage": "Plutzer (on the World Wide Web)#http://www.microsoft.com/accessdev/sampleapps/plutzer.htm#" - }, - { - "id": "13", - "SupplierID": 13, - "CompanyName": "Nord-Ost-Fisch Handelsgesellschaft mbH", - "ContactName": "Sven Petersen", - "ContactTitle": "Coordinator Foreign Markets", - "Address": "Frahmredder 112a", - "City": "Cuxhaven", - "Region": null, - "PostalCode": "27478", - "Country": "Germany", - "Phone": "(04721) 8713", - "Fax": "(04721) 8714", - "HomePage": null - }, - { - "id": "14", - "SupplierID": 14, - "CompanyName": "Formaggi Fortini s.r.l.", - "ContactName": "Elio Rossi", - "ContactTitle": "Sales Representative", - "Address": "Viale Dante, 75", - "City": "Ravenna", - "Region": null, - "PostalCode": "48100", - "Country": "Italy", - "Phone": "(0544) 60323", - "Fax": "(0544) 60603", - "HomePage": "#FORMAGGI.HTM#" - }, - { - "id": "15", - "SupplierID": 15, - "CompanyName": "Norske Meierier", - "ContactName": "Beate Vileid", - "ContactTitle": "Marketing Manager", - "Address": "Hatlevegen 5", - "City": "Sandvika", - "Region": null, - "PostalCode": "1320", - "Country": "Norway", - "Phone": "(0)2-953010", - "Fax": null, - "HomePage": null - }, - { - "id": "16", - "SupplierID": 16, - "CompanyName": "Bigfoot Breweries", - "ContactName": "Cheryl Saylor", - "ContactTitle": "Regional Account Rep.", - "Address": "3400 - 8th Avenue Suite 210", - "City": "Bend", - "Region": "OR", - "PostalCode": "97101", - "Country": "USA", - "Phone": "(503) 555-9931", - "Fax": null, - "HomePage": null - }, - { - "id": "17", - "SupplierID": 17, - "CompanyName": "Svensk Sjöföda AB", - "ContactName": "Michael Björn", - "ContactTitle": "Sales Representative", - "Address": "Brovallavägen 231", - "City": "Stockholm", - "Region": null, - "PostalCode": "S-123 45", - "Country": "Sweden", - "Phone": "08-123 45 67", - "Fax": null, - "HomePage": null - }, - { - "id": "18", - "SupplierID": 18, - "CompanyName": "Aux joyeux ecclésiastiques", - "ContactName": "Guylène Nodier", - "ContactTitle": "Sales Manager", - "Address": "203, Rue des Francs-Bourgeois", - "City": "Paris", - "Region": null, - "PostalCode": "75004", - "Country": "France", - "Phone": "(1) 03.83.00.68", - "Fax": "(1) 03.83.00.62", - "HomePage": null - }, - { - "id": "19", - "SupplierID": 19, - "CompanyName": "New England Seafood Cannery", - "ContactName": "Robb Merchant", - "ContactTitle": "Wholesale Account Agent", - "Address": "Order Processing Dept. 2100 Paul Revere Blvd.", - "City": "Boston", - "Region": "MA", - "PostalCode": "02134", - "Country": "USA", - "Phone": "(617) 555-3267", - "Fax": "(617) 555-3389", - "HomePage": null - }, - { - "id": "20", - "SupplierID": 20, - "CompanyName": "Leka Trading", - "ContactName": "Chandra Leka", - "ContactTitle": "Owner", - "Address": "471 Serangoon Loop, Suite #402", - "City": "Singapore", - "Region": null, - "PostalCode": "0512", - "Country": "Singapore", - "Phone": "555-8787", - "Fax": null, - "HomePage": null - }, - { - "id": "21", - "SupplierID": 21, - "CompanyName": "Lyngbysild", - "ContactName": "Niels Petersen", - "ContactTitle": "Sales Manager", - "Address": "Lyngbysild Fiskebakken 10", - "City": "Lyngby", - "Region": null, - "PostalCode": "2800", - "Country": "Denmark", - "Phone": "43844108", - "Fax": "43844115", - "HomePage": null - }, - { - "id": "22", - "SupplierID": 22, - "CompanyName": "Zaanse Snoepfabriek", - "ContactName": "Dirk Luchte", - "ContactTitle": "Accounting Manager", - "Address": "Verkoop Rijnweg 22", - "City": "Zaandam", - "Region": null, - "PostalCode": "9999 ZZ", - "Country": "Netherlands", - "Phone": "(12345) 1212", - "Fax": "(12345) 1210", - "HomePage": null - }, - { - "id": "23", - "SupplierID": 23, - "CompanyName": "Karkki Oy", - "ContactName": "Anne Heikkonen", - "ContactTitle": "Product Manager", - "Address": "Valtakatu 12", - "City": "Lappeenranta", - "Region": null, - "PostalCode": "53120", - "Country": "Finland", - "Phone": "(953) 10956", - "Fax": null, - "HomePage": null - }, - { - "id": "24", - "SupplierID": 24, - "CompanyName": "G'day, Mate", - "ContactName": "Wendy Mackenzie", - "ContactTitle": "Sales Representative", - "Address": "170 Prince Edward Parade Hunter's Hill", - "City": "Sydney", - "Region": "NSW", - "PostalCode": "2042", - "Country": "Australia", - "Phone": "(02) 555-5914", - "Fax": "(02) 555-4873", - "HomePage": "G'day Mate (on the World Wide Web)#http://www.microsoft.com/accessdev/sampleapps/gdaymate.htm#" - }, - { - "id": "25", - "SupplierID": 25, - "CompanyName": "Ma Maison", - "ContactName": "Jean-Guy Lauzon", - "ContactTitle": "Marketing Manager", - "Address": "2960 Rue St. Laurent", - "City": "Montréal", - "Region": "Québec", - "PostalCode": "H1J 1C3", - "Country": "Canada", - "Phone": "(514) 555-9022", - "Fax": null, - "HomePage": null - }, - { - "id": "26", - "SupplierID": 26, - "CompanyName": "Pasta Buttini s.r.l.", - "ContactName": "Giovanni Giudici", - "ContactTitle": "Order Administrator", - "Address": "Via dei Gelsomini, 153", - "City": "Salerno", - "Region": null, - "PostalCode": "84100", - "Country": "Italy", - "Phone": "(089) 6547665", - "Fax": "(089) 6547667", - "HomePage": null - }, - { - "id": "27", - "SupplierID": 27, - "CompanyName": "Escargots Nouveaux", - "ContactName": "Marie Delamare", - "ContactTitle": "Sales Manager", - "Address": "22, rue H. Voiron", - "City": "Montceau", - "Region": null, - "PostalCode": "71300", - "Country": "France", - "Phone": "85.57.00.07", - "Fax": null, - "HomePage": null - }, - { - "id": "28", - "SupplierID": 28, - "CompanyName": "Gai pâturage", - "ContactName": "Eliane Noz", - "ContactTitle": "Sales Representative", - "Address": "Bat. B 3, rue des Alpes", - "City": "Annecy", - "Region": null, - "PostalCode": "74000", - "Country": "France", - "Phone": "38.76.98.06", - "Fax": "38.76.98.58", - "HomePage": null - }, - { - "id": "29", - "SupplierID": 29, - "CompanyName": "Forêts d'érables", - "ContactName": "Chantal Goulet", - "ContactTitle": "Accounting Manager", - "Address": "148 rue Chasseur", - "City": "Ste-Hyacinthe", - "Region": "Québec", - "PostalCode": "J2S 7S8", - "Country": "Canada", - "Phone": "(514) 555-2955", - "Fax": "(514) 555-2921", - "HomePage": null - } - ] - }, - { - "Name": "Territories", - "Data": [ - { - "id": "01581", - "TerritoryID": "01581", - "TerritoryDescription": "Westboro", - "RegionID": 1 - }, - { - "id": "01730", - "TerritoryID": "01730", - "TerritoryDescription": "Bedford", - "RegionID": 1 - }, - { - "id": "01833", - "TerritoryID": "01833", - "TerritoryDescription": "Georgetow", - "RegionID": 1 - }, - { - "id": "02116", - "TerritoryID": "02116", - "TerritoryDescription": "Boston", - "RegionID": 1 - }, - { - "id": "02139", - "TerritoryID": "02139", - "TerritoryDescription": "Cambridge", - "RegionID": 1 - }, - { - "id": "02184", - "TerritoryID": "02184", - "TerritoryDescription": "Braintree", - "RegionID": 1 - }, - { - "id": "02903", - "TerritoryID": "02903", - "TerritoryDescription": "Providence", - "RegionID": 1 - }, - { - "id": "03049", - "TerritoryID": "03049", - "TerritoryDescription": "Hollis", - "RegionID": 3 - }, - { - "id": "03801", - "TerritoryID": "03801", - "TerritoryDescription": "Portsmouth", - "RegionID": 3 - }, - { - "id": "06897", - "TerritoryID": "06897", - "TerritoryDescription": "Wilton", - "RegionID": 1 - }, - { - "id": "07960", - "TerritoryID": "07960", - "TerritoryDescription": "Morristown", - "RegionID": 1 - }, - { - "id": "08837", - "TerritoryID": "08837", - "TerritoryDescription": "Edison", - "RegionID": 1 - }, - { - "id": "10019", - "TerritoryID": "10019", - "TerritoryDescription": "New York", - "RegionID": 1 - }, - { - "id": "10038", - "TerritoryID": "10038", - "TerritoryDescription": "New York", - "RegionID": 1 - }, - { - "id": "11747", - "TerritoryID": "11747", - "TerritoryDescription": "Mellvile", - "RegionID": 1 - }, - { - "id": "14450", - "TerritoryID": "14450", - "TerritoryDescription": "Fairport", - "RegionID": 1 - }, - { - "id": "19428", - "TerritoryID": "19428", - "TerritoryDescription": "Philadelphia", - "RegionID": 3 - }, - { - "id": "19713", - "TerritoryID": "19713", - "TerritoryDescription": "Neward", - "RegionID": 1 - }, - { - "id": "20852", - "TerritoryID": "20852", - "TerritoryDescription": "Rockville", - "RegionID": 1 - }, - { - "id": "27403", - "TerritoryID": "27403", - "TerritoryDescription": "Greensboro", - "RegionID": 1 - }, - { - "id": "27511", - "TerritoryID": "27511", - "TerritoryDescription": "Cary", - "RegionID": 1 - }, - { - "id": "29202", - "TerritoryID": "29202", - "TerritoryDescription": "Columbia", - "RegionID": 4 - }, - { - "id": "30346", - "TerritoryID": "30346", - "TerritoryDescription": "Atlanta", - "RegionID": 4 - }, - { - "id": "31406", - "TerritoryID": "31406", - "TerritoryDescription": "Savannah", - "RegionID": 4 - }, - { - "id": "32859", - "TerritoryID": "32859", - "TerritoryDescription": "Orlando", - "RegionID": 4 - }, - { - "id": "33607", - "TerritoryID": "33607", - "TerritoryDescription": "Tampa", - "RegionID": 4 - }, - { - "id": "40222", - "TerritoryID": "40222", - "TerritoryDescription": "Louisville", - "RegionID": 1 - }, - { - "id": "44122", - "TerritoryID": "44122", - "TerritoryDescription": "Beachwood", - "RegionID": 3 - }, - { - "id": "45839", - "TerritoryID": "45839", - "TerritoryDescription": "Findlay", - "RegionID": 3 - }, - { - "id": "48075", - "TerritoryID": "48075", - "TerritoryDescription": "Southfield", - "RegionID": 3 - }, - { - "id": "48084", - "TerritoryID": "48084", - "TerritoryDescription": "Troy", - "RegionID": 3 - }, - { - "id": "48304", - "TerritoryID": "48304", - "TerritoryDescription": "Bloomfield Hills", - "RegionID": 3 - }, - { - "id": "53404", - "TerritoryID": "53404", - "TerritoryDescription": "Racine", - "RegionID": 3 - }, - { - "id": "55113", - "TerritoryID": "55113", - "TerritoryDescription": "Roseville", - "RegionID": 3 - }, - { - "id": "55439", - "TerritoryID": "55439", - "TerritoryDescription": "Minneapolis", - "RegionID": 3 - }, - { - "id": "60179", - "TerritoryID": "60179", - "TerritoryDescription": "Hoffman Estates", - "RegionID": 2 - }, - { - "id": "60601", - "TerritoryID": "60601", - "TerritoryDescription": "Chicago", - "RegionID": 2 - }, - { - "id": "72716", - "TerritoryID": "72716", - "TerritoryDescription": "Bentonville", - "RegionID": 4 - }, - { - "id": "75234", - "TerritoryID": "75234", - "TerritoryDescription": "Dallas", - "RegionID": 4 - }, - { - "id": "78759", - "TerritoryID": "78759", - "TerritoryDescription": "Austin", - "RegionID": 4 - }, - { - "id": "80202", - "TerritoryID": "80202", - "TerritoryDescription": "Denver", - "RegionID": 2 - }, - { - "id": "80909", - "TerritoryID": "80909", - "TerritoryDescription": "Colorado Springs", - "RegionID": 2 - }, - { - "id": "85014", - "TerritoryID": "85014", - "TerritoryDescription": "Phoenix", - "RegionID": 2 - }, - { - "id": "85251", - "TerritoryID": "85251", - "TerritoryDescription": "Scottsdale", - "RegionID": 2 - }, - { - "id": "90405", - "TerritoryID": "90405", - "TerritoryDescription": "Santa Monica", - "RegionID": 2 - }, - { - "id": "94025", - "TerritoryID": "94025", - "TerritoryDescription": "Menlo Park", - "RegionID": 2 - }, - { - "id": "94105", - "TerritoryID": "94105", - "TerritoryDescription": "San Francisco", - "RegionID": 2 - }, - { - "id": "95008", - "TerritoryID": "95008", - "TerritoryDescription": "Campbell", - "RegionID": 2 - }, - { - "id": "95054", - "TerritoryID": "95054", - "TerritoryDescription": "Santa Clara", - "RegionID": 2 - }, - { - "id": "95060", - "TerritoryID": "95060", - "TerritoryDescription": "Santa Cruz", - "RegionID": 2 - }, - { - "id": "98004", - "TerritoryID": "98004", - "TerritoryDescription": "Bellevue", - "RegionID": 2 - }, - { - "id": "98052", - "TerritoryID": "98052", - "TerritoryDescription": "Redmond", - "RegionID": 2 - }, - { - "id": "98104", - "TerritoryID": "98104", - "TerritoryDescription": "Seattle", - "RegionID": 2 - } - ] } ] \ No newline at end of file diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/FromSqlQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/FromSqlQueryCosmosTest.cs index eb5773c663d..6c90934c2ba 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/FromSqlQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/FromSqlQueryCosmosTest.cs @@ -51,14 +51,14 @@ SELECT VALUE s public async Task FromSqlRaw_queryable_incorrect_discriminator_throws() { using var context = CreateContext(); - var query = context.Set().FromSqlRaw(""" -SELECT * FROM root c WHERE c["Discriminator"] = "Order" + var query = context.Set().FromSqlRaw(""" +SELECT * FROM root c WHERE c["Discriminator"] = "OrderDetail" """); var exception = await Assert.ThrowsAsync(() => query.ToArrayAsync()); Assert.Equal( - CoreStrings.UnableToDiscriminate(context.Model.FindEntityType(typeof(Customer))!.DisplayName(), "Order"), + CoreStrings.UnableToDiscriminate(context.Model.FindEntityType(typeof(Order))!.DisplayName(), "OrderDetail"), exception.Message); } @@ -71,7 +71,7 @@ public Task FromSqlRaw_queryable_simple_columns_out_of_order(bool async) using var context = CreateContext(); var query = context.Set().FromSqlRaw( """ -SELECT c["id"], c["Discriminator"], c["Region"], c["PostalCode"], c["Phone"], c["Fax"], c["CustomerID"], c["Country"], c["ContactTitle"], c["ContactName"], c["CompanyName"], c["City"], c["Address"] FROM root c WHERE c["Discriminator"] = "Customer" +SELECT c["id"], c["Discriminator"], c["Region"], c["PostalCode"], c["Phone"], c["Fax"], c["Country"], c["ContactTitle"], c["ContactName"], c["CompanyName"], c["City"], c["Address"] FROM root c WHERE c["Discriminator"] = "Customer" """); var actual = a @@ -85,7 +85,7 @@ public Task FromSqlRaw_queryable_simple_columns_out_of_order(bool async) """ SELECT VALUE s FROM ( - SELECT c["id"], c["Discriminator"], c["Region"], c["PostalCode"], c["Phone"], c["Fax"], c["CustomerID"], c["Country"], c["ContactTitle"], c["ContactName"], c["CompanyName"], c["City"], c["Address"] FROM root c WHERE c["Discriminator"] = "Customer" + SELECT c["id"], c["Discriminator"], c["Region"], c["PostalCode"], c["Phone"], c["Fax"], c["Country"], c["ContactTitle"], c["ContactName"], c["CompanyName"], c["City"], c["Address"] FROM root c WHERE c["Discriminator"] = "Customer" ) s """); }); @@ -99,7 +99,7 @@ public Task FromSqlRaw_queryable_simple_columns_out_of_order_and_extra_columns(b using var context = CreateContext(); var query = context.Set().FromSqlRaw( """ -SELECT c["id"], c["Discriminator"], c["Region"], c["PostalCode"], c["PostalCode"] AS Foo, c["Phone"], c["Fax"], c["CustomerID"], c["Country"], c["ContactTitle"], c["ContactName"], c["CompanyName"], c["City"], c["Address"] FROM root c WHERE c["Discriminator"] = "Customer" +SELECT c["id"], c["Discriminator"], c["Region"], c["PostalCode"], c["PostalCode"] AS Foo, c["Phone"], c["Fax"], c["Country"], c["ContactTitle"], c["ContactName"], c["CompanyName"], c["City"], c["Address"] FROM root c WHERE c["Discriminator"] = "Customer" """); var actual = a @@ -113,7 +113,7 @@ public Task FromSqlRaw_queryable_simple_columns_out_of_order_and_extra_columns(b """ SELECT VALUE s FROM ( - SELECT c["id"], c["Discriminator"], c["Region"], c["PostalCode"], c["PostalCode"] AS Foo, c["Phone"], c["Fax"], c["CustomerID"], c["Country"], c["ContactTitle"], c["ContactName"], c["CompanyName"], c["City"], c["Address"] FROM root c WHERE c["Discriminator"] = "Customer" + SELECT c["id"], c["Discriminator"], c["Region"], c["PostalCode"], c["PostalCode"] AS Foo, c["Phone"], c["Fax"], c["Country"], c["ContactTitle"], c["ContactName"], c["CompanyName"], c["City"], c["Address"] FROM root c WHERE c["Discriminator"] = "Customer" ) s """); }); @@ -240,7 +240,7 @@ public virtual Task FromSqlRaw_queryable_composed_compiled_with_parameter(bool a { var query = EF.CompileAsyncQuery( (NorthwindContext context) => context.Set().FromSqlRaw( - """SELECT * FROM root c WHERE c["Discriminator"] = "Customer" AND c["CustomerID"] = {0}""", "CONSH") + """SELECT * FROM root c WHERE c["Discriminator"] = "Customer" AND c["id"] = {0}""", "CONSH") .Where(c => c.ContactName.Contains("z"))); using (var context = CreateContext()) @@ -254,7 +254,7 @@ public virtual Task FromSqlRaw_queryable_composed_compiled_with_parameter(bool a { var query = EF.CompileQuery( (NorthwindContext context) => context.Set().FromSqlRaw( - """SELECT * FROM root c WHERE c["Discriminator"] = "Customer" AND c["CustomerID"] = {0}""", "CONSH") + """SELECT * FROM root c WHERE c["Discriminator"] = "Customer" AND c["id"] = {0}""", "CONSH") .Where(c => c.ContactName.Contains("z"))); using (var context = CreateContext()) @@ -269,7 +269,7 @@ public virtual Task FromSqlRaw_queryable_composed_compiled_with_parameter(bool a """ SELECT VALUE s FROM ( - SELECT * FROM root c WHERE c["Discriminator"] = "Customer" AND c["CustomerID"] = "CONSH" + SELECT * FROM root c WHERE c["Discriminator"] = "Customer" AND c["id"] = "CONSH" ) s WHERE CONTAINS(s["ContactName"], "z") """); @@ -704,7 +704,11 @@ public virtual Task FromSqlRaw_queryable_simple_projection_not_composed(bool asy AssertSql( """ -SELECT s["CustomerID"], s["City"] +SELECT VALUE +{ + "CustomerID" : s["id"], + "City" : s["City"] +} FROM ( SELECT * FROM root c WHERE c["Discriminator"] = "Customer" ) s @@ -715,16 +719,16 @@ public virtual Task FromSqlRaw_queryable_simple_projection_not_composed(bool asy public async Task FromSqlRaw_queryable_simple_with_missing_key_and_non_tracking_throws() { using var context = CreateContext(); - var query = context.Set() - .FromSqlRaw("""SELECT * FROM root c WHERE c["Discriminator"] = "Category" """) + var query = context.Set() + .FromSqlRaw("""SELECT * FROM root c WHERE c["Discriminator"] = "Product" """) .AsNoTracking(); var exception = await Assert.ThrowsAsync(() => query.ToArrayAsync()); Assert.Equal( CoreStrings.InvalidKeyValue( - context.Model.FindEntityType(typeof(Customer))!.DisplayName(), - "CustomerID"), + context.Model.FindEntityType(typeof(Order))!.DisplayName(), + "OrderID"), exception.Message); } diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosFixture.cs b/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosFixture.cs index a446aa89dee..4b0e4fa56cb 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosFixture.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosFixture.cs @@ -1,6 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.EntityFrameworkCore.TestModels.InheritanceModel; + namespace Microsoft.EntityFrameworkCore.Query; #nullable disable @@ -25,4 +27,18 @@ public Task NoSyncTest(bool async, Func testCode) public override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder) => base.AddOptions(builder.ConfigureWarnings( w => w.Ignore(CoreEventId.MappedEntityTypeIgnoredWarning, CosmosEventId.NoPartitionKeyDefined))); + + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + + modelBuilder.Entity().ToContainer("Animals"); + modelBuilder.Entity().ToContainer("Plants"); + modelBuilder.Entity().ToContainer("Countries"); + modelBuilder.Entity().ToContainer("Drinks");; + modelBuilder.Entity().ToContainer("Animals"); + modelBuilder.Entity().ToContainer("Animals"); + modelBuilder.Entity().ToContainer("Animals");; + modelBuilder.Entity().ToContainer("Animals");; + } } diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosTest.cs index e069d65d502..66471f1aade 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/InheritanceQueryCosmosTest.cs @@ -278,7 +278,7 @@ public override Task Can_query_all_plants(bool async) SELECT VALUE c FROM root c WHERE c["Discriminator"] IN ("Daisy", "Rose") -ORDER BY c["Species"] +ORDER BY c["id"] """); }); diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindAggregateOperatorsQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindAggregateOperatorsQueryCosmosTest.cs index d97e0bc94c6..e7dcea3f49b 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindAggregateOperatorsQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindAggregateOperatorsQueryCosmosTest.cs @@ -65,7 +65,7 @@ public override Task Contains_with_local_non_primitive_list_closure_mix(bool asy SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__Select_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__Select_0, c["id"]) """); }); @@ -81,7 +81,7 @@ public override Task Contains_with_local_non_primitive_list_inline_closure_mix(b SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__Select_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__Select_0, c["id"]) """, // """ @@ -89,7 +89,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__Select_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__Select_0, c["id"]) """); }); @@ -129,7 +129,6 @@ public override Task First(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") ORDER BY c["ContactName"] OFFSET 0 LIMIT 1 """); @@ -187,7 +186,7 @@ public override Task First_Predicate(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = "London")) +WHERE (c["City"] = "London") ORDER BY c["ContactName"] OFFSET 0 LIMIT 1 """); @@ -204,7 +203,6 @@ public override async Task Single_Throws(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") OFFSET 0 LIMIT 2 """); } @@ -220,7 +218,7 @@ public override Task Where_First(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = "London")) +WHERE (c["City"] = "London") ORDER BY c["ContactName"] OFFSET 0 LIMIT 1 """); @@ -232,7 +230,7 @@ public override Task Where_Single(bool async) { await base.Where_Single(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); public override Task FirstOrDefault(bool async) @@ -240,12 +238,10 @@ public override Task FirstOrDefault(bool async) async, async a => { await base.FirstOrDefault(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") ORDER BY c["ContactName"] OFFSET 0 LIMIT 1 """); @@ -261,7 +257,7 @@ public override Task Array_cast_to_IEnumerable_Contains_with_constant(bool async """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND c["CustomerID"] IN ("ALFKI", "WRONG")) +WHERE c["id"] IN ("ALFKI", "WRONG") """); }); @@ -275,7 +271,7 @@ public override Task FirstOrDefault_Predicate(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = "London")) +WHERE (c["City"] = "London") ORDER BY c["ContactName"] OFFSET 0 LIMIT 1 """); @@ -287,7 +283,7 @@ public override Task SingleOrDefault_Predicate(bool async) { await base.SingleOrDefault_Predicate(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); public override async Task SingleOrDefault_Throws(bool async) @@ -301,7 +297,6 @@ public override async Task SingleOrDefault_Throws(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") OFFSET 0 LIMIT 2 """); } @@ -312,12 +307,11 @@ public override Task Where_FirstOrDefault(bool async) async, async a => { await base.Where_FirstOrDefault(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = "London")) +WHERE (c["City"] = "London") ORDER BY c["ContactName"] OFFSET 0 LIMIT 1 """); @@ -329,7 +323,7 @@ public override Task Where_SingleOrDefault(bool async) { await base.Where_SingleOrDefault(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); public override async Task Select_All(bool async) @@ -1179,7 +1173,6 @@ await Assert.ThrowsAsync( SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Employee") ORDER BY 42 OFFSET 0 LIMIT @__p_0 """); @@ -1196,7 +1189,6 @@ public override Task Distinct(bool async) """ SELECT DISTINCT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -1227,7 +1219,7 @@ public override Task OrderBy_Distinct(bool async) SELECT DISTINCT c["City"] FROM root c WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); }); @@ -1275,7 +1267,7 @@ public override Task Single_Predicate(bool async) { await base.Single_Predicate(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); public override async Task FirstOrDefault_inside_subquery_gets_server_evaluated(bool async) @@ -1312,7 +1304,6 @@ public override Task Last(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") ORDER BY c["ContactName"] DESC OFFSET 0 LIMIT 1 """); @@ -1324,7 +1315,7 @@ public override Task Last_when_no_order_by(bool async) { await base.Last_when_no_order_by(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); public override Task LastOrDefault_when_no_order_by(bool async) @@ -1333,7 +1324,7 @@ public override Task LastOrDefault_when_no_order_by(bool async) { await base.LastOrDefault_when_no_order_by(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); public override Task Last_Predicate(bool async) @@ -1346,7 +1337,7 @@ public override Task Last_Predicate(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = "London")) +WHERE (c["City"] = "London") ORDER BY c["ContactName"] DESC OFFSET 0 LIMIT 1 """); @@ -1362,7 +1353,7 @@ public override Task Where_Last(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = "London")) +WHERE (c["City"] = "London") ORDER BY c["ContactName"] DESC OFFSET 0 LIMIT 1 """); @@ -1378,7 +1369,6 @@ public override Task LastOrDefault(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") ORDER BY c["ContactName"] DESC OFFSET 0 LIMIT 1 """); @@ -1394,7 +1384,7 @@ public override Task LastOrDefault_Predicate(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = "London")) +WHERE (c["City"] = "London") ORDER BY c["ContactName"] DESC OFFSET 0 LIMIT 1 """); @@ -1410,7 +1400,7 @@ public override Task Where_LastOrDefault(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = "London")) +WHERE (c["City"] = "London") ORDER BY c["ContactName"] DESC OFFSET 0 LIMIT 1 """); @@ -1431,20 +1421,20 @@ public override Task Contains_with_local_array_closure(bool async) await base.Contains_with_local_array_closure(a); AssertSql( - """ + """ @__ids_0='["ABCDE","ALFKI"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """, - // - """ + // + """ @__ids_0='["ABCDE"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -1468,7 +1458,7 @@ public override Task Contains_with_local_uint_array_closure(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND ARRAY_CONTAINS(@__ids_0, c["EmployeeID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["EmployeeID"]) """, // """ @@ -1476,7 +1466,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND ARRAY_CONTAINS(@__ids_0, c["EmployeeID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["EmployeeID"]) """); }); @@ -1492,7 +1482,7 @@ public override Task Contains_with_local_nullable_uint_array_closure(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND ARRAY_CONTAINS(@__ids_0, c["EmployeeID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["EmployeeID"]) """, // """ @@ -1500,7 +1490,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND ARRAY_CONTAINS(@__ids_0, c["EmployeeID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["EmployeeID"]) """); }); @@ -1509,12 +1499,11 @@ public override Task Contains_with_local_array_inline(bool async) async, async a => { await base.Contains_with_local_array_inline(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND c["CustomerID"] IN ("ABCDE", "ALFKI")) +WHERE c["id"] IN ("ABCDE", "ALFKI") """); }); @@ -1530,7 +1519,7 @@ public override Task Contains_with_local_list_closure(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -1539,14 +1528,13 @@ public override Task Contains_with_local_object_list_closure(bool async) async, async a => { await base.Contains_with_local_object_list_closure(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='["ABCDE","ALFKI"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -1555,14 +1543,13 @@ public override Task Contains_with_local_list_closure_all_null(bool async) async, async a => { await base.Contains_with_local_list_closure_all_null(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='[null,null]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -1571,12 +1558,11 @@ public override Task Contains_with_local_list_inline(bool async) async, async a => { await base.Contains_with_local_list_inline(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND c["CustomerID"] IN ("ABCDE", "ALFKI")) +WHERE c["id"] IN ("ABCDE", "ALFKI") """); }); @@ -1585,22 +1571,21 @@ public override Task Contains_with_local_list_inline_closure_mix(bool async) async, async a => { await base.Contains_with_local_list_inline_closure_mix(a); - - AssertSql( - """ +AssertSql( + """ @__p_0='["ABCDE","ALFKI"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__p_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__p_0, c["id"]) """, - // - """ + // + """ @__p_0='["ABCDE","ANATR"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__p_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__p_0, c["id"]) """); }); @@ -1615,7 +1600,7 @@ public override Task Contains_with_local_enumerable_closure(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """, // """ @@ -1623,7 +1608,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -1639,7 +1624,7 @@ public override Task Contains_with_local_object_enumerable_closure(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -1648,14 +1633,13 @@ public override Task Contains_with_local_enumerable_closure_all_null(bool async) async, async a => { await base.Contains_with_local_enumerable_closure_all_null(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='[]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -1664,15 +1648,14 @@ public override Task Contains_with_local_enumerable_inline(bool async) async, async a => { await base.Contains_with_local_enumerable_inline(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND EXISTS ( +WHERE EXISTS ( SELECT 1 FROM a IN (SELECT VALUE ["ABCDE", "ALFKI"]) - WHERE ((a != null) AND (a = c["CustomerID"])))) + WHERE ((a != null) AND (a = c["id"]))) """); }); @@ -1681,28 +1664,27 @@ public override Task Contains_with_local_enumerable_inline_closure_mix(bool asyn async, async a => { await base.Contains_with_local_enumerable_inline_closure_mix(a); - - AssertSql( - """ +AssertSql( + """ @__p_0='["ABCDE","ALFKI"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND EXISTS ( +WHERE EXISTS ( SELECT 1 FROM p IN (SELECT VALUE @__p_0) - WHERE ((p != null) AND (p = c["CustomerID"])))) + WHERE ((p != null) AND (p = c["id"]))) """, - // - """ + // + """ @__p_0='["ABCDE","ANATR"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND EXISTS ( +WHERE EXISTS ( SELECT 1 FROM p IN (SELECT VALUE @__p_0) - WHERE ((p != null) AND (p = c["CustomerID"])))) + WHERE ((p != null) AND (p = c["id"]))) """); }); @@ -1718,7 +1700,7 @@ public override Task Contains_with_local_ordered_enumerable_closure(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """, // """ @@ -1726,7 +1708,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -1735,14 +1717,13 @@ public override Task Contains_with_local_object_ordered_enumerable_closure(bool async, async a => { await base.Contains_with_local_object_ordered_enumerable_closure(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='["ABCDE","ALFKI"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -1751,14 +1732,13 @@ public override Task Contains_with_local_ordered_enumerable_closure_all_null(boo async, async a => { await base.Contains_with_local_ordered_enumerable_closure_all_null(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='[null,null]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -1767,12 +1747,11 @@ public override Task Contains_with_local_ordered_enumerable_inline(bool async) async, async a => { await base.Contains_with_local_ordered_enumerable_inline(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND c["CustomerID"] IN ("ABCDE", "ALFKI")) +WHERE c["id"] IN ("ABCDE", "ALFKI") """); }); @@ -1788,7 +1767,7 @@ public override Task Contains_with_local_ordered_enumerable_inline_closure_mix(b SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__Order_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__Order_0, c["id"]) """, // """ @@ -1796,7 +1775,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__Order_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__Order_0, c["id"]) """); }); @@ -1805,22 +1784,21 @@ public override Task Contains_with_local_read_only_collection_closure(bool async async, async a => { await base.Contains_with_local_read_only_collection_closure(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='["ABCDE","ALFKI"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """, - // - """ + // + """ @__ids_0='["ABCDE"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -1829,14 +1807,13 @@ public override Task Contains_with_local_object_read_only_collection_closure(boo async, async a => { await base.Contains_with_local_object_read_only_collection_closure(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='["ABCDE","ALFKI"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -1845,14 +1822,13 @@ public override Task Contains_with_local_ordered_read_only_collection_all_null(b async, async a => { await base.Contains_with_local_ordered_read_only_collection_all_null(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='[null,null]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -1861,12 +1837,11 @@ public override Task Contains_with_local_read_only_collection_inline(bool async) async, async a => { await base.Contains_with_local_read_only_collection_inline(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND c["CustomerID"] IN ("ABCDE", "ALFKI")) +WHERE c["id"] IN ("ABCDE", "ALFKI") """); }); @@ -1875,22 +1850,21 @@ public override Task Contains_with_local_read_only_collection_inline_closure_mix async, async a => { await base.Contains_with_local_read_only_collection_inline_closure_mix(a); - - AssertSql( - """ +AssertSql( + """ @__AsReadOnly_0='["ABCDE","ALFKI"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__AsReadOnly_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__AsReadOnly_0, c["id"]) """, - // - """ + // + """ @__AsReadOnly_0='["ABCDE","ANATR"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__AsReadOnly_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__AsReadOnly_0, c["id"]) """); }); @@ -1899,14 +1873,13 @@ public override Task Contains_with_local_collection_false(bool async) async, async a => { await base.Contains_with_local_collection_false(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='["ABCDE","ALFKI"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND NOT(ARRAY_CONTAINS(@__ids_0, c["CustomerID"]))) +WHERE NOT(ARRAY_CONTAINS(@__ids_0, c["id"])) """); }); @@ -1922,7 +1895,7 @@ public override Task Contains_with_local_collection_complex_predicate_and(bool a SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (((c["CustomerID"] = "ALFKI") OR (c["CustomerID"] = "ABCDE")) AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"]))) +WHERE (((c["id"] = "ALFKI") OR (c["id"] = "ABCDE")) AND ARRAY_CONTAINS(@__ids_0, c["id"])) """); }); @@ -1931,14 +1904,13 @@ public override Task Contains_with_local_collection_complex_predicate_or(bool as async, async a => { await base.Contains_with_local_collection_complex_predicate_or(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='["ABCDE","ALFKI"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (ARRAY_CONTAINS(@__ids_0, c["CustomerID"]) OR ((c["CustomerID"] = "ALFKI") OR (c["CustomerID"] = "ABCDE")))) +WHERE (ARRAY_CONTAINS(@__ids_0, c["id"]) OR ((c["id"] = "ALFKI") OR (c["id"] = "ABCDE"))) """); }); @@ -1947,14 +1919,13 @@ public override Task Contains_with_local_collection_complex_predicate_not_matchi async, async a => { await base.Contains_with_local_collection_complex_predicate_not_matching_ins1(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='["ABCDE","ALFKI"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (((c["CustomerID"] = "ALFKI") OR (c["CustomerID"] = "ABCDE")) OR NOT(ARRAY_CONTAINS(@__ids_0, c["CustomerID"])))) +WHERE (((c["id"] = "ALFKI") OR (c["id"] = "ABCDE")) OR NOT(ARRAY_CONTAINS(@__ids_0, c["id"]))) """); }); @@ -1963,14 +1934,13 @@ public override Task Contains_with_local_collection_complex_predicate_not_matchi async, async a => { await base.Contains_with_local_collection_complex_predicate_not_matching_ins2(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='["ABCDE","ALFKI"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (ARRAY_CONTAINS(@__ids_0, c["CustomerID"]) AND ((c["CustomerID"] != "ALFKI") AND (c["CustomerID"] != "ABCDE")))) +WHERE (ARRAY_CONTAINS(@__ids_0, c["id"]) AND ((c["id"] != "ALFKI") AND (c["id"] != "ABCDE"))) """); }); @@ -1979,14 +1949,13 @@ public override Task Contains_with_local_collection_sql_injection(bool async) async, async a => { await base.Contains_with_local_collection_sql_injection(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='["ALFKI","ABC')); GO; DROP TABLE Orders; GO; --"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (ARRAY_CONTAINS(@__ids_0, c["CustomerID"]) OR ((c["CustomerID"] = "ALFKI") OR (c["CustomerID"] = "ABCDE")))) +WHERE (ARRAY_CONTAINS(@__ids_0, c["id"]) OR ((c["id"] = "ALFKI") OR (c["id"] = "ABCDE"))) """); }); @@ -2002,7 +1971,7 @@ public override Task Contains_with_local_collection_empty_closure(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -2016,7 +1985,7 @@ public override Task Contains_with_local_collection_empty_inline(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND NOT(false)) +WHERE NOT(false) """); }); @@ -2037,7 +2006,7 @@ public override async Task Contains_top_level(bool async) SELECT VALUE EXISTS ( SELECT 1 FROM root c - WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = @__p_0))) + WHERE (c["id"] = @__p_0)) AS c """); } } @@ -2068,7 +2037,7 @@ public override async Task OfType_Select(bool async) public override async Task OfType_Select_OfType_Select(bool async) { - // Contains over subquery. Issue #17246. + // Contains over subquery. Issue #15937. await AssertTranslationFailed(() => base.OfType_Select_OfType_Select(async)); AssertSql(); @@ -2157,12 +2126,11 @@ public override Task List_Contains_with_constant_list(bool async) async, async a => { await base.List_Contains_with_constant_list(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND c["CustomerID"] IN ("ALFKI", "ANATR")) +WHERE c["id"] IN ("ALFKI", "ANATR") """); }); @@ -2176,7 +2144,7 @@ public override Task List_Contains_with_parameter_list(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND c["CustomerID"] IN ("ALFKI", "ANATR")) +WHERE c["id"] IN ("ALFKI", "ANATR") """); }); @@ -2213,12 +2181,11 @@ public override Task IImmutableSet_Contains_with_parameter(bool async) async, async a => { await base.IImmutableSet_Contains_with_parameter(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") """); }); @@ -2227,12 +2194,11 @@ public override Task IReadOnlySet_Contains_with_parameter(bool async) async, async a => { await base.IReadOnlySet_Contains_with_parameter(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") """); }); @@ -2241,14 +2207,13 @@ public override Task HashSet_Contains_with_parameter(bool async) async, async a => { await base.HashSet_Contains_with_parameter(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='["ALFKI"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -2257,14 +2222,13 @@ public override Task ImmutableHashSet_Contains_with_parameter(bool async) async, async a => { await base.ImmutableHashSet_Contains_with_parameter(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='["ALFKI"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -2307,9 +2271,8 @@ public override Task String_FirstOrDefault_in_projection_does_not_do_client_eval AssertSql( """ -SELECT VALUE LEFT(c["CustomerID"], 1) +SELECT VALUE LEFT(c["id"], 1) FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -2323,7 +2286,6 @@ public override Task Project_constant_Sum(bool async) """ SELECT VALUE SUM(1) FROM root c -WHERE (c["Discriminator"] = "Employee") """); }); @@ -2339,7 +2301,7 @@ public override Task Where_subquery_any_equals_operator(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -2348,12 +2310,11 @@ public override Task Where_subquery_any_equals(bool async) async, async a => { await base.Where_subquery_any_equals(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND c["CustomerID"] IN ("ABCDE", "ALFKI", "ANATR")) +WHERE c["id"] IN ("ABCDE", "ALFKI", "ANATR") """); }); @@ -2369,7 +2330,7 @@ public override Task Where_subquery_any_equals_static(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ARRAY_CONTAINS(@__ids_0, c["id"]) """); }); @@ -2378,22 +2339,21 @@ public override Task Where_subquery_where_any(bool async) async, async a => { await base.Where_subquery_where_any(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='["ABCDE","ALFKI","ANATR"]' SELECT VALUE c FROM root c -WHERE (((c["Discriminator"] = "Customer") AND (c["City"] = "México D.F.")) AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ((c["City"] = "México D.F.") AND ARRAY_CONTAINS(@__ids_0, c["id"])) """, - // - """ + // + """ @__ids_0='["ABCDE","ALFKI","ANATR"]' SELECT VALUE c FROM root c -WHERE (((c["Discriminator"] = "Customer") AND (c["City"] = "México D.F.")) AND ARRAY_CONTAINS(@__ids_0, c["CustomerID"])) +WHERE ((c["City"] = "México D.F.") AND ARRAY_CONTAINS(@__ids_0, c["id"])) """); }); @@ -2402,14 +2362,13 @@ public override Task Where_subquery_all_not_equals_operator(bool async) async, async a => { await base.Where_subquery_all_not_equals_operator(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='["ABCDE","ALFKI","ANATR"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND NOT(ARRAY_CONTAINS(@__ids_0, c["CustomerID"]))) +WHERE NOT(ARRAY_CONTAINS(@__ids_0, c["id"])) """); }); @@ -2418,12 +2377,11 @@ public override Task Where_subquery_all_not_equals(bool async) async, async a => { await base.Where_subquery_all_not_equals(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND c["CustomerID"] NOT IN ("ABCDE", "ALFKI", "ANATR")) +WHERE c["id"] NOT IN ("ABCDE", "ALFKI", "ANATR") """); }); @@ -2432,14 +2390,13 @@ public override Task Where_subquery_all_not_equals_static(bool async) async, async a => { await base.Where_subquery_all_not_equals_static(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='["ABCDE","ALFKI","ANATR"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND NOT(ARRAY_CONTAINS(@__ids_0, c["CustomerID"]))) +WHERE NOT(ARRAY_CONTAINS(@__ids_0, c["id"])) """); }); @@ -2448,22 +2405,21 @@ public override Task Where_subquery_where_all(bool async) async, async a => { await base.Where_subquery_where_all(a); - - AssertSql( - """ +AssertSql( + """ @__ids_0='["ABCDE","ALFKI","ANATR"]' SELECT VALUE c FROM root c -WHERE (((c["Discriminator"] = "Customer") AND (c["City"] = "México D.F.")) AND NOT(ARRAY_CONTAINS(@__ids_0, c["CustomerID"]))) +WHERE ((c["City"] = "México D.F.") AND NOT(ARRAY_CONTAINS(@__ids_0, c["id"]))) """, - // - """ + // + """ @__ids_0='["ABCDE","ALFKI","ANATR"]' SELECT VALUE c FROM root c -WHERE (((c["Discriminator"] = "Customer") AND (c["City"] = "México D.F.")) AND NOT(ARRAY_CONTAINS(@__ids_0, c["CustomerID"]))) +WHERE ((c["City"] = "México D.F.") AND NOT(ARRAY_CONTAINS(@__ids_0, c["id"]))) """); }); @@ -2472,12 +2428,10 @@ public override Task Cast_to_same_Type_Count_works(bool async) async, async a => { await base.Cast_to_same_Type_Count_works(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE COUNT(1) FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -2687,7 +2641,6 @@ public override Task Contains_inside_Average_without_GroupBy(bool async) SELECT VALUE AVG((ARRAY_CONTAINS(@__cities_0, c["City"]) ? 1.0 : 0.0)) FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -2703,7 +2656,6 @@ public override Task Contains_inside_Sum_without_GroupBy(bool async) SELECT VALUE SUM((ARRAY_CONTAINS(@__cities_0, c["City"]) ? 1 : 0)) FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -2719,7 +2671,7 @@ public override Task Contains_inside_Count_without_GroupBy(bool async) SELECT VALUE COUNT(1) FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__cities_0, c["City"])) +WHERE ARRAY_CONTAINS(@__cities_0, c["City"]) """); }); @@ -2735,7 +2687,7 @@ public override Task Contains_inside_LongCount_without_GroupBy(bool async) SELECT VALUE COUNT(1) FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__cities_0, c["City"])) +WHERE ARRAY_CONTAINS(@__cities_0, c["City"]) """); }); @@ -2751,7 +2703,6 @@ public override Task Contains_inside_Max_without_GroupBy(bool async) SELECT VALUE MAX((ARRAY_CONTAINS(@__cities_0, c["City"]) ? 1 : 0)) FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -2767,7 +2718,6 @@ public override Task Contains_inside_Min_without_GroupBy(bool async) SELECT VALUE MIN((ARRAY_CONTAINS(@__cities_0, c["City"]) ? 1 : 0)) FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -2779,46 +2729,46 @@ public override Task Return_type_of_singular_operator_is_preserved(bool async) AssertSql( """ -SELECT c["CustomerID"], c["City"] +SELECT c["id"], c["City"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") OFFSET 0 LIMIT 1 """, // """ -SELECT c["CustomerID"], c["City"] +SELECT c["id"], c["City"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") OFFSET 0 LIMIT 1 """, // """ -SELECT c["CustomerID"], c["City"] +SELECT c["id"], c["City"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") OFFSET 0 LIMIT 2 """, // """ -SELECT c["CustomerID"], c["City"] +SELECT c["id"], c["City"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") OFFSET 0 LIMIT 2 """, // """ -SELECT c["CustomerID"], c["City"] +SELECT c["id"], c["City"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["CustomerID"], "A")) -ORDER BY c["CustomerID"] DESC +WHERE STARTSWITH(c["id"], "A") +ORDER BY c["id"] DESC OFFSET 0 LIMIT 1 """, // """ -SELECT c["CustomerID"], c["City"] +SELECT c["id"], c["City"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["CustomerID"], "A")) -ORDER BY c["CustomerID"] DESC +WHERE STARTSWITH(c["id"], "A") +ORDER BY c["id"] DESC OFFSET 0 LIMIT 1 """); }); diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs index c50c3d01e5d..c5783af4006 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindFunctionsQueryCosmosTest.cs @@ -36,7 +36,7 @@ public override Task String_StartsWith_Literal(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["ContactName"], "M")) +WHERE STARTSWITH(c["ContactName"], "M") """); }); @@ -52,7 +52,7 @@ public override Task String_StartsWith_Parameter(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["ContactName"], @__pattern_0)) +WHERE STARTSWITH(c["ContactName"], @__pattern_0) """); }); @@ -66,7 +66,7 @@ public override Task String_StartsWith_Identity(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["ContactName"], c["ContactName"])) +WHERE STARTSWITH(c["ContactName"], c["ContactName"]) """); }); @@ -80,7 +80,7 @@ public override Task String_StartsWith_Column(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["ContactName"], c["ContactName"])) +WHERE STARTSWITH(c["ContactName"], c["ContactName"]) """); }); @@ -94,7 +94,7 @@ public override Task String_StartsWith_MethodCall(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["ContactName"], "M")) +WHERE STARTSWITH(c["ContactName"], "M") """); }); @@ -108,7 +108,7 @@ public override Task String_StartsWith_with_StringComparison_Ordinal(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["CompanyName"], "Qu", false)) +WHERE STARTSWITH(c["CompanyName"], "Qu", false) """); }); @@ -122,7 +122,7 @@ public override Task String_StartsWith_with_StringComparison_OrdinalIgnoreCase(b """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["CompanyName"], "Qu", true)) +WHERE STARTSWITH(c["CompanyName"], "Qu", true) """); }); @@ -149,7 +149,7 @@ public override Task String_EndsWith_Literal(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ENDSWITH(c["ContactName"], "b")) +WHERE ENDSWITH(c["ContactName"], "b") """); }); @@ -165,7 +165,7 @@ public override Task String_EndsWith_Parameter(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ENDSWITH(c["ContactName"], @__pattern_0)) +WHERE ENDSWITH(c["ContactName"], @__pattern_0) """); }); @@ -179,7 +179,7 @@ public override Task String_EndsWith_Identity(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ENDSWITH(c["ContactName"], c["ContactName"])) +WHERE ENDSWITH(c["ContactName"], c["ContactName"]) """); }); @@ -193,7 +193,7 @@ public override Task String_EndsWith_Column(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ENDSWITH(c["ContactName"], c["ContactName"])) +WHERE ENDSWITH(c["ContactName"], c["ContactName"]) """); }); @@ -207,7 +207,7 @@ public override Task String_EndsWith_MethodCall(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ENDSWITH(c["ContactName"], "m")) +WHERE ENDSWITH(c["ContactName"], "m") """); }); @@ -221,7 +221,7 @@ public override Task String_EndsWith_with_StringComparison_Ordinal(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ENDSWITH(c["ContactName"], "DY", false)) +WHERE ENDSWITH(c["ContactName"], "DY", false) """); }); @@ -235,7 +235,7 @@ public override Task String_EndsWith_with_StringComparison_OrdinalIgnoreCase(boo """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ENDSWITH(c["ContactName"], "DY", true)) +WHERE ENDSWITH(c["ContactName"], "DY", true) """); }); @@ -262,7 +262,7 @@ public override Task String_Contains_Literal(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND CONTAINS(c["ContactName"], "M")) +WHERE CONTAINS(c["ContactName"], "M") """); }); @@ -275,7 +275,7 @@ public override Task String_Contains_Identity(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND CONTAINS(c["ContactName"], c["ContactName"])) +WHERE CONTAINS(c["ContactName"], c["ContactName"]) """); }); @@ -289,7 +289,7 @@ public override Task String_Contains_Column(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND CONTAINS(c["CompanyName"], c["ContactName"])) +WHERE CONTAINS(c["CompanyName"], c["ContactName"]) """); }); @@ -303,7 +303,7 @@ public override Task String_Contains_with_StringComparison_Ordinal(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND CONTAINS(c["ContactName"], "M", false)) +WHERE CONTAINS(c["ContactName"], "M", false) """); }); @@ -317,7 +317,7 @@ public override Task String_Contains_with_StringComparison_OrdinalIgnoreCase(boo """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND CONTAINS(c["ContactName"], "M", true)) +WHERE CONTAINS(c["ContactName"], "M", true) """); }); @@ -342,7 +342,7 @@ public override Task String_FirstOrDefault_MethodCall(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (LEFT(c["ContactName"], 1) = "A")) +WHERE (LEFT(c["ContactName"], 1) = "A") """); }); @@ -356,7 +356,7 @@ public override Task String_LastOrDefault_MethodCall(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (RIGHT(c["ContactName"], 1) = "s")) +WHERE (RIGHT(c["ContactName"], 1) = "s") """); }); @@ -370,7 +370,7 @@ public override Task String_Contains_MethodCall(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND CONTAINS(c["ContactName"], "M")) +WHERE CONTAINS(c["ContactName"], "M") """); }); @@ -1130,7 +1130,7 @@ public override Task Where_string_to_upper(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (UPPER(c["CustomerID"]) = "ALFKI")) +WHERE (UPPER(c["id"]) = "ALFKI") """); }); @@ -1144,7 +1144,7 @@ public override Task Where_string_to_lower(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (LOWER(c["CustomerID"]) = "alfki")) +WHERE (LOWER(c["id"]) = "alfki") """); }); @@ -1230,7 +1230,7 @@ public override Task Indexof_with_emptystring(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (INDEX_OF(c["Region"], "") = 0)) +WHERE (INDEX_OF(c["Region"], "") = 0) """); }); @@ -1244,7 +1244,7 @@ public override Task Indexof_with_one_constant_arg(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (INDEX_OF(c["ContactName"], "a") = 1)) +WHERE (INDEX_OF(c["ContactName"], "a") = 1) """); }); @@ -1260,7 +1260,7 @@ public override Task Indexof_with_one_parameter_arg(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (INDEX_OF(c["ContactName"], @__pattern_0) = 1)) +WHERE (INDEX_OF(c["ContactName"], @__pattern_0) = 1) """); }); @@ -1274,7 +1274,7 @@ public override Task Indexof_with_constant_starting_position(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (INDEX_OF(c["ContactName"], "a", 2) = 4)) +WHERE (INDEX_OF(c["ContactName"], "a", 2) = 4) """); }); @@ -1290,7 +1290,7 @@ public override Task Indexof_with_parameter_starting_position(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (INDEX_OF(c["ContactName"], "a", @__start_0) = 4)) +WHERE (INDEX_OF(c["ContactName"], "a", @__start_0) = 4) """); }); @@ -1304,7 +1304,7 @@ public override Task Replace_with_emptystring(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (REPLACE(c["ContactName"], "ia", "") = "Mar Anders")) +WHERE (REPLACE(c["ContactName"], "ia", "") = "Mar Anders") """); }); @@ -1318,7 +1318,7 @@ public override Task Replace_using_property_arguments(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (REPLACE(c["ContactName"], c["ContactName"], c["CustomerID"]) = c["CustomerID"])) +WHERE (REPLACE(c["ContactName"], c["ContactName"], c["id"]) = c["id"]) """); }); @@ -1332,7 +1332,7 @@ public override Task Substring_with_one_arg_with_zero_startindex(bool async) """ SELECT VALUE c["ContactName"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (SUBSTRING(c["CustomerID"], 0, LENGTH(c["CustomerID"])) = "ALFKI")) +WHERE (SUBSTRING(c["id"], 0, LENGTH(c["id"])) = "ALFKI") """); }); @@ -1346,7 +1346,7 @@ public override Task Substring_with_one_arg_with_constant(bool async) """ SELECT VALUE c["ContactName"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (SUBSTRING(c["CustomerID"], 1, LENGTH(c["CustomerID"])) = "LFKI")) +WHERE (SUBSTRING(c["id"], 1, LENGTH(c["id"])) = "LFKI") """); }); @@ -1362,7 +1362,7 @@ public override Task Substring_with_one_arg_with_closure(bool async) SELECT VALUE c["ContactName"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (SUBSTRING(c["CustomerID"], @__start_0, LENGTH(c["CustomerID"])) = "FKI")) +WHERE (SUBSTRING(c["id"], @__start_0, LENGTH(c["id"])) = "FKI") """); }); @@ -1376,7 +1376,7 @@ public override Task Substring_with_two_args_with_zero_startindex(bool async) """ SELECT VALUE LEFT(c["ContactName"], 3) FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") """); }); @@ -1390,7 +1390,7 @@ public override Task Substring_with_two_args_with_zero_length(bool async) """ SELECT VALUE SUBSTRING(c["ContactName"], 2, 0) FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") """); }); @@ -1404,7 +1404,7 @@ public override Task Substring_with_two_args_with_constant(bool async) """ SELECT VALUE SUBSTRING(c["ContactName"], 1, 3) FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") """); }); @@ -1420,7 +1420,7 @@ public override Task Substring_with_two_args_with_closure(bool async) SELECT VALUE SUBSTRING(c["ContactName"], @__start_0, 3) FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") """); }); @@ -1434,7 +1434,7 @@ public override Task Substring_with_two_args_with_Index_of(bool async) """ SELECT VALUE SUBSTRING(c["ContactName"], INDEX_OF(c["ContactName"], "a"), 3) FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") """); }); @@ -1470,9 +1470,8 @@ public override Task IsNullOrEmpty_in_projection(bool async) AssertSql( """ -SELECT c["CustomerID"], c["Region"] +SELECT c["id"], c["Region"] FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -1484,9 +1483,8 @@ public override Task IsNullOrEmpty_negated_in_projection(bool async) AssertSql( """ -SELECT c["CustomerID"], c["Region"] +SELECT c["id"], c["Region"] FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -1508,7 +1506,7 @@ public override Task TrimStart_without_arguments_in_predicate(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (LTRIM(c["ContactTitle"]) = "Owner")) +WHERE (LTRIM(c["ContactTitle"]) = "Owner") """); }); @@ -1538,7 +1536,7 @@ public override Task TrimEnd_without_arguments_in_predicate(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (RTRIM(c["ContactTitle"]) = "Owner")) +WHERE (RTRIM(c["ContactTitle"]) = "Owner") """); }); @@ -1568,7 +1566,7 @@ public override Task Trim_without_argument_in_predicate(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (TRIM(c["ContactTitle"]) = "Owner")) +WHERE (TRIM(c["ContactTitle"]) = "Owner") """); }); @@ -1600,8 +1598,7 @@ public override async Task Order_by_length_twice(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY LENGTH(c["CustomerID"]), c["CustomerID"] +ORDER BY LENGTH(c["id"]), c["id"] """); } } @@ -1621,7 +1618,7 @@ public override Task Static_string_equals_in_predicate(bool async) { await base.Static_string_equals_in_predicate(a); - AssertSql("ReadItem(None, Customer|ANATR)"); + AssertSql("ReadItem(None, ANATR)"); }); public override Task Static_equals_nullable_datetime_compared_to_non_nullable(bool async) @@ -1712,7 +1709,7 @@ public override Task Regex_IsMatch_MethodCall(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND RegexMatch(c["CustomerID"], "^T")) +WHERE RegexMatch(c["id"], "^T") """); }); @@ -1726,7 +1723,7 @@ public override Task Regex_IsMatch_MethodCall_constant_input(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND RegexMatch("ALFKI", c["CustomerID"])) +WHERE RegexMatch("ALFKI", c["id"]) """); }); @@ -1744,7 +1741,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND RegexMatch(c["CustomerID"], "^T")) +WHERE RegexMatch(c["id"], "^T") """); }); @@ -1762,7 +1759,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND RegexMatch(c["CustomerID"], "^T", "i")) +WHERE RegexMatch(c["id"], "^T", "i") """); }); @@ -1780,7 +1777,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND RegexMatch(c["CustomerID"], "^T", "m")) +WHERE RegexMatch(c["id"], "^T", "m") """); }); @@ -1798,7 +1795,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND RegexMatch(c["CustomerID"], "^T", "s")) +WHERE RegexMatch(c["id"], "^T", "s") """); }); @@ -1816,7 +1813,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND RegexMatch(c["CustomerID"], "^T", "x")) +WHERE RegexMatch(c["id"], "^T", "x") """); }); @@ -1835,7 +1832,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND RegexMatch(c["CustomerID"], "^T", "ix")) +WHERE RegexMatch(c["id"], "^T", "ix") """); }); @@ -1870,7 +1867,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STRINGEQUALS(c["CustomerID"], "alFkI", true)) +WHERE STRINGEQUALS(c["id"], "alFkI", true) """); }); @@ -1888,7 +1885,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STRINGEQUALS(c["CustomerID"], "alFkI", true)) +WHERE STRINGEQUALS(c["id"], "alFkI", true) """); }); @@ -1906,7 +1903,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STRINGEQUALS(c["CustomerID"], "ALFKI")) +WHERE STRINGEQUALS(c["id"], "ALFKI") """); }); @@ -1924,7 +1921,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STRINGEQUALS(c["CustomerID"], "ALFKI")) +WHERE STRINGEQUALS(c["id"], "ALFKI") """); }); @@ -1946,7 +1943,7 @@ public override Task String_Contains_constant_with_whitespace(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND CONTAINS(c["ContactName"], " ")) +WHERE CONTAINS(c["ContactName"], " ") """); }); @@ -1962,7 +1959,7 @@ public override Task String_Contains_parameter_with_whitespace(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND CONTAINS(c["ContactName"], @__pattern_0)) +WHERE CONTAINS(c["ContactName"], @__pattern_0) """); }); @@ -2018,7 +2015,7 @@ public override Task String_Contains_negated_in_predicate(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND NOT(CONTAINS(c["CompanyName"], c["ContactName"]))) +WHERE NOT(CONTAINS(c["CompanyName"], c["ContactName"])) """); }); @@ -2032,11 +2029,10 @@ public override Task String_Contains_negated_in_projection(bool async) """ SELECT VALUE { - "Id" : c["CustomerID"], + "Id" : c["id"], "Value" : NOT(CONTAINS(c["CompanyName"], c["ContactName"])) } FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindKeylessEntitiesQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindKeylessEntitiesQueryCosmosTest.cs index 0a602698988..c2058d52398 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindKeylessEntitiesQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindKeylessEntitiesQueryCosmosTest.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Microsoft.EntityFrameworkCore.Cosmos.Internal; using Xunit.Sdk; namespace Microsoft.EntityFrameworkCore.Query; @@ -33,7 +34,6 @@ public override Task KeylessEntity_simple(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -42,12 +42,11 @@ public override Task KeylessEntity_where_simple(bool async) async, async a => { await base.KeylessEntity_where_simple(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = "London")) +WHERE (c["City"] = "London") """); }); @@ -89,7 +88,7 @@ await Assert.ThrowsAsync( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["OrderCount"] > 0)) +WHERE (c["OrderCount"] > 0) """); } } @@ -134,7 +133,7 @@ public override async Task KeylessEntity_with_defining_query_and_correlated_coll public override async Task KeylessEntity_select_where_navigation(bool async) { - // Left join translation. Issue #17314. + // Cosmos client evaluation. Issue #17246. await AssertTranslationFailed(() => base.KeylessEntity_select_where_navigation(async)); AssertSql(); @@ -142,7 +141,7 @@ public override async Task KeylessEntity_select_where_navigation(bool async) public override async Task KeylessEntity_select_where_navigation_multi_level(bool async) { - // Left join translation. Issue #17314. + // Cosmos client evaluation. Issue #17246. await AssertTranslationFailed(() => base.KeylessEntity_select_where_navigation_multi_level(async)); AssertSql(); @@ -150,7 +149,7 @@ public override async Task KeylessEntity_select_where_navigation_multi_level(boo public override async Task KeylessEntity_with_included_navs_multi_level(bool async) { - // Left join translation. Issue #17314. + // Cosmos client evaluation. Issue #17246. await AssertTranslationFailed(() => base.KeylessEntity_with_included_navs_multi_level(async)); AssertSql(); @@ -177,12 +176,10 @@ public override Task Auto_initialized_view_set(bool async) async, async a => { await base.Auto_initialized_view_set(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -196,7 +193,6 @@ public override Task Count_over_keyless_entity(bool async) """ SELECT VALUE COUNT(1) FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindMiscellaneousQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindMiscellaneousQueryCosmosTest.cs index dcd18a3c5ca..712a380601d 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindMiscellaneousQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindMiscellaneousQueryCosmosTest.cs @@ -41,7 +41,6 @@ public virtual Task Simple_IQueryable(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -55,13 +54,13 @@ public override Task Shaper_command_caching_when_parameter_names_different(bool """ SELECT VALUE COUNT(1) FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") """, // """ SELECT VALUE COUNT(1) FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") """); }); @@ -87,7 +86,7 @@ public override Task Local_dictionary(bool async) { await base.Local_dictionary(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); public override Task Entity_equality_self(bool async) @@ -98,9 +97,9 @@ public override Task Entity_equality_self(bool async) AssertSql( """ -SELECT VALUE c["CustomerID"] +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = c["CustomerID"])) +WHERE (c["id"] = c["id"]) """); }); @@ -114,9 +113,9 @@ public override Task Entity_equality_local(bool async) """ @__entity_equality_local_0_CustomerID='ANATR' -SELECT VALUE c["CustomerID"] +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = @__entity_equality_local_0_CustomerID)) +WHERE (c["id"] = @__entity_equality_local_0_CustomerID) """); }); @@ -145,9 +144,9 @@ public override Task Entity_equality_local_inline(bool async) AssertSql( """ -SELECT VALUE c["CustomerID"] +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ANATR")) +WHERE (c["id"] = "ANATR") """); }); @@ -168,9 +167,9 @@ public override Task Entity_equality_null(bool async) AssertSql( """ -SELECT VALUE c["CustomerID"] +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = null)) +WHERE (c["id"] = null) """); }); @@ -182,9 +181,9 @@ public override Task Entity_equality_not_null(bool async) AssertSql( """ -SELECT VALUE c["CustomerID"] +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] != null)) +WHERE (c["id"] != null) """); }); @@ -478,7 +477,6 @@ await Assert.ThrowsAsync( """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Employee") ORDER BY (c["EmployeeID"] - c["EmployeeID"]) """); } @@ -563,7 +561,6 @@ public override Task Skip_Take(bool async) SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") ORDER BY c["ContactName"] OFFSET @__p_0 LIMIT @__p_1 """); @@ -654,7 +651,6 @@ public override Task Queryable_simple(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -668,7 +664,6 @@ public override Task Queryable_simple_anonymous(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -677,12 +672,10 @@ public override Task Queryable_nested_simple(bool async) async, async a => { await base.Queryable_nested_simple(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -698,7 +691,6 @@ public override Task Queryable_simple_anonymous_projection_subquery(bool async) SELECT VALUE c["City"] FROM root c -WHERE (c["Discriminator"] = "Customer") OFFSET 0 LIMIT @__p_0 """); }); @@ -715,7 +707,6 @@ public override Task Queryable_simple_anonymous_subquery(bool async) SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") OFFSET 0 LIMIT @__p_0 """); }); @@ -732,8 +723,7 @@ public override Task Take_simple(bool async) SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] OFFSET 0 LIMIT @__p_0 """); }); @@ -743,15 +733,13 @@ public override Task Take_simple_parameterized(bool async) async, async a => { await base.Take_simple_parameterized(a); - - AssertSql( - """ +AssertSql( + """ @__p_0='10' SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] OFFSET 0 LIMIT @__p_0 """); }); @@ -761,15 +749,13 @@ public override Task Take_simple_projection(bool async) async, async a => { await base.Take_simple_projection(a); - - AssertSql( - """ +AssertSql( + """ @__p_0='10' SELECT VALUE c["City"] FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] OFFSET 0 LIMIT @__p_0 """); }); @@ -779,15 +765,13 @@ public override Task Take_subquery_projection(bool async) async, async a => { await base.Take_subquery_projection(a); - - AssertSql( - """ +AssertSql( + """ @__p_0='2' SELECT VALUE c["City"] FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] OFFSET 0 LIMIT @__p_0 """); }); @@ -823,8 +807,7 @@ public override async Task Any_simple(bool async) """ SELECT VALUE EXISTS ( SELECT 1 - FROM root c - WHERE (c["Discriminator"] = "Customer")) + FROM root c) """); } } @@ -838,13 +821,12 @@ public override async Task Any_predicate(bool async) var exception = await Assert.ThrowsAsync(() => base.Any_predicate(async)); Assert.Equal(HttpStatusCode.BadRequest, exception.StatusCode); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE EXISTS ( SELECT 1 FROM root c - WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["ContactName"], "A"))) + WHERE STARTSWITH(c["ContactName"], "A")) AS c """); } } @@ -1284,15 +1266,13 @@ public override Task Skip_Take_Distinct(bool async) async, async a => { await base.Skip_Take_Distinct(a); - - AssertSql( - """ +AssertSql( + """ @__p_0='5' @__p_1='10' SELECT DISTINCT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") ORDER BY c["ContactName"] OFFSET @__p_0 LIMIT @__p_1 """); @@ -1316,7 +1296,6 @@ public override async Task Skip_Take_Any(bool async) SELECT VALUE EXISTS ( SELECT 1 FROM root c - WHERE (c["Discriminator"] = "Customer") ORDER BY c["ContactName"] OFFSET @__p_0 LIMIT @__p_1) """); @@ -1348,17 +1327,16 @@ public override async Task Skip_Take_Any_with_predicate(bool async) var exception = await Assert.ThrowsAsync(() => base.Skip_Take_Any_with_predicate(async)); Assert.Equal(HttpStatusCode.BadRequest, exception.StatusCode); - - AssertSql( - """ +AssertSql( + """ @__p_0='5' @__p_1='7' SELECT VALUE EXISTS ( SELECT 1 FROM root c - WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["CustomerID"], "C")) - ORDER BY c["CustomerID"] + WHERE STARTSWITH(c["id"], "C") + ORDER BY c["id"] OFFSET @__p_0 LIMIT @__p_1) """); } @@ -1373,16 +1351,15 @@ public override async Task Take_Any_with_predicate(bool async) var exception = await Assert.ThrowsAsync(() => base.Take_Any_with_predicate(async)); Assert.Equal(HttpStatusCode.BadRequest, exception.StatusCode); - - AssertSql( - """ +AssertSql( + """ @__p_0='5' SELECT VALUE EXISTS ( SELECT 1 FROM root c - WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["CustomerID"], "B")) - ORDER BY c["CustomerID"] + WHERE STARTSWITH(c["id"], "B") + ORDER BY c["id"] OFFSET 0 LIMIT @__p_0) """); } @@ -1393,13 +1370,11 @@ public override Task OrderBy(bool async) async, async a => { await base.OrderBy(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); }); @@ -1416,7 +1391,6 @@ await Assert.ThrowsAsync( """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") ORDER BY true """); } @@ -1430,12 +1404,10 @@ public override async Task OrderBy_integer(bool async) // Cosmos client evaluation. Issue #17246. await Assert.ThrowsAsync( async () => await base.OrderBy_integer(async)); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") ORDER BY 3 """); } @@ -1456,7 +1428,6 @@ await Assert.ThrowsAsync( SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") ORDER BY @__param_0 """); } @@ -1467,13 +1438,11 @@ public override Task OrderBy_anon(bool async) async, async a => { await base.OrderBy_anon(a); - - AssertSql( - """ -SELECT VALUE c["CustomerID"] +AssertSql( + """ +SELECT VALUE c["id"] AS CustomerID FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); }); @@ -1482,13 +1451,11 @@ public override Task OrderBy_anon2(bool async) async, async a => { await base.OrderBy_anon2(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); }); @@ -1501,7 +1468,9 @@ public override async Task OrderBy_client_mixed(bool async) public override async Task OrderBy_multiple_queries(bool async) { - await base.OrderBy_multiple_queries(async); + await AssertTranslationFailedWithDetails( + () => base.Where_join_orderby_join_select(async), + CosmosStrings.MultipleRootEntityTypesReferencedInQuery(nameof(Order), nameof(Customer))); AssertSql(); } @@ -1550,12 +1519,10 @@ public override async Task OrderBy_shadow(bool async) // Cosmos client evaluation. Issue #17246. await Assert.ThrowsAsync( async () => await base.OrderBy_shadow(async)); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Employee") ORDER BY c["Title"], c["EmployeeID"] """); } @@ -1574,7 +1541,7 @@ await Assert.ThrowsAsync( """ SELECT VALUE c["City"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["CustomerID"], "A")) +WHERE STARTSWITH(c["id"], "A") ORDER BY c["Country"], c["City"] """); } @@ -1594,8 +1561,7 @@ public override async Task OrderBy_ThenBy_Any(bool async) """ SELECT VALUE EXISTS ( SELECT 1 - FROM root c - WHERE (c["Discriminator"] = "Customer")) + FROM root c) """); } } @@ -1812,8 +1778,7 @@ await Assert.ThrowsAsync( """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY ((c["Region"] != null) ? c["Region"] : "ZZ"), c["CustomerID"] +ORDER BY ((c["Region"] != null) ? c["Region"] : "ZZ"), c["id"] """); } } @@ -1826,18 +1791,16 @@ public override async Task Select_null_coalesce_operator(bool async) // Cosmos client evaluation. Issue #17246. await Assert.ThrowsAsync( async () => await base.Select_null_coalesce_operator(async)); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE { - "CustomerID" : c["CustomerID"], + "CustomerID" : c["id"], "CompanyName" : c["CompanyName"], "Region" : ((c["Region"] != null) ? c["Region"] : "ZZ") } FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY ((c["Region"] != null) ? c["Region"] : "ZZ"), c["CustomerID"] +ORDER BY ((c["Region"] != null) ? c["Region"] : "ZZ"), c["id"] """); } } @@ -1850,13 +1813,11 @@ public override async Task OrderBy_conditional_operator(bool async) // Cosmos client evaluation. Issue #17246. await Assert.ThrowsAsync( async () => await base.OrderBy_conditional_operator(async)); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY ((c["Region"] = null) ? "ZZ" : c["Region"]), c["CustomerID"] +ORDER BY ((c["Region"] = null) ? "ZZ" : c["Region"]), c["id"] """); } } @@ -1871,7 +1832,6 @@ public override Task OrderBy_conditional_operator_where_condition_false(bool asy """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") ORDER BY c["City"] """); }); @@ -1889,7 +1849,6 @@ await Assert.ThrowsAsync( """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") ORDER BY (c["Region"] = "ASK") """); } @@ -1900,17 +1859,15 @@ public override Task Projection_null_coalesce_operator(bool async) async, async a => { await base.Projection_null_coalesce_operator(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE { - "CustomerID" : c["CustomerID"], + "CustomerID" : c["id"], "CompanyName" : c["CompanyName"], "Region" : ((c["Region"] != null) ? c["Region"] : "ZZ") } FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -1919,12 +1876,11 @@ public override Task Filter_coalesce_operator(bool async) async, async a => { await base.Filter_coalesce_operator(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (((c["ContactName"] != null) ? c["ContactName"] : c["CompanyName"]) = "Liz Nixon")) +WHERE (((c["ContactName"] != null) ? c["ContactName"] : c["CompanyName"]) = "Liz Nixon") """); }); @@ -1952,12 +1908,11 @@ await Assert.ThrowsAsync( SELECT VALUE { - "CustomerID" : c["CustomerID"], + "CustomerID" : c["id"], "CompanyName" : c["CompanyName"], "Region" : ((c["Region"] != null) ? c["Region"] : "ZZ") } FROM root c -WHERE (c["Discriminator"] = "Customer") ORDER BY ((c["Region"] != null) ? c["Region"] : "ZZ") OFFSET 0 LIMIT @__p_0 """); @@ -1999,12 +1954,10 @@ public override async Task Selected_column_can_coalesce(bool async) // Unsupported ORDER BY clause. await Assert.ThrowsAsync( () => base.Selected_column_can_coalesce(async)); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") ORDER BY ((c["Region"] != null) ? c["Region"] : "ZZ") """); } @@ -2140,7 +2093,7 @@ public override Task Environment_newline_is_funcletized(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND CONTAINS(c["CustomerID"], @__NewLine_0)) +WHERE CONTAINS(c["id"], @__NewLine_0) """, sql); }); @@ -2168,17 +2121,15 @@ public override async Task Select_bitwise_or(bool async) { // Bitwise operators on booleans. Issue #13168. await Assert.ThrowsAsync(() => base.Select_bitwise_or(async)); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE { - "CustomerID" : c["CustomerID"], - "Value" : ((c["CustomerID"] = "ALFKI") | (c["CustomerID"] = "ANATR")) + "CustomerID" : c["id"], + "Value" : ((c["id"] = "ALFKI") | (c["id"] = "ANATR")) } FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); } } @@ -2190,17 +2141,15 @@ public override async Task Select_bitwise_or_multiple(bool async) { // Bitwise operators on booleans. Issue #13168. await Assert.ThrowsAsync(() => base.Select_bitwise_or_multiple(async)); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE { - "CustomerID" : c["CustomerID"], - "Value" : (((c["CustomerID"] = "ALFKI") | (c["CustomerID"] = "ANATR")) | (c["CustomerID"] = "ANTON")) + "CustomerID" : c["id"], + "Value" : (((c["id"] = "ALFKI") | (c["id"] = "ANATR")) | (c["id"] = "ANTON")) } FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); } } @@ -2212,17 +2161,15 @@ public override async Task Select_bitwise_and(bool async) { // Bitwise operators on booleans. Issue #13168. await Assert.ThrowsAsync(() => base.Select_bitwise_and(async)); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE { - "CustomerID" : c["CustomerID"], - "Value" : ((c["CustomerID"] = "ALFKI") & (c["CustomerID"] = "ANATR")) + "CustomerID" : c["id"], + "Value" : ((c["id"] = "ALFKI") & (c["id"] = "ANATR")) } FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); } } @@ -2234,17 +2181,15 @@ public override async Task Select_bitwise_and_or(bool async) { // Bitwise operators on booleans. Issue #13168. await Assert.ThrowsAsync(() => base.Select_bitwise_and_or(async)); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE { - "CustomerID" : c["CustomerID"], - "Value" : (((c["CustomerID"] = "ALFKI") & (c["CustomerID"] = "ANATR")) | (c["CustomerID"] = "ANTON")) + "CustomerID" : c["id"], + "Value" : (((c["id"] = "ALFKI") & (c["id"] = "ANATR")) | (c["id"] = "ANTON")) } FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); } } @@ -2256,12 +2201,11 @@ public override async Task Where_bitwise_or_with_logical_or(bool async) { // Bitwise operators on booleans. Issue #13168. await Assert.ThrowsAsync(() => base.Where_bitwise_or_with_logical_or(async)); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (((c["CustomerID"] = "ALFKI") | (c["CustomerID"] = "ANATR")) OR (c["CustomerID"] = "ANTON"))) +WHERE (((c["id"] = "ALFKI") | (c["id"] = "ANATR")) OR (c["id"] = "ANTON")) """); } } @@ -2271,12 +2215,11 @@ public override Task Where_bitwise_and_with_logical_and(bool async) async, async a => { await base.Where_bitwise_and_with_logical_and(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (((c["CustomerID"] = "ALFKI") & (c["CustomerID"] = "ANATR")) AND (c["CustomerID"] = "ANTON"))) +WHERE (((c["id"] = "ALFKI") & (c["id"] = "ANATR")) AND (c["id"] = "ANTON")) """); }); @@ -2287,12 +2230,11 @@ public override async Task Where_bitwise_or_with_logical_and(bool async) { // Bitwise operators on booleans. Issue #13168. await Assert.ThrowsAsync(() => base.Where_bitwise_or_with_logical_and(async)); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (((c["CustomerID"] = "ALFKI") | (c["CustomerID"] = "ANATR")) AND (c["Country"] = "Germany"))) +WHERE (((c["id"] = "ALFKI") | (c["id"] = "ANATR")) AND (c["Country"] = "Germany")) """); } } @@ -2302,12 +2244,11 @@ public override Task Where_bitwise_and_with_logical_or(bool async) async, async a => { await base.Where_bitwise_and_with_logical_or(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (((c["CustomerID"] = "ALFKI") & (c["CustomerID"] = "ANATR")) OR (c["CustomerID"] = "ANTON"))) +WHERE (((c["id"] = "ALFKI") & (c["id"] = "ANATR")) OR (c["id"] = "ANTON")) """); }); @@ -2376,17 +2317,15 @@ public override async Task Select_bitwise_or_with_logical_or(bool async) { // Bitwise operators on booleans. Issue #13168. await Assert.ThrowsAsync(() => base.Select_bitwise_or_with_logical_or(async)); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE { - "CustomerID" : c["CustomerID"], - "Value" : (((c["CustomerID"] = "ALFKI") | (c["CustomerID"] = "ANATR")) OR (c["CustomerID"] = "ANTON")) + "CustomerID" : c["id"], + "Value" : (((c["id"] = "ALFKI") | (c["id"] = "ANATR")) OR (c["id"] = "ANTON")) } FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); } } @@ -2398,17 +2337,15 @@ public override async Task Select_bitwise_and_with_logical_and(bool async) { // Bitwise operators on booleans. Issue #13168. await Assert.ThrowsAsync(() => base.Select_bitwise_and_with_logical_and(async)); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE { - "CustomerID" : c["CustomerID"], - "Value" : (((c["CustomerID"] = "ALFKI") & (c["CustomerID"] = "ANATR")) AND (c["CustomerID"] = "ANTON")) + "CustomerID" : c["id"], + "Value" : (((c["id"] = "ALFKI") & (c["id"] = "ANATR")) AND (c["id"] = "ANTON")) } FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); } } @@ -2751,7 +2688,8 @@ public override async Task DefaultIfEmpty_in_subquery_nested_filter_order_compar // Cosmos client evaluation. Issue #17246. await AssertTranslationFailed(() => base.DefaultIfEmpty_in_subquery_nested_filter_order_comparison(async)); - AssertSql(); + AssertSql( +); } public override async Task OrderBy_skip_take(bool async) @@ -2770,7 +2708,6 @@ await Assert.ThrowsAsync( SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") ORDER BY c["ContactTitle"], c["ContactName"] OFFSET @__p_0 LIMIT @__p_1 """); @@ -2810,7 +2747,8 @@ await AssertTranslationFailedWithDetails( () => base.OrderBy_skip_take_skip_take_skip(async), CosmosStrings.LimitOffsetNotSupportedInSubqueries); - AssertSql(); + AssertSql( +); } public override async Task OrderBy_skip_take_distinct(bool async) @@ -2829,7 +2767,6 @@ await Assert.ThrowsAsync( SELECT DISTINCT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") ORDER BY c["ContactTitle"], c["ContactName"] OFFSET @__p_0 LIMIT @__p_1 """); @@ -2974,12 +2911,11 @@ public override Task Anonymous_member_distinct_where(bool async) async, async a => { await base.Anonymous_member_distinct_where(a); - - AssertSql( - """ -SELECT DISTINCT VALUE c["CustomerID"] +AssertSql( + """ +SELECT DISTINCT VALUE c["id"] AS CustomerID FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") """); }); @@ -3006,12 +2942,11 @@ public override Task Anonymous_complex_distinct_where(bool async) async, async a => { await base.Anonymous_complex_distinct_where(a); - - AssertSql( - """ -SELECT DISTINCT VALUE (c["CustomerID"] || c["City"]) +AssertSql( + """ +SELECT DISTINCT VALUE (c["id"] || c["City"]) FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((c["CustomerID"] || c["City"]) = "ALFKIBerlin")) +WHERE ((c["id"] || c["City"]) = "ALFKIBerlin") """); }); @@ -3029,8 +2964,8 @@ public override async Task Anonymous_complex_distinct_result(bool async) { // Cosmos client evaluation. Issue #17246. await AssertTranslationFailed(() => base.Anonymous_complex_distinct_result(async)); - - AssertSql(); + AssertSql( +); } public override async Task Anonymous_complex_orderby(bool async) @@ -3043,10 +2978,9 @@ await Assert.ThrowsAsync( AssertSql( """ -SELECT VALUE (c["CustomerID"] || c["City"]) +SELECT VALUE (c["id"] || c["City"]) FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY (c["CustomerID"] || c["City"]) +ORDER BY (c["id"] || c["City"]) """); } } @@ -3055,8 +2989,8 @@ public override async Task Anonymous_subquery_orderby(bool async) { // Cosmos client evaluation. Issue #17246. await AssertTranslationFailed(() => base.Anonymous_subquery_orderby(async)); - - AssertSql(); +AssertSql( +); } public override Task DTO_member_distinct_where(bool async) @@ -3064,12 +2998,11 @@ public override Task DTO_member_distinct_where(bool async) async, async a => { await base.DTO_member_distinct_where(a); - - AssertSql( - """ -SELECT DISTINCT VALUE c["CustomerID"] +AssertSql( + """ +SELECT DISTINCT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") """); }); @@ -3096,12 +3029,11 @@ public override Task DTO_complex_distinct_where(bool async) async, async a => { await base.DTO_complex_distinct_where(a); - - AssertSql( - """ -SELECT DISTINCT VALUE (c["CustomerID"] || c["City"]) +AssertSql( + """ +SELECT DISTINCT VALUE (c["id"] || c["City"]) FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((c["CustomerID"] || c["City"]) = "ALFKIBerlin")) +WHERE ((c["id"] || c["City"]) = "ALFKIBerlin") """); }); @@ -3131,13 +3063,11 @@ public override async Task DTO_complex_orderby(bool async) // Cosmos client evaluation. Issue #17246. await Assert.ThrowsAsync( async () => await base.DTO_complex_orderby(async)); - - AssertSql( - """ -SELECT VALUE (c["CustomerID"] || c["City"]) +AssertSql( + """ +SELECT VALUE (c["id"] || c["City"]) FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY (c["CustomerID"] || c["City"]) +ORDER BY (c["id"] || c["City"]) """); } } @@ -3360,8 +3290,8 @@ public override async Task Select_distinct_sum(bool async) { // Cosmos client evaluation. Issue #17246. await AssertTranslationFailed(() => base.Select_distinct_sum(async)); - - AssertSql(); +AssertSql( +); } public override Task Comparing_to_fixed_string_parameter(bool async) @@ -3369,14 +3299,13 @@ public override Task Comparing_to_fixed_string_parameter(bool async) async, async a => { await base.Comparing_to_fixed_string_parameter(a); - - AssertSql( - """ +AssertSql( + """ @__prefix_0='A' -SELECT VALUE c["CustomerID"] +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["CustomerID"], @__prefix_0)) +WHERE STARTSWITH(c["id"], @__prefix_0) """); }); @@ -3404,10 +3333,10 @@ public override Task Comparing_entity_to_null_using_Equals(bool async) AssertSql( """ -SELECT VALUE c["CustomerID"] +SELECT VALUE c["id"] FROM root c -WHERE (((c["Discriminator"] = "Customer") AND STARTSWITH(c["CustomerID"], "A")) AND NOT((c["CustomerID"] = null))) -ORDER BY c["CustomerID"] +WHERE (STARTSWITH(c["id"], "A") AND NOT((c["id"] = null))) +ORDER BY c["id"] """); }); @@ -3448,12 +3377,11 @@ public override Task Comparing_collection_navigation_to_null(bool async) async, async a => { await base.Comparing_collection_navigation_to_null(a); - - AssertSql( - """ -SELECT VALUE c["CustomerID"] +AssertSql( + """ +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = null)) +WHERE (c["id"] = null) """); }); @@ -3462,7 +3390,8 @@ public override async Task Comparing_collection_navigation_to_null_complex(bool // Cosmos client evaluation. Issue #17246. await AssertTranslationFailed(() => base.Comparing_collection_navigation_to_null_complex(async)); - AssertSql(); + AssertSql( +); } public override Task Compare_collection_navigation_with_itself(bool async) @@ -3470,12 +3399,11 @@ public override Task Compare_collection_navigation_with_itself(bool async) async, async a => { await base.Compare_collection_navigation_with_itself(a); - - AssertSql( - """ -SELECT VALUE c["CustomerID"] +AssertSql( + """ +SELECT VALUE c["id"] FROM root c -WHERE (((c["Discriminator"] = "Customer") AND STARTSWITH(c["CustomerID"], "A")) AND (c["CustomerID"] = c["CustomerID"])) +WHERE (STARTSWITH(c["id"], "A") AND (c["id"] = c["id"])) """); }); @@ -3500,7 +3428,8 @@ public override async Task Compare_two_collection_navigations_with_different_pro // Cosmos client evaluation. Issue #17246. await AssertTranslationFailed(() => base.Compare_two_collection_navigations_with_different_property_chains(async)); - AssertSql(); + AssertSql( +); } public override Task OrderBy_ThenBy_same_column_different_direction(bool async) @@ -3508,13 +3437,12 @@ public override Task OrderBy_ThenBy_same_column_different_direction(bool async) async, async a => { await base.OrderBy_ThenBy_same_column_different_direction(a); - - AssertSql( - """ -SELECT VALUE c["CustomerID"] +AssertSql( + """ +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["CustomerID"], "A")) -ORDER BY c["CustomerID"] +WHERE STARTSWITH(c["id"], "A") +ORDER BY c["id"] """); }); @@ -3523,13 +3451,12 @@ public override Task OrderBy_OrderBy_same_column_different_direction(bool async) async, async a => { await base.OrderBy_OrderBy_same_column_different_direction(a); - - AssertSql( - """ -SELECT VALUE c["CustomerID"] +AssertSql( + """ +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["CustomerID"], "A")) -ORDER BY c["CustomerID"] DESC +WHERE STARTSWITH(c["id"], "A") +ORDER BY c["id"] DESC """); }); @@ -3556,16 +3483,14 @@ public override Task OrderBy_Dto_projection_skip_take(bool async) async, async a => { await base.OrderBy_Dto_projection_skip_take(a); - - AssertSql( - """ +AssertSql( + """ @__p_0='5' @__p_1='10' -SELECT VALUE c["CustomerID"] +SELECT VALUE c["id"] FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] OFFSET @__p_0 LIMIT @__p_1 """); }); @@ -3574,8 +3499,8 @@ public override async Task Join_take_count_works(bool async) { // Cosmos client evaluation. Issue #17246. await AssertTranslationFailed(() => base.Join_take_count_works(async)); - - AssertSql(); +AssertSql( +); } public override async Task OrderBy_empty_list_contains(bool async) @@ -3585,15 +3510,13 @@ public override async Task OrderBy_empty_list_contains(bool async) { await Assert.ThrowsAsync( async () => await base.OrderBy_empty_list_contains(async)); - - AssertSql( - """ +AssertSql( + """ @__list_0='[]' SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY ARRAY_CONTAINS(@__list_0, c["CustomerID"]) +ORDER BY ARRAY_CONTAINS(@__list_0, c["id"]) """); } } @@ -3612,8 +3535,7 @@ await Assert.ThrowsAsync( SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY NOT(ARRAY_CONTAINS(@__list_0, c["CustomerID"])) +ORDER BY NOT(ARRAY_CONTAINS(@__list_0, c["id"])) """); } } @@ -3714,13 +3636,13 @@ public override Task Can_convert_manually_build_expression_with_default(bool asy """ SELECT VALUE COUNT(1) FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] != null)) +WHERE (c["City"] != null) """, // """ SELECT VALUE COUNT(1) FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] != null)) +WHERE (c["City"] != null) """); }); @@ -3780,8 +3702,7 @@ await Assert.ThrowsAsync( """ SELECT VALUE c["City"] FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] DESC, c["Country"] +ORDER BY c["id"] DESC, c["Country"] """); } } @@ -3794,13 +3715,11 @@ public override async Task OrderByDescending_ThenByDescending(bool async) // Cosmos client evaluation. Issue #17246. await Assert.ThrowsAsync( async () => await base.OrderByDescending_ThenByDescending(async)); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c["City"] FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] DESC, c["Country"] DESC +ORDER BY c["id"] DESC, c["Country"] DESC """); } } @@ -3810,7 +3729,8 @@ public override async Task OrderBy_Join(bool async) // Cosmos client evaluation. Issue #17246. await AssertTranslationFailed(() => base.OrderBy_Join(async)); - AssertSql(); + AssertSql( +); } public override async Task OrderBy_ThenBy(bool async) @@ -3826,8 +3746,7 @@ await Assert.ThrowsAsync( """ SELECT VALUE c["City"] FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"], c["Country"] +ORDER BY c["id"], c["Country"] """); } } @@ -3845,8 +3764,8 @@ await Assert.ThrowsAsync( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = "London")) -ORDER BY c["City"], c["CustomerID"] +WHERE (c["City"] = "London") +ORDER BY c["City"], c["id"] """); } } @@ -3926,7 +3845,6 @@ public override Task Select_Property_when_shadow_unconstrained_generic_method(bo """ SELECT VALUE c["Title"] FROM root c -WHERE (c["Discriminator"] = "Employee") """); }); @@ -3945,14 +3863,13 @@ public override Task Where_Property_when_shadow_unconstrained_generic_method(boo async, async a => { await base.Where_Property_when_shadow_unconstrained_generic_method(a); - - AssertSql( - """ +AssertSql( + """ @__value_0='Sales Representative' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["Title"] = @__value_0)) +WHERE (c["Title"] = @__value_0) """); }); @@ -4181,7 +4098,7 @@ public override Task Entity_equality_with_null_coalesce_client_side(bool async) { await base.Entity_equality_with_null_coalesce_client_side(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); public override Task Entity_equality_contains_with_list_of_null(bool async) @@ -4189,12 +4106,11 @@ public override Task Entity_equality_contains_with_list_of_null(bool async) async, async a => { await base.Entity_equality_contains_with_list_of_null(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND c["CustomerID"] IN (null, "ALFKI")) +WHERE c["id"] IN (null, "ALFKI") """); }); @@ -4392,13 +4308,11 @@ public override Task AsEnumerable_over_string(bool async) async, async a => { await base.AsEnumerable_over_string(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c["City"] FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); }); @@ -4421,12 +4335,10 @@ public override Task Cast_results_to_object(bool async) async, async a => { await base.Cast_results_to_object(a); - AssertSql( """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -4440,7 +4352,6 @@ public override Task Null_Coalesce_Short_Circuit_with_server_correlated_leftover """ SELECT VALUE false FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -4478,12 +4389,10 @@ public override async Task Throws_on_concurrent_query_first(bool async) if (async) { await base.Throws_on_concurrent_query_first(async); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); } } @@ -4493,12 +4402,11 @@ public override Task Entity_equality_through_include(bool async) async, async a => { await base.Entity_equality_through_include(a); - - AssertSql( - """ -SELECT VALUE c["CustomerID"] +AssertSql( + """ +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = null)) +WHERE (c["id"] = null) """); }); @@ -4526,7 +4434,6 @@ public override Task OrderBy_scalar_primitive(bool async) """ SELECT VALUE c["EmployeeID"] FROM root c -WHERE (c["Discriminator"] = "Employee") ORDER BY c["EmployeeID"] """); }); @@ -4545,13 +4452,11 @@ public override Task OrderBy_Select(bool async) async, async a => { await base.OrderBy_Select(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c["ContactName"] FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); }); @@ -4583,7 +4488,6 @@ await AssertQuery( """ SELECT VALUE LENGTH(c["Region"]) FROM root c -WHERE (c["Discriminator"] = "Customer") """); } } @@ -4593,13 +4497,11 @@ public override Task ToList_over_string(bool async) async, async a => { await base.ToList_over_string(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c["City"] FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); }); @@ -4629,12 +4531,10 @@ public override Task ToListAsync_with_canceled_token() true, async _ => { await base.ToListAsync_with_canceled_token(); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Employee") """); }); @@ -4648,11 +4548,10 @@ public override Task Ternary_should_not_evaluate_both_sides(bool async) """ SELECT VALUE { - "CustomerID" : c["CustomerID"], + "CustomerID" : c["id"], "Data1" : "none" } FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -4661,13 +4560,11 @@ public override Task Entity_equality_orderby(bool async) async, async a => { await base.Entity_equality_orderby(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); }); @@ -4676,12 +4573,10 @@ public override Task Load_should_track_results(bool async) async, async a => { await base.Load_should_track_results(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -4691,7 +4586,7 @@ public override Task Null_parameter_name_works(bool async) { await base.Null_parameter_name_works(a); - AssertSql("ReadItem(None, Customer|null)"); + AssertSql("ReadItem(None, null)"); }); public override Task Where_Property_shadow_closure(bool async) @@ -4699,22 +4594,21 @@ public override Task Where_Property_shadow_closure(bool async) async, async a => { await base.Where_Property_shadow_closure(a); - - AssertSql( - """ +AssertSql( + """ @__value_0='Sales Representative' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["Title"] = @__value_0)) +WHERE (c["Title"] = @__value_0) """, - // - """ + // + """ @__value_0='Steven' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["FirstName"] = @__value_0)) +WHERE (c["FirstName"] = @__value_0) """); }); @@ -4728,9 +4622,9 @@ public override Task Entity_equality_local_double_check(bool async) """ @__entity_equality_local_0_CustomerID='ANATR' -SELECT VALUE c["CustomerID"] +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((c["CustomerID"] = @__entity_equality_local_0_CustomerID) AND (@__entity_equality_local_0_CustomerID = c["CustomerID"]))) +WHERE ((c["id"] = @__entity_equality_local_0_CustomerID) AND (@__entity_equality_local_0_CustomerID = c["id"])) """); }); @@ -4744,8 +4638,7 @@ public override Task ToArray_over_string(bool async) """ SELECT VALUE c["City"] FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); }); @@ -4754,12 +4647,11 @@ public override Task MemberInitExpression_NewExpression_is_funcletized_even_when async, async a => { await base.MemberInitExpression_NewExpression_is_funcletized_even_when_bindings_are_not_evaluatable(a); - - AssertSql( - """ -SELECT VALUE c["CustomerID"] +AssertSql( + """ +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["CustomerID"], "A")) +WHERE STARTSWITH(c["id"], "A") """); }); @@ -4806,7 +4698,7 @@ public override Task Where_Property_when_shadow(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["Title"] = "Sales Representative")) +WHERE (c["Title"] = "Sales Representative") """); }); @@ -4816,12 +4708,10 @@ public override async Task Throws_on_concurrent_query_list(bool async) if (async) { await base.Throws_on_concurrent_query_list(async); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); } } @@ -4864,13 +4754,11 @@ public override Task Context_based_client_method(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """, // """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -4879,13 +4767,11 @@ public override Task OrderByDescending(bool async) async, async a => { await base.OrderByDescending(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c["City"] FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] DESC +ORDER BY c["id"] DESC """); }); @@ -4899,7 +4785,6 @@ public override Task Select_Property_when_shadow(bool async) """ SELECT VALUE c["Title"] FROM root c -WHERE (c["Discriminator"] = "Employee") """); }); @@ -4915,8 +4800,7 @@ public override Task Skip_0_Take_0_works_when_parameter(bool async) SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] OFFSET @__p_0 LIMIT @__p_0 """, // @@ -4925,8 +4809,7 @@ OFFSET @__p_0 LIMIT @__p_0 SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] OFFSET @__p_0 LIMIT @__p_0 """); }); @@ -5181,14 +5064,13 @@ public override Task Contains_over_concatenated_columns_with_different_sizes(boo async, async a => { await base.Contains_over_concatenated_columns_with_different_sizes(a); - - AssertSql( - """ +AssertSql( + """ @__data_0='["ALFKIAlfreds Futterkiste","ANATRAna Trujillo Emparedados y helados"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__data_0, (c["CustomerID"] || c["CompanyName"]))) +WHERE ARRAY_CONTAINS(@__data_0, (c["id"] || c["CompanyName"])) """); }); @@ -5204,7 +5086,7 @@ public override Task Contains_over_concatenated_column_and_constant(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__data_0, (c["CustomerID"] || "SomeConstant"))) +WHERE ARRAY_CONTAINS(@__data_0, (c["id"] || "SomeConstant")) """); }); @@ -5221,15 +5103,14 @@ public override Task Contains_over_concatenated_column_and_parameter(bool async) async, async a => { await base.Contains_over_concatenated_column_and_parameter(a); - - AssertSql( - """ +AssertSql( + """ @__data_1='["ALFKISomeVariable","ANATRSomeVariable","ALFKIX"]' @__someVariable_0='SomeVariable' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__data_1, (c["CustomerID"] || @__someVariable_0))) +WHERE ARRAY_CONTAINS(@__data_1, (c["id"] || @__someVariable_0)) """); }); @@ -5245,7 +5126,7 @@ public override Task Contains_over_concatenated_parameter_and_constant(bool asyn SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND @__Contains_0) +WHERE @__Contains_0 """); }); @@ -5254,15 +5135,14 @@ public override Task Compiler_generated_local_closure_produces_valid_parameter_n async, async a => { await base.Compiler_generated_local_closure_produces_valid_parameter_name(a); - - AssertSql( - """ +AssertSql( + """ @__customerId_0='ALFKI' @__details_City_1='Berlin' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((c["CustomerID"] = @__customerId_0) AND (c["City"] = @__details_City_1))) +WHERE ((c["id"] = @__customerId_0) AND (c["City"] = @__details_City_1)) """); }); @@ -5272,7 +5152,7 @@ public override Task Static_member_access_gets_parameterized_within_larger_evalu { await base.Static_member_access_gets_parameterized_within_larger_evaluatable(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); #region ToPageAsync @@ -5311,7 +5191,6 @@ public virtual async Task ToPageAsync() """ SELECT VALUE COUNT(1) FROM root c -WHERE (c["Discriminator"] = "Customer") """, // """ @@ -5379,22 +5258,19 @@ FROM root c """ SELECT VALUE c["CustomerID"] FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """, // """ SELECT VALUE c["CustomerID"] FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """, // """ SELECT VALUE c["CustomerID"] FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); } @@ -5412,19 +5288,16 @@ public virtual async Task ToPageAsync_with_exact_maxItemCount() Assert.Equal("ALFKI", onlyPage.Values[0].CustomerID); Assert.Equal("WOLZA", onlyPage.Values[^1].CustomerID); Assert.Null(onlyPage.ContinuationToken); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE COUNT(1) FROM root c -WHERE (c["Discriminator"] = "Customer") """, - // - """ + // + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); } @@ -5439,12 +5312,11 @@ public virtual async Task ToPageAsync_does_not_use_ReadItem() Assert.Equal("ALFKI", onlyPage.Values[0].CustomerID); Assert.Null(onlyPage.ContinuationToken); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") """); } diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindQueryCosmosFixture.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindQueryCosmosFixture.cs index e8fb657be4b..1576130227b 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindQueryCosmosFixture.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindQueryCosmosFixture.cs @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using Microsoft.EntityFrameworkCore.TestModels.Northwind; +using Product = Microsoft.EntityFrameworkCore.TestModels.Northwind.Product; namespace Microsoft.EntityFrameworkCore.Query; @@ -36,20 +37,46 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con { base.OnModelCreating(modelBuilder, context); - modelBuilder - .Entity() - .HasDiscriminator("Discriminator").HasValue("Customer"); + modelBuilder.Entity().ToContainer("Customers"); + modelBuilder.Entity().ToContainer("Employees"); - modelBuilder - .Entity() + modelBuilder.Entity() + .IncludeRootDiscriminatorInJsonId() + .ToContainer("ProductsAndOrders"); + + modelBuilder.Entity() + .IncludeRootDiscriminatorInJsonId() + .ToContainer("ProductsAndOrders"); + + modelBuilder.Entity() + .IncludeRootDiscriminatorInJsonId() + .ToContainer("ProductsAndOrders"); + + modelBuilder.Entity() + .ToContainer("ProductsAndOrders") + .IncludeRootDiscriminatorInJsonId() .HasDiscriminator("Discriminator").HasValue("Order"); modelBuilder .Entity() + .ToContainer("ProductsAndOrders") + .IncludeRootDiscriminatorInJsonId() .HasDiscriminator("Discriminator").HasValue("Product"); + modelBuilder + .Entity() + .ToContainer("ProductsAndOrders") + .IncludeRootDiscriminatorInJsonId() + .HasDiscriminator("Discriminator").HasValue("ProductView"); + modelBuilder .Entity() + .ToContainer("Customers") + .HasDiscriminator("Discriminator").HasValue("Customer"); + + modelBuilder + .Entity() + .ToContainer("Customers") .HasDiscriminator("Discriminator").HasValue("Customer"); modelBuilder.Entity().Metadata.RemoveIndex( diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindSelectQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindSelectQueryCosmosTest.cs index 730c21306e6..57a0cb00ea3 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindSelectQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindSelectQueryCosmosTest.cs @@ -111,7 +111,6 @@ public override Task Projection_when_null_value(bool async) """ SELECT VALUE c["Region"] FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -133,7 +132,7 @@ public override Task Project_to_object_array(bool async) """ SELECT c["EmployeeID"], c["ReportsTo"], c["Title"] FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["EmployeeID"] = 1)) +WHERE (c["EmployeeID"] = 1) """); }); @@ -142,13 +141,12 @@ public override Task Projection_of_entity_type_into_object_array(bool async) async, async a => { await base.Projection_of_entity_type_into_object_array(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["CustomerID"], "A")) -ORDER BY c["CustomerID"] +WHERE STARTSWITH(c["id"], "A") +ORDER BY c["id"] """); }); @@ -165,13 +163,11 @@ public override Task Projection_of_entity_type_into_object_list(bool async) async, async a => { await base.Projection_of_entity_type_into_object_list(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); }); @@ -185,7 +181,7 @@ public override Task Project_to_int_array(bool async) """ SELECT VALUE [c["EmployeeID"], c["ReportsTo"]] FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["EmployeeID"] = 1)) +WHERE (c["EmployeeID"] = 1) """); }); @@ -211,7 +207,6 @@ await Assert.ThrowsAsync( SELECT VALUE @__boolean_0 FROM root c -WHERE (c["Discriminator"] = "Customer") ORDER BY @__boolean_0 """); } @@ -227,7 +222,6 @@ public override Task Select_scalar(bool async) """ SELECT VALUE c["City"] FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -236,12 +230,10 @@ public override Task Select_anonymous_one(bool async) async, async a => { await base.Select_anonymous_one(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c["City"] FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -255,7 +247,6 @@ public override Task Select_anonymous_two(bool async) """ SELECT c["City"], c["Phone"] FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -269,7 +260,6 @@ public override Task Select_anonymous_three(bool async) """ SELECT c["City"], c["Phone"], c["Country"] FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -283,11 +273,10 @@ public override Task Select_anonymous_bool_constant_true(bool async) """ SELECT VALUE { - "CustomerID" : c["CustomerID"], + "CustomerID" : c["id"], "ConstantTrue" : true } FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -296,16 +285,14 @@ public override Task Select_anonymous_constant_in_expression(bool async) async, async a => { await base.Select_anonymous_constant_in_expression(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE { - "CustomerID" : c["CustomerID"], - "Expression" : (LENGTH(c["CustomerID"]) + 5) + "CustomerID" : c["id"], + "Expression" : (LENGTH(c["id"]) + 5) } FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -337,7 +324,6 @@ public override Task Select_anonymous_with_object(bool async) """ SELECT c["City"], c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -346,12 +332,10 @@ public override Task Select_constant_int(bool async) async, async a => { await base.Select_constant_int(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE 0 FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -365,7 +349,6 @@ public override Task Select_constant_null_string(bool async) """ SELECT VALUE null FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -374,14 +357,12 @@ public override Task Select_local(bool async) async, async a => { await base.Select_local(a); - - AssertSql( - """ +AssertSql( + """ @__x_0='10' SELECT VALUE @__x_0 FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -397,7 +378,6 @@ public override Task Select_scalar_primitive_after_take(bool async) SELECT VALUE c["EmployeeID"] FROM root c -WHERE (c["Discriminator"] = "Employee") OFFSET 0 LIMIT @__p_0 """); }); @@ -407,12 +387,11 @@ public override Task Select_project_filter(bool async) async, async a => { await base.Select_project_filter(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c["CompanyName"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = "London")) +WHERE (c["City"] = "London") """); }); @@ -426,7 +405,7 @@ public override Task Select_project_filter2(bool async) """ SELECT VALUE c["City"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = "London")) +WHERE (c["City"] = "London") """); }); @@ -499,12 +478,11 @@ public override Task New_date_time_in_anonymous_type_works(bool async) async, async a => { await base.New_date_time_in_anonymous_type_works(a); - - AssertSql( - """ +AssertSql( + """ SELECT 1 FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["CustomerID"], "A")) +WHERE STARTSWITH(c["id"], "A") """); }); @@ -924,9 +902,8 @@ public override Task Select_byte_constant(bool async) AssertSql( """ -SELECT VALUE ((c["CustomerID"] = "ALFKI") ? 1 : 2) +SELECT VALUE ((c["id"] = "ALFKI") ? 1 : 2) FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -938,9 +915,8 @@ public override Task Select_short_constant(bool async) AssertSql( """ -SELECT VALUE ((c["CustomerID"] = "ALFKI") ? 1 : 2) +SELECT VALUE ((c["id"] = "ALFKI") ? 1 : 2) FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -952,9 +928,8 @@ public override Task Select_bool_constant(bool async) AssertSql( """ -SELECT VALUE ((c["CustomerID"] = "ALFKI") ? true : false) +SELECT VALUE ((c["id"] = "ALFKI") ? true : false) FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -977,13 +952,11 @@ public override Task Anonymous_projection_with_repeated_property_being_ordered(b async, async a => { await base.Anonymous_projection_with_repeated_property_being_ordered(a); - - AssertSql( - """ -SELECT VALUE c["CustomerID"] +AssertSql( + """ +SELECT VALUE c["id"] FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); }); @@ -1022,12 +995,11 @@ public override Task Client_method_in_projection_requiring_materialization_1(boo async, async a => { await base.Client_method_in_projection_requiring_materialization_1(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["CustomerID"], "A")) +WHERE STARTSWITH(c["id"], "A") """); }); @@ -1036,12 +1008,11 @@ public override Task Client_method_in_projection_requiring_materialization_2(boo async, async a => { await base.Client_method_in_projection_requiring_materialization_2(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["CustomerID"], "A")) +WHERE STARTSWITH(c["id"], "A") """); }); @@ -1295,7 +1266,6 @@ public override Task Reverse_changes_asc_order_to_desc(bool async) """ SELECT VALUE c["EmployeeID"] FROM root c -WHERE (c["Discriminator"] = "Employee") ORDER BY c["EmployeeID"] DESC """); }); @@ -1310,7 +1280,6 @@ public override Task Reverse_changes_desc_order_to_asc(bool async) """ SELECT VALUE c["EmployeeID"] FROM root c -WHERE (c["Discriminator"] = "Employee") ORDER BY c["EmployeeID"] """); }); @@ -1333,8 +1302,7 @@ public override Task Projection_custom_type_in_both_sides_of_ternary(bool async) """ SELECT VALUE (c["City"] = "Seattle") FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] """); }); @@ -1432,10 +1400,10 @@ public override Task Projection_take_predicate_projection(bool async) """ @__p_0='10' -SELECT VALUE ((c["CustomerID"] || " ") || c["City"]) +SELECT VALUE ((c["id"] || " ") || c["City"]) FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["CustomerID"], "A")) -ORDER BY c["CustomerID"] +WHERE STARTSWITH(c["id"], "A") +ORDER BY c["id"] OFFSET 0 LIMIT @__p_0 """); }); @@ -1445,15 +1413,13 @@ public override Task Projection_take_projection_doesnt_project_intermittent_colu async, async a => { await base.Projection_take_projection_doesnt_project_intermittent_column(a); - - AssertSql( - """ +AssertSql( + """ @__p_0='10' -SELECT VALUE ((c["CustomerID"] || " ") || c["City"]) +SELECT VALUE ((c["id"] || " ") || c["City"]) FROM root c -WHERE (c["Discriminator"] = "Customer") -ORDER BY c["CustomerID"] +ORDER BY c["id"] OFFSET 0 LIMIT @__p_0 """); }); @@ -1703,7 +1669,6 @@ await Assert.ThrowsAsync( """ SELECT VALUE c["EmployeeID"] FROM root c -WHERE (c["Discriminator"] = "Employee") ORDER BY c["EmployeeID"] DESC, c["City"] """); } @@ -1742,18 +1707,15 @@ public override Task Select_bool_closure(bool async) async, async a => { await base.Select_bool_closure(a); - - AssertSql( - """ +AssertSql( + """ SELECT 1 FROM root c -WHERE (c["Discriminator"] = "Customer") """, - // - """ + // + """ SELECT 1 FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -1781,7 +1743,6 @@ public override Task Reverse_after_multiple_orderbys(bool async) """ SELECT VALUE c["EmployeeID"] FROM root c -WHERE (c["Discriminator"] = "Employee") ORDER BY c["EmployeeID"] """); }); @@ -1827,7 +1788,6 @@ public override Task Select_customer_identity(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -1841,7 +1801,7 @@ public override Task Projection_with_parameterized_constructor(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") """); }); @@ -1855,7 +1815,6 @@ public override Task Select_anonymous_nested(bool async) """ SELECT c["City"], c["Country"] FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -1878,12 +1837,10 @@ public override Task Select_anonymous_empty(bool async) async, async a => { await base.Select_anonymous_empty(a); - - AssertSql( - """ +AssertSql( + """ SELECT 1 FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -1897,7 +1854,6 @@ public override Task Select_scalar_primitive(bool async) """ SELECT VALUE c["EmployeeID"] FROM root c -WHERE (c["Discriminator"] = "Employee") """); }); @@ -1906,12 +1862,11 @@ public override Task Select_into(bool async) async, async a => { await base.Select_into(a); - - AssertSql( - """ -SELECT VALUE c["CustomerID"] +AssertSql( + """ +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") """); }); @@ -1925,7 +1880,7 @@ public override Task Projection_with_parameterized_constructor_with_member_assig """ SELECT c, c["City"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") """); }); @@ -1955,7 +1910,7 @@ await Assert.ThrowsAsync( """ SELECT VALUE INDEX_OF(c["Region"], "") FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = "ALFKI")) +WHERE (c["id"] = "ALFKI") """); } } @@ -1984,7 +1939,6 @@ public override Task Select_anonymous_literal(bool async) """ SELECT VALUE 10 FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -1998,7 +1952,6 @@ public override Task Select_customer_table(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -2007,12 +1960,10 @@ public override Task Select_over_10_nested_ternary_condition(bool async) async, async a => { await base.Select_over_10_nested_ternary_condition(a); - - AssertSql( - """ -SELECT VALUE ((c["CustomerID"] = "1") ? "01" : ((c["CustomerID"] = "2") ? "02" : ((c["CustomerID"] = "3") ? "03" : ((c["CustomerID"] = "4") ? "04" : ((c["CustomerID"] = "5") ? "05" : ((c["CustomerID"] = "6") ? "06" : ((c["CustomerID"] = "7") ? "07" : ((c["CustomerID"] = "8") ? "08" : ((c["CustomerID"] = "9") ? "09" : ((c["CustomerID"] = "10") ? "10" : ((c["CustomerID"] = "11") ? "11" : null))))))))))) +AssertSql( + """ +SELECT VALUE ((c["id"] = "1") ? "01" : ((c["id"] = "2") ? "02" : ((c["id"] = "3") ? "03" : ((c["id"] = "4") ? "04" : ((c["id"] = "5") ? "05" : ((c["id"] = "6") ? "06" : ((c["id"] = "7") ? "07" : ((c["id"] = "8") ? "08" : ((c["id"] = "9") ? "09" : ((c["id"] = "10") ? "10" : ((c["id"] = "11") ? "11" : null))))))))))) FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -2080,9 +2031,9 @@ public override Task Using_enumerable_parameter_in_projection(bool async) AssertSql( """ -SELECT VALUE c["CustomerID"] +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STARTSWITH(c["CustomerID"], "F")) +WHERE STARTSWITH(c["id"], "F") """); }); @@ -2108,7 +2059,6 @@ public override Task Entity_passed_to_DTO_constructor_works(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindWhereQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindWhereQueryCosmosTest.cs index e6d3e7f5bf1..fcfedf6853a 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindWhereQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/NorthwindWhereQueryCosmosTest.cs @@ -130,7 +130,7 @@ await Fixture.NoSyncTest( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((c["CustomerID"] = "ALFKI") | (c["CustomerID"] = "ANATR"))) +WHERE ((c["id"] = "ALFKI") | (c["id"] = "ANATR")) """); }); } @@ -146,7 +146,7 @@ public override Task Where_bitwise_and(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((c["CustomerID"] = "ALFKI") & (c["CustomerID"] = "ANATR"))) +WHERE ((c["id"] = "ALFKI") & (c["id"] = "ANATR")) """); }); @@ -162,7 +162,7 @@ public override Task Where_bitwise_xor(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((c["CustomerID"] = "ALFKI") != true)) +WHERE ((c["id"] = "ALFKI") != true) """); }); @@ -216,7 +216,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((c["City"] = "Seattle") AND (c["ContactTitle"] = "Owner"))) +WHERE ((c["City"] = "Seattle") AND (c["ContactTitle"] = "Owner")) """); }); @@ -234,7 +234,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((c["CustomerID"] = "ALFKI") OR (c["CustomerID"] = "ANATR"))) +WHERE ((c["id"] = "ALFKI") OR (c["id"] = "ANATR")) """); }); @@ -252,7 +252,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND NOT((c["City"] != "Seattle"))) +WHERE NOT((c["City"] != "Seattle")) """); }); @@ -270,7 +270,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["ReportsTo"] = 2)) +WHERE (c["ReportsTo"] = 2) """); }); @@ -288,7 +288,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["ReportsTo"] != 2)) +WHERE (c["ReportsTo"] != 2) """); }); @@ -306,7 +306,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["ReportsTo"] > 2)) +WHERE (c["ReportsTo"] > 2) """); }); @@ -324,7 +324,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["ReportsTo"] >= 2)) +WHERE (c["ReportsTo"] >= 2) """); }); @@ -342,7 +342,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["ReportsTo"] < 3)) +WHERE (c["ReportsTo"] < 3) """); }); @@ -360,7 +360,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["ReportsTo"] <= 2)) +WHERE (c["ReportsTo"] <= 2) """); }); @@ -378,7 +378,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((c["CustomerID"] || "END") = "ALFKIEND")) +WHERE ((c["id"] || "END") = "ALFKIEND") """); }); @@ -434,7 +434,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (((c["Region"] != null) ? c["Region"] : "SP") = "BC")) +WHERE (((c["Region"] != null) ? c["Region"] : "SP") = "BC") """); }); @@ -452,7 +452,7 @@ await AssertQuery( """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (((c["Region"] != null) ? c["Region"] : "SP") = "BC")) +WHERE (((c["Region"] != null) ? c["Region"] : "SP") = "BC") """); }); @@ -466,7 +466,7 @@ public override Task Where_simple(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = "London")) +WHERE (c["City"] = "London") """); }); @@ -493,7 +493,7 @@ await Fixture.NoSyncTest( SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__city_0)) +WHERE (c["City"] = @__city_0) """); }); @@ -512,7 +512,7 @@ public override Task Where_indexer_closure(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__p_0)) +WHERE (c["City"] = @__p_0) """); }); @@ -528,7 +528,7 @@ public override Task Where_dictionary_key_access_closure(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__get_Item_0)) +WHERE (c["City"] = @__get_Item_0) """); }); @@ -544,7 +544,7 @@ public override Task Where_tuple_item_closure(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__predicateTuple_Item2_0)) +WHERE (c["City"] = @__predicateTuple_Item2_0) """); }); @@ -560,7 +560,7 @@ public override Task Where_named_tuple_item_closure(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__predicateTuple_Item2_0)) +WHERE (c["City"] = @__predicateTuple_Item2_0) """); }); @@ -576,7 +576,7 @@ public override Task Where_simple_closure_constant(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND @__predicate_0) +WHERE @__predicate_0 """); }); @@ -592,7 +592,7 @@ public override Task Where_simple_closure_via_query_cache(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__city_0)) +WHERE (c["City"] = @__city_0) """, // """ @@ -600,7 +600,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__city_0)) +WHERE (c["City"] = @__city_0) """); }); @@ -632,7 +632,7 @@ public override Task Where_method_call_closure_via_query_cache(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__GetCity_0)) +WHERE (c["City"] = @__GetCity_0) """, // """ @@ -640,7 +640,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__GetCity_0)) +WHERE (c["City"] = @__GetCity_0) """); }); @@ -656,7 +656,7 @@ public override Task Where_field_access_closure_via_query_cache(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__city_InstanceFieldValue_0)) +WHERE (c["City"] = @__city_InstanceFieldValue_0) """, // """ @@ -664,7 +664,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__city_InstanceFieldValue_0)) +WHERE (c["City"] = @__city_InstanceFieldValue_0) """); }); @@ -680,7 +680,7 @@ public override Task Where_property_access_closure_via_query_cache(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__city_InstancePropertyValue_0)) +WHERE (c["City"] = @__city_InstancePropertyValue_0) """, // """ @@ -688,7 +688,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__city_InstancePropertyValue_0)) +WHERE (c["City"] = @__city_InstancePropertyValue_0) """); }); @@ -704,7 +704,7 @@ public override Task Where_static_field_access_closure_via_query_cache(bool asyn SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__StaticFieldValue_0)) +WHERE (c["City"] = @__StaticFieldValue_0) """, // """ @@ -712,7 +712,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__StaticFieldValue_0)) +WHERE (c["City"] = @__StaticFieldValue_0) """); }); @@ -728,7 +728,7 @@ public override Task Where_static_property_access_closure_via_query_cache(bool a SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__StaticPropertyValue_0)) +WHERE (c["City"] = @__StaticPropertyValue_0) """, // """ @@ -736,7 +736,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__StaticPropertyValue_0)) +WHERE (c["City"] = @__StaticPropertyValue_0) """); }); @@ -752,7 +752,7 @@ public override Task Where_nested_field_access_closure_via_query_cache(bool asyn SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__city_Nested_InstanceFieldValue_0)) +WHERE (c["City"] = @__city_Nested_InstanceFieldValue_0) """, // """ @@ -760,7 +760,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__city_Nested_InstanceFieldValue_0)) +WHERE (c["City"] = @__city_Nested_InstanceFieldValue_0) """); }); @@ -776,7 +776,7 @@ public override Task Where_nested_property_access_closure_via_query_cache(bool a SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__city_Nested_InstancePropertyValue_0)) +WHERE (c["City"] = @__city_Nested_InstancePropertyValue_0) """, // """ @@ -784,7 +784,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__city_Nested_InstancePropertyValue_0)) +WHERE (c["City"] = @__city_Nested_InstancePropertyValue_0) """); }); @@ -800,7 +800,7 @@ public override Task Where_new_instance_field_access_query_cache(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__InstanceFieldValue_0)) +WHERE (c["City"] = @__InstanceFieldValue_0) """, // """ @@ -808,7 +808,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__InstanceFieldValue_0)) +WHERE (c["City"] = @__InstanceFieldValue_0) """); }); @@ -824,7 +824,7 @@ public override Task Where_new_instance_field_access_closure_via_query_cache(boo SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__InstanceFieldValue_0)) +WHERE (c["City"] = @__InstanceFieldValue_0) """, // """ @@ -832,7 +832,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__InstanceFieldValue_0)) +WHERE (c["City"] = @__InstanceFieldValue_0) """); }); @@ -866,7 +866,7 @@ public override Task Where_simple_shadow(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["Title"] = "Sales Representative")) +WHERE (c["Title"] = "Sales Representative") """); }); @@ -880,7 +880,7 @@ public override Task Where_simple_shadow_projection(bool async) """ SELECT VALUE c["Title"] FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["Title"] = "Sales Representative")) +WHERE (c["Title"] = "Sales Representative") """); }); @@ -900,7 +900,7 @@ await Fixture.NoSyncTest( SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["Title"] = "Sales Representative")) +WHERE (c["Title"] = "Sales Representative") ORDER BY c["EmployeeID"] OFFSET 0 LIMIT @__p_0 """); @@ -976,7 +976,7 @@ public override Task Where_equals_method_string(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = "London")) +WHERE (c["City"] = "London") """); }); @@ -990,7 +990,7 @@ public override Task Where_equals_method_string_with_ignore_case(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND STRINGEQUALS(c["City"], "London", true)) +WHERE STRINGEQUALS(c["City"], "London", true) """); }); @@ -1000,7 +1000,7 @@ public override Task Where_equals_method_int(bool async) { await base.Where_equals_method_int(a); - AssertSql("ReadItem(None, Employee|1)"); + AssertSql("ReadItem(None, 1)"); }); public override Task Where_equals_using_object_overload_on_mismatched_types(bool async) @@ -1023,7 +1023,7 @@ public override Task Where_equals_using_int_overload_on_mismatched_types(bool as { await base.Where_equals_using_int_overload_on_mismatched_types(a); - AssertSql("ReadItem(None, Employee|1)"); + AssertSql("ReadItem(None, 1)"); }); public override Task Where_equals_on_mismatched_types_nullable_int_long(bool async) @@ -1078,7 +1078,7 @@ public override Task Where_equals_on_mismatched_types_int_nullable_int(bool asyn SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["ReportsTo"] = @__intPrm_0)) +WHERE (c["ReportsTo"] = @__intPrm_0) """, // """ @@ -1086,7 +1086,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (@__intPrm_0 = c["ReportsTo"])) +WHERE (@__intPrm_0 = c["ReportsTo"]) """); }); @@ -1102,7 +1102,7 @@ public override Task Where_equals_on_matched_nullable_int_types(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (@__nullableIntPrm_0 = c["ReportsTo"])) +WHERE (@__nullableIntPrm_0 = c["ReportsTo"]) """, // """ @@ -1110,7 +1110,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["ReportsTo"] = @__nullableIntPrm_0)) +WHERE (c["ReportsTo"] = @__nullableIntPrm_0) """); }); @@ -1126,7 +1126,7 @@ public override Task Where_equals_on_null_nullable_int_types(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (@__nullableIntPrm_0 = c["ReportsTo"])) +WHERE (@__nullableIntPrm_0 = c["ReportsTo"]) """, // """ @@ -1134,7 +1134,7 @@ FROM root c SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["ReportsTo"] = @__nullableIntPrm_0)) +WHERE (c["ReportsTo"] = @__nullableIntPrm_0) """); }); @@ -1148,7 +1148,7 @@ public override Task Where_comparison_nullable_type_not_null(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["ReportsTo"] = 2)) +WHERE (c["ReportsTo"] = 2) """); }); @@ -1162,7 +1162,7 @@ public override Task Where_comparison_nullable_type_null(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["ReportsTo"] = null)) +WHERE (c["ReportsTo"] = null) """); }); @@ -1176,7 +1176,7 @@ public override Task Where_string_length(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (LENGTH(c["City"]) = 6)) +WHERE (LENGTH(c["City"]) = 6) """); }); @@ -1190,7 +1190,7 @@ public override Task Where_string_indexof(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (INDEX_OF(c["City"], "Sea") != -1)) +WHERE (INDEX_OF(c["City"], "Sea") != -1) """); }); @@ -1204,7 +1204,7 @@ public override Task Where_string_replace(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (REPLACE(c["City"], "Sea", "Rea") = "Reattle")) +WHERE (REPLACE(c["City"], "Sea", "Rea") = "Reattle") """); }); @@ -1218,7 +1218,7 @@ public override Task Where_string_substring(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (SUBSTRING(c["City"], 1, 2) = "ea")) +WHERE (SUBSTRING(c["City"], 1, 2) = "ea") """); }); @@ -1242,7 +1242,7 @@ public override Task Where_datetime_utcnow(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (GetCurrentDateTime() != @__myDatetime_0)) +WHERE (GetCurrentDateTime() != @__myDatetime_0) """); }); @@ -1258,7 +1258,7 @@ public override Task Where_datetimeoffset_utcnow(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (GetCurrentDateTime() != @__myDatetimeOffset_0)) +WHERE (GetCurrentDateTime() != @__myDatetimeOffset_0) """); }); @@ -1424,7 +1424,7 @@ public override Task Where_simple_reversed(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ("London" = c["City"])) +WHERE ("London" = c["City"]) """); }); @@ -1438,7 +1438,7 @@ public override Task Where_is_null(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["Region"] = null)) +WHERE (c["Region"] = null) """); }); @@ -1452,7 +1452,6 @@ public override Task Where_null_is_null(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -1475,12 +1474,11 @@ public override Task Where_is_not_null(bool async) async, async a => { await base.Where_is_not_null(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] != null)) +WHERE (c["City"] != null) """); }); @@ -1503,12 +1501,10 @@ public override Task Where_constant_is_not_null(bool async) async, async a => { await base.Where_constant_is_not_null(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -1522,7 +1518,7 @@ public override Task Where_identity_comparison(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = c["City"])) +WHERE (c["City"] = c["City"]) """); }); @@ -1586,7 +1582,7 @@ public override Task Where_primitive(bool async) SELECT VALUE c["EmployeeID"] FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["EmployeeID"] = 5)) +WHERE (c["EmployeeID"] = 5) OFFSET 0 LIMIT @__p_0 """); }); @@ -1862,12 +1858,11 @@ public override Task Where_comparison_to_nullable_bool(bool async) async, async a => { await base.Where_comparison_to_nullable_bool(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (ENDSWITH(c["CustomerID"], "KI") = true)) +WHERE (ENDSWITH(c["id"], "KI") = true) """); }); @@ -1876,12 +1871,10 @@ public override Task Where_true(bool async) async, async a => { await base.Where_true(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -1904,7 +1897,6 @@ public override Task Where_bool_closure(bool async) async, async a => { await base.Where_bool_closure(a); - AssertSql( """ SELECT VALUE c @@ -1912,14 +1904,13 @@ FROM root c WHERE false """, // - "ReadItem(None, Customer|ALFKI)", + "ReadItem(None, ALFKI)", // - "ReadItem(None, Customer|ALFKI)", + "ReadItem(None, ALFKI)", // """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -1933,7 +1924,7 @@ public override Task Where_default(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["Fax"] = null)) +WHERE (c["Fax"] = null) """); }); @@ -1943,7 +1934,7 @@ public override Task Where_expression_invoke_1(bool async) { await base.Where_expression_invoke_1(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); public override async Task Where_expression_invoke_2(bool async) @@ -1960,7 +1951,7 @@ public override Task Where_expression_invoke_3(bool async) { await base.Where_expression_invoke_3(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); public override async Task Where_concat_string_int_comparison1(bool async) @@ -1992,7 +1983,8 @@ public override async Task Where_concat_string_int_comparison4(bool async) // Cosmos client evaluation. Issue #17246. await AssertTranslationFailed(() => base.Where_concat_string_int_comparison4(async)); - AssertSql(); + AssertSql( +); } public override Task Where_string_concat_method_comparison(bool async) @@ -2005,9 +1997,9 @@ public override Task Where_string_concat_method_comparison(bool async) """ @__i_0='A' -SELECT VALUE c["CustomerID"] +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((@__i_0 || c["CustomerID"]) = "AAROUT")) +WHERE ((@__i_0 || c["id"]) = "AAROUT") """); }); @@ -2022,9 +2014,9 @@ public override Task Where_string_concat_method_comparison_2(bool async) @__i_0='A' @__j_1='B' -SELECT VALUE c["CustomerID"] +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((@__i_0 || (@__j_1 || c["CustomerID"])) = "ABANATR")) +WHERE ((@__i_0 || (@__j_1 || c["id"])) = "ABANATR") """); }); @@ -2040,9 +2032,9 @@ public override Task Where_string_concat_method_comparison_3(bool async) @__j_1='B' @__k_2='C' -SELECT VALUE c["CustomerID"] +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((@__i_0 || (@__j_1 || (@__k_2 || c["CustomerID"]))) = "ABCANTON")) +WHERE ((@__i_0 || (@__j_1 || (@__k_2 || c["id"]))) = "ABCANTON") """); }); @@ -2214,7 +2206,7 @@ public override Task Where_compare_null(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((c["Region"] = null) AND (c["Country"] = "UK"))) +WHERE ((c["Region"] = null) AND (c["Country"] = "UK")) """); }); @@ -2228,7 +2220,6 @@ public override Task Where_Is_on_same_type(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -2265,7 +2256,7 @@ public override Task Where_array_index(bool async) { await base.Where_array_index(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); public override async Task Where_multiple_contains_in_subquery_with_or(bool async) @@ -2273,7 +2264,8 @@ public override async Task Where_multiple_contains_in_subquery_with_or(bool asyn // Cosmos client evaluation. Issue #17246. await AssertTranslationFailed(() => base.Where_multiple_contains_in_subquery_with_or(async)); - AssertSql(); + AssertSql( +); } public override async Task Where_multiple_contains_in_subquery_with_and(bool async) @@ -2566,7 +2558,7 @@ public override Task Filter_with_EF_Property_using_closure_for_property_name(boo { await base.Filter_with_EF_Property_using_closure_for_property_name(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); public override Task Filter_with_EF_Property_using_function_for_property_name(bool async) @@ -2575,7 +2567,7 @@ public override Task Filter_with_EF_Property_using_function_for_property_name(bo { await base.Filter_with_EF_Property_using_function_for_property_name(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); public override async Task FirstOrDefault_over_scalar_projection_compared_to_null(bool async) @@ -2718,7 +2710,7 @@ public override Task Where_Contains_and_comparison(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (ARRAY_CONTAINS(@__customerIds_0, c["CustomerID"]) AND (c["City"] = "Seattle"))) +WHERE (ARRAY_CONTAINS(@__customerIds_0, c["id"]) AND (c["City"] = "Seattle")) """); }); @@ -2734,7 +2726,7 @@ public override Task Where_Contains_or_comparison(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (ARRAY_CONTAINS(@__customerIds_0, c["CustomerID"]) OR (c["City"] = "Seattle"))) +WHERE (ARRAY_CONTAINS(@__customerIds_0, c["id"]) OR (c["City"] = "Seattle")) """); }); @@ -2749,7 +2741,8 @@ public override async Task Where_Like_or_comparison(bool async) { await AssertTranslationFailed(() => base.Where_Like_or_comparison(async)); - AssertSql(); + AssertSql( +); } public override Task GetType_on_non_hierarchy1(bool async) @@ -2762,7 +2755,6 @@ public override Task GetType_on_non_hierarchy1(bool async) """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -2799,12 +2791,10 @@ public override Task GetType_on_non_hierarchy4(bool async) async, async a => { await base.GetType_on_non_hierarchy4(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """); }); @@ -2813,12 +2803,11 @@ public override Task Case_block_simplification_works_correctly(bool async) async, async a => { await base.Case_block_simplification_works_correctly(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (((c["Region"] = null) ? "OR" : c["Region"]) = "OR")) +WHERE (((c["Region"] = null) ? "OR" : c["Region"]) = "OR") """); }); @@ -2832,7 +2821,7 @@ public override Task Where_compare_null_with_cast_to_object(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["Region"] = null)) +WHERE (c["Region"] = null) """); }); @@ -2846,7 +2835,7 @@ public override Task Where_compare_with_both_cast_to_object(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = "London")) +WHERE (c["City"] = "London") """); }); @@ -2860,7 +2849,7 @@ public override Task Where_projection(bool async) """ SELECT VALUE c["CompanyName"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = "London")) +WHERE (c["City"] = "London") """); }); @@ -2899,14 +2888,13 @@ public override Task Generic_Ilist_contains_translates_to_server(bool async) async, async a => { await base.Generic_Ilist_contains_translates_to_server(a); - - AssertSql( - """ +AssertSql( + """ @__cities_0='["Seattle"]' SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ARRAY_CONTAINS(@__cities_0, c["City"])) +WHERE ARRAY_CONTAINS(@__cities_0, c["City"]) """); }); @@ -2920,7 +2908,7 @@ public override Task Multiple_OrElse_on_same_column_converted_to_in_with_overlap """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((((c["CustomerID"] = "ALFKI") OR (c["CustomerID"] = "ANATR")) OR (c["CustomerID"] = "ANTON")) OR (c["CustomerID"] = "ANATR"))) +WHERE ((((c["id"] = "ALFKI") OR (c["id"] = "ANATR")) OR (c["id"] = "ANTON")) OR (c["id"] = "ANATR")) """); }); @@ -2929,12 +2917,11 @@ public override Task Multiple_OrElse_on_same_column_with_null_constant_compariso async, async a => { await base.Multiple_OrElse_on_same_column_with_null_constant_comparison_converted_to_in(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((((c["Region"] = "WA") OR (c["Region"] = "OR")) OR (c["Region"] = null)) OR (c["Region"] = "BC"))) +WHERE ((((c["Region"] = "WA") OR (c["Region"] = "OR")) OR (c["Region"] = null)) OR (c["Region"] = "BC")) """); }); @@ -2943,12 +2930,11 @@ public override Task Constant_array_Contains_OrElse_comparison_with_constant_get async, async a => { await base.Constant_array_Contains_OrElse_comparison_with_constant_gets_combined_to_one_in(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] IN ("ALFKI", "ANATR") OR (c["CustomerID"] = "ANTON"))) +WHERE (c["id"] IN ("ALFKI", "ANATR") OR (c["id"] = "ANTON")) """); }); @@ -2962,7 +2948,7 @@ public override Task Constant_array_Contains_OrElse_comparison_with_constant_get """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (((c["CustomerID"] = "ANTON") OR c["CustomerID"] IN ("ALFKI", "ANATR")) OR (c["CustomerID"] = "ALFKI"))) +WHERE (((c["id"] = "ANTON") OR c["id"] IN ("ALFKI", "ANATR")) OR (c["id"] = "ALFKI")) """); }); @@ -2976,7 +2962,7 @@ public override Task Constant_array_Contains_OrElse_another_Contains_gets_combin """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] IN ("ALFKI", "ANATR") OR c["CustomerID"] IN ("ALFKI", "ANTON"))) +WHERE (c["id"] IN ("ALFKI", "ANATR") OR c["id"] IN ("ALFKI", "ANTON")) """); }); @@ -2990,7 +2976,7 @@ public override Task Constant_array_Contains_AndAlso_another_Contains_gets_combi """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] NOT IN ("ALFKI", "ANATR") AND c["CustomerID"] NOT IN ("ALFKI", "ANTON"))) +WHERE (c["id"] NOT IN ("ALFKI", "ANATR") AND c["id"] NOT IN ("ALFKI", "ANTON")) """); }); @@ -3008,7 +2994,7 @@ public override Task Multiple_AndAlso_on_same_column_converted_to_in_using_param SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (((c["CustomerID"] != @__prm1_0) AND (c["CustomerID"] != @__prm2_1)) AND (c["CustomerID"] != @__prm3_2))) +WHERE (((c["id"] != @__prm1_0) AND (c["id"] != @__prm2_1)) AND (c["id"] != @__prm3_2)) """); }); @@ -3025,7 +3011,7 @@ public override Task Array_of_parameters_Contains_OrElse_comparison_with_constan SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] IN (@__prm1_0, @__prm2_1) OR (c["CustomerID"] = "ANTON"))) +WHERE (c["id"] IN (@__prm1_0, @__prm2_1) OR (c["id"] = "ANTON")) """); }); @@ -3041,7 +3027,7 @@ public override Task Multiple_OrElse_on_same_column_with_null_parameter_comparis SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((((c["Region"] = "WA") OR (c["Region"] = "OR")) OR (c["Region"] = @__prm_0)) OR (c["Region"] = "BC"))) +WHERE ((((c["Region"] = "WA") OR (c["Region"] = "OR")) OR (c["Region"] = @__prm_0)) OR (c["Region"] = "BC")) """); }); @@ -3057,7 +3043,7 @@ public override Task Parameter_array_Contains_OrElse_comparison_with_constant(bo SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (ARRAY_CONTAINS(@__array_0, c["CustomerID"]) OR (c["CustomerID"] = "ANTON"))) +WHERE (ARRAY_CONTAINS(@__array_0, c["id"]) OR (c["id"] = "ANTON")) """); }); @@ -3075,7 +3061,7 @@ public override Task Parameter_array_Contains_OrElse_comparison_with_parameter_w SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (((c["CustomerID"] = @__prm1_0) OR ARRAY_CONTAINS(@__array_1, c["CustomerID"])) OR (c["CustomerID"] = @__prm2_2))) +WHERE (((c["id"] = @__prm1_0) OR ARRAY_CONTAINS(@__array_1, c["id"])) OR (c["id"] = @__prm2_2)) """); }); @@ -3089,7 +3075,7 @@ public override Task Two_sets_of_comparison_combine_correctly(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] IN ("ALFKI", "ANATR") AND ((c["CustomerID"] = "ANATR") OR (c["CustomerID"] = "ANTON")))) +WHERE (c["id"] IN ("ALFKI", "ANATR") AND ((c["id"] = "ANATR") OR (c["id"] = "ANTON"))) """); }); @@ -3103,7 +3089,7 @@ public override Task Two_sets_of_comparison_combine_correctly2(bool async) """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((((c["Region"] != "WA") AND (c["Region"] != "OR")) AND (c["Region"] != null)) OR ((c["Region"] != "WA") AND (c["Region"] != null)))) +WHERE ((((c["Region"] != "WA") AND (c["Region"] != "OR")) AND (c["Region"] != null)) OR ((c["Region"] != "WA") AND (c["Region"] != null))) """); }); @@ -3117,7 +3103,7 @@ public override Task Filter_with_property_compared_to_null_wrapped_in_explicit_c """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["Region"] = null)) +WHERE (c["Region"] = null) """); }); @@ -3149,7 +3135,7 @@ SELECT VALUE "Title" : c["Title"] } FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["Title"] = "Sales Representative")) +WHERE (c["Title"] = "Sales Representative") """); }); @@ -3165,7 +3151,7 @@ public override Task Where_primitive_tracked(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["EmployeeID"] = 5)) +WHERE (c["EmployeeID"] = 5) OFFSET 0 LIMIT @__p_0 """); }); @@ -3182,7 +3168,7 @@ public override Task Where_primitive_tracked2(bool async) SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Employee") AND (c["EmployeeID"] = 5)) +WHERE (c["EmployeeID"] = 5) OFFSET 0 LIMIT @__p_0 """); }); @@ -3192,22 +3178,21 @@ public override Task Where_poco_closure(bool async) async, async a => { await base.Where_poco_closure(a); - - AssertSql( - """ +AssertSql( + """ @__entity_equality_customer_0_CustomerID='ALFKI' -SELECT VALUE c["CustomerID"] +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = @__entity_equality_customer_0_CustomerID)) +WHERE (c["id"] = @__entity_equality_customer_0_CustomerID) """, - // - """ + // + """ @__entity_equality_customer_0_CustomerID='ANATR' -SELECT VALUE c["CustomerID"] +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = @__entity_equality_customer_0_CustomerID)) +WHERE (c["id"] = @__entity_equality_customer_0_CustomerID) """); }); @@ -3221,9 +3206,9 @@ public override Task Where_concat_string_string_comparison(bool async) """ @__i_0='A' -SELECT VALUE c["CustomerID"] +SELECT VALUE c["id"] FROM root c -WHERE ((c["Discriminator"] = "Customer") AND ((@__i_0 || c["CustomerID"]) = "AALFKI")) +WHERE ((@__i_0 || c["id"]) = "AALFKI") """); }); @@ -3233,7 +3218,7 @@ public override Task EF_Constant(bool async) { await base.EF_Constant(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); public override Task EF_Constant_with_subtree(bool async) @@ -3242,7 +3227,7 @@ public override Task EF_Constant_with_subtree(bool async) { await base.EF_Constant_with_subtree(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); public override Task EF_Constant_does_not_parameterized_as_part_of_bigger_subtree(bool async) @@ -3250,20 +3235,19 @@ public override Task EF_Constant_does_not_parameterized_as_part_of_bigger_subtre async, async a => { await base.EF_Constant_does_not_parameterized_as_part_of_bigger_subtree(a); - - AssertSql( - """ +AssertSql( + """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = ("ALF" || "KI"))) +WHERE (c["id"] = ("ALF" || "KI")) """); }); public override async Task EF_Constant_with_non_evaluatable_argument_throws(bool async) { await base.EF_Constant_with_non_evaluatable_argument_throws(async); - - AssertSql(); +AssertSql( +); } public override Task EF_Parameter(bool async) @@ -3272,7 +3256,7 @@ public override Task EF_Parameter(bool async) { await base.EF_Parameter(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); public override Task EF_Parameter_with_subtree(bool async) @@ -3281,7 +3265,7 @@ public override Task EF_Parameter_with_subtree(bool async) { await base.EF_Parameter_with_subtree(a); - AssertSql("ReadItem(None, Customer|ALFKI)"); + AssertSql("ReadItem(None, ALFKI)"); }); public override Task EF_Parameter_does_not_parameterized_as_part_of_bigger_subtree(bool async) @@ -3296,7 +3280,7 @@ public override Task EF_Parameter_does_not_parameterized_as_part_of_bigger_subtr SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["CustomerID"] = (@__id_0 || "KI"))) +WHERE (c["id"] = (@__id_0 || "KI")) """); }); diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/OwnedQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/OwnedQueryCosmosTest.cs index 73ad5f5e24d..eeefbecbb4f 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/OwnedQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/OwnedQueryCosmosTest.cs @@ -18,6 +18,15 @@ public OwnedQueryCosmosTest(OwnedQueryCosmosFixture fixture, ITestOutputHelper t Fixture.TestSqlLoggerFactory.SetTestOutputHelper(testOutputHelper); } + public override async Task SelectMany_on_owned_reference_followed_by_regular_entity_and_collection(bool async) + { + await AssertTranslationFailedWithDetails( + () => base.SelectMany_on_owned_reference_followed_by_regular_entity_and_collection(async), + CosmosStrings.MultipleRootEntityTypesReferencedInQuery("Planet", "OwnedPerson")); + + AssertSql(); + } + public override async Task Query_loads_reference_nav_automatically_in_projection(bool async) { // Fink.Barton is a non-owned navigation, cross-document join @@ -329,16 +338,6 @@ JOIN o IN c["Orders"] """); }); - public override async Task SelectMany_on_owned_reference_followed_by_regular_entity_and_collection(bool async) - { - // Address.Planet is a non-owned navigation, cross-document join - await AssertTranslationFailedWithDetails( - () => base.SelectMany_on_owned_reference_followed_by_regular_entity_and_collection(async), - CosmosStrings.MultipleRootEntityTypesReferencedInQuery(nameof(Planet), nameof(OwnedPerson))); - - AssertSql(); - } - // Address.Planet is a non-owned navigation, cross-document join public override async Task SelectMany_on_owned_reference_with_entity_in_between_ending_in_owned_collection(bool async) { @@ -883,7 +882,6 @@ await AssertTranslationFailedWithDetails( CosmosStrings.MultipleRootEntityTypesReferencedInQuery(nameof(Barton), nameof(Fink))); AssertSql(); - } public override async Task Left_join_on_entity_with_owned_navigations(bool async) @@ -1348,6 +1346,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity( eb => { + eb.ToContainer("OwnedPeople"); eb.IndexerProperty("Name"); eb.HasData( new @@ -1503,6 +1502,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity( eb => { + eb.ToContainer("OwnedPeople"); eb.HasData( new { @@ -1552,6 +1552,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity( eb => { + eb.ToContainer("OwnedPeople"); eb.HasData( new { @@ -1589,6 +1590,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity( eb => { + eb.ToContainer("OwnedPeople"); eb.HasData( new { @@ -1626,6 +1628,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity( pb => { + pb.ToContainer("Planets"); + pb.IncludeDiscriminatorInJsonId(); pb.HasData( new { @@ -1638,6 +1642,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity( mb => { + mb.ToContainer("Planets"); + mb.IncludeDiscriminatorInJsonId(); mb.HasData( new { @@ -1651,6 +1657,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity( sb => { + sb.ToContainer("Planets"); + sb.IncludeDiscriminatorInJsonId(); sb.HasData( new { @@ -1682,6 +1690,8 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity( b => { + b.ToContainer("Bartons"); + b.IncludeDiscriminatorInJsonId(); b.OwnsOne( e => e.Throned, b => b.HasData( new @@ -1695,12 +1705,28 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con new Barton { Id = 2, Simple = "Not" }); }); - modelBuilder.Entity().HasData( - new { Id = 1, BartonId = 1 }); + modelBuilder.Entity( + b => + { + b.ToContainer("Bartons"); + b.IncludeDiscriminatorInJsonId(); + b.HasData( + new { Id = 1, BartonId = 1 }); + }); + + modelBuilder + .Entity() + .ToContainer("Balloons"); + + modelBuilder + .Entity() + .ToContainer("Balloons") + .OwnsOne(e => e.Gas); - modelBuilder.Entity(); - modelBuilder.Entity().OwnsOne(e => e.Gas); - modelBuilder.Entity().OwnsOne(e => e.Gas); + modelBuilder + .Entity() + .ToContainer("Balloons") + .OwnsOne(e => e.Gas); } } } diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/PrimitiveCollectionsQueryCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/PrimitiveCollectionsQueryCosmosTest.cs index c3275e807a9..0d4808754df 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/PrimitiveCollectionsQueryCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/PrimitiveCollectionsQueryCosmosTest.cs @@ -149,7 +149,7 @@ public override Task Inline_collection_Contains_with_one_value(bool async) { await base.Inline_collection_Contains_with_one_value(a); - AssertSql("ReadItem(None, PrimitiveCollectionsEntity|2)"); + AssertSql("ReadItem(None, 2)"); }); public override Task Inline_collection_Contains_with_two_values(bool async) diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/QueryLoggingCosmosTestBase.cs b/test/EFCore.Cosmos.FunctionalTests/Query/QueryLoggingCosmosTestBase.cs index 2c84d5fae0c..f7dc3ca8876 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/QueryLoggingCosmosTestBase.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/QueryLoggingCosmosTestBase.cs @@ -43,11 +43,10 @@ public virtual async Task Queryable_simple() { Assert.Equal( CosmosResources.LogExecutingSqlQuery(new TestLogger()).GenerateMessage( - "NorthwindContext", "None", "", Environment.NewLine, + "Customers", "None", "", Environment.NewLine, """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """), Fixture.TestSqlLoggerFactory.Log[2].Message); } @@ -55,11 +54,10 @@ FROM root c { Assert.Equal( CosmosResources.LogExecutingSqlQuery(new TestLogger()).GenerateMessage( - "NorthwindContext", "?", "", Environment.NewLine, + "Customers", "?", "", Environment.NewLine, """ SELECT VALUE c FROM root c -WHERE (c["Discriminator"] = "Customer") """), Fixture.TestSqlLoggerFactory.Log[2].Message); } @@ -89,11 +87,11 @@ public virtual async Task Queryable_with_parameter_outputs_parameter_value_loggi { Assert.Equal( CosmosResources.LogExecutingSqlQuery(new TestLogger()).GenerateMessage( - "NorthwindContext", "None", "@__city_0='Redmond'", Environment.NewLine, + "Customers", "None", "@__city_0='Redmond'", Environment.NewLine, """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__city_0)) +WHERE (c["City"] = @__city_0) """), Fixture.TestSqlLoggerFactory.Log[3].Message); } @@ -101,11 +99,11 @@ FROM root c { Assert.Equal( CosmosResources.LogExecutingSqlQuery(new TestLogger()).GenerateMessage( - "NorthwindContext", "?", "@__city_0=?", Environment.NewLine, + "Customers", "?", "@__city_0=?", Environment.NewLine, """ SELECT VALUE c FROM root c -WHERE ((c["Discriminator"] = "Customer") AND (c["City"] = @__city_0)) +WHERE (c["City"] = @__city_0) """), Fixture.TestSqlLoggerFactory.Log[2].Message); } diff --git a/test/EFCore.Cosmos.FunctionalTests/Query/ReadItemPartitionKeyQueryTest.cs b/test/EFCore.Cosmos.FunctionalTests/Query/ReadItemPartitionKeyQueryTest.cs index ff923b54676..27ca46f0388 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Query/ReadItemPartitionKeyQueryTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Query/ReadItemPartitionKeyQueryTest.cs @@ -165,7 +165,7 @@ await AssertQuery( ss => ss.Set() .Where(e => e.Id == 1 && e.PartitionKey1 == "PK1" && e.PartitionKey2 == partitionKey2 && e.PartitionKey3)); - AssertSql("""ReadItem(["PK1",1.0,true], HierarchicalPartitionKeyEntity|1)"""); + AssertSql("""ReadItem(["PK1",1.0,true], 1)"""); } [ConditionalFact] @@ -175,7 +175,7 @@ await AssertQuery( async: true, ss => ss.Set().Where(e => e.Id == 1 && e.PartitionKey == "PK1")); - AssertSql("""ReadItem(["PK1"], SinglePartitionKeyEntity|1)"""); + AssertSql("""ReadItem(["PK1"], 1)"""); } [ConditionalFact] @@ -187,7 +187,7 @@ await AssertQuery( async: true, ss => ss.Set().Where(e => e.Id == 1 && e.PartitionKey == partitionKey)); - AssertSql("""ReadItem(["PK1"], SinglePartitionKeyEntity|1)"""); + AssertSql("""ReadItem(["PK1"], 1)"""); } [ConditionalFact] @@ -199,7 +199,7 @@ await AssertSingle( async: true, ss => ss.Set().Where(e => e.Id == 1 && e.PartitionKey == partitionKey)); - AssertSql("""ReadItem(["PK1"], SinglePartitionKeyEntity|1)"""); + AssertSql("""ReadItem(["PK1"], 1)"""); } [ConditionalFact] @@ -209,7 +209,7 @@ await AssertQuery( async: true, ss => ss.Set().Where(e => 1 == e.Id && "PK1" == e.PartitionKey)); - AssertSql("""ReadItem(["PK1"], SinglePartitionKeyEntity|1)"""); + AssertSql("""ReadItem(["PK1"], 1)"""); } [ConditionalFact] @@ -221,7 +221,7 @@ await AssertQuery( e => EF.Property(e, nameof(SinglePartitionKeyEntity.Id)) == 1 && EF.Property(e, nameof(SinglePartitionKeyEntity.PartitionKey)) == "PK1")); - AssertSql("""ReadItem(["PK1"], SinglePartitionKeyEntity|1)"""); + AssertSql("""ReadItem(["PK1"], 1)"""); } [ConditionalFact] @@ -232,7 +232,7 @@ await AssertQuery( ss => ss.Set().WithPartitionKey("PK1").Where(e => e.Id == 1), ss => ss.Set().Where(e => e.PartitionKey == "PK1").Where(e => e.Id == 1)); - AssertSql("""ReadItem(["PK1"], SinglePartitionKeyEntity|1)"""); + AssertSql("""ReadItem(["PK1"], 1)"""); } [ConditionalFact] @@ -260,7 +260,7 @@ await AssertQuery( async: true, ss => ss.Set().Where(e => e.Id == 1)); - AssertSql("ReadItem(None, NoPartitionKeyEntity|1)"); + AssertSql("""ReadItem(None, 1)"""); } [ConditionalFact] @@ -286,7 +286,7 @@ await AssertQuery( ss => ss.Set().Where(e => e.Id == 999 && e.PartitionKey == "PK1"), assertEmpty: true); - AssertSql("""ReadItem(["PK1"], SinglePartitionKeyEntity|999)"""); + AssertSql("""ReadItem(["PK1"], 999)"""); } [ConditionalFact] @@ -296,7 +296,7 @@ await AssertQuery( async: true, ss => ss.Set().AsNoTracking().Where(e => e.Id == 1 && e.PartitionKey == "PK1")); - AssertSql("""ReadItem(["PK1"], SinglePartitionKeyEntity|1)"""); + AssertSql("""ReadItem(["PK1"], 1)"""); } [ConditionalFact] @@ -306,7 +306,7 @@ await AssertQuery( async: true, ss => ss.Set().AsNoTrackingWithIdentityResolution().Where(e => e.Id == 1 && e.PartitionKey == "PK1")); - AssertSql("""ReadItem(["PK1"], SinglePartitionKeyEntity|1)"""); + AssertSql("""ReadItem(["PK1"], 1)"""); } [ConditionalFact] @@ -341,7 +341,7 @@ await AssertQuery( async: true, ss => ss.Set().Where(e => e.Id == 5 && e.PartitionKey == "PK2")); - AssertSql("""ReadItem(["PK2"], SharedContainerEntity2Child|5)"""); + AssertSql("""ReadItem(["PK2"], SharedContainerEntity2|5)"""); } private void AssertSql(params string[] expected) @@ -364,18 +364,26 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con modelBuilder.Entity() .ToContainer(nameof(HierarchicalPartitionKeyEntity)) .HasPartitionKey(h => new { h.PartitionKey1, h.PartitionKey2, h.PartitionKey3 }); + modelBuilder.Entity() .ToContainer(nameof(SinglePartitionKeyEntity)) .HasPartitionKey(h => h.PartitionKey); + modelBuilder.Entity() .ToContainer(nameof(NoPartitionKeyEntity)); + modelBuilder.Entity() .ToContainer("SharedContainer") + .IncludeRootDiscriminatorInJsonId() .HasPartitionKey(e => e.PartitionKey); + modelBuilder.Entity() .ToContainer("SharedContainer") + .IncludeRootDiscriminatorInJsonId() .HasPartitionKey(e => e.PartitionKey); + modelBuilder.Entity() + .IncludeRootDiscriminatorInJsonId() .HasPartitionKey(e => e.PartitionKey); } diff --git a/test/EFCore.Cosmos.FunctionalTests/QueryExpressionInterceptionWithDiagnosticsCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/QueryExpressionInterceptionWithDiagnosticsCosmosTest.cs index b75a2e4645b..76fc19127c4 100644 --- a/test/EFCore.Cosmos.FunctionalTests/QueryExpressionInterceptionWithDiagnosticsCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/QueryExpressionInterceptionWithDiagnosticsCosmosTest.cs @@ -32,6 +32,13 @@ protected override IServiceCollection InjectInterceptors( IEnumerable injectedInterceptors) => base.InjectInterceptors(serviceCollection.AddEntityFrameworkCosmos(), injectedInterceptors); + protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext context) + { + base.OnModelCreating(modelBuilder, context); + + modelBuilder.IncludeDiscriminatorInJsonId(); + } + protected override string StoreName => "QueryExpressionInterceptionWithDiagnostics"; diff --git a/test/EFCore.Cosmos.FunctionalTests/ReadItemTest.cs b/test/EFCore.Cosmos.FunctionalTests/ReadItemTest.cs new file mode 100644 index 00000000000..5f282702bb0 --- /dev/null +++ b/test/EFCore.Cosmos.FunctionalTests/ReadItemTest.cs @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/Basic_cosmos_model/DataEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/Basic_cosmos_model/DataEntityType.cs index 3231aa88c7e..0decd2a1cf5 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/Basic_cosmos_model/DataEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/Basic_cosmos_model/DataEntityType.cs @@ -33,7 +33,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas typeof(CompiledModelTestBase.Data), baseEntityType, propertyCount: 6, - keyCount: 2); + keyCount: 1); var id = runtimeEntityType.AddProperty( "Id", @@ -170,13 +170,13 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas string (InternalEntityEntry entry) => entry.ReadShadowValue(2), string (InternalEntityEntry entry) => entry.ReadShadowValue(2), string (InternalEntityEntry entry) => entry.ReadOriginalValue(__id, 3), - string (InternalEntityEntry entry) => entry.ReadRelationshipSnapshotValue(__id, 2), + string (InternalEntityEntry entry) => entry.GetCurrentValue(__id), object (ValueBuffer valueBuffer) => valueBuffer[3]); __id.SetPropertyIndexes( index: 3, originalValueIndex: 3, shadowIndex: 2, - relationshipIndex: 2, + relationshipIndex: -1, storeGenerationIndex: -1); __id.TypeMapping = CosmosTypeMapping.Default.Clone( comparer: new ValueComparer( @@ -193,7 +193,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas string (string v) => v), clrType: typeof(string), jsonValueReaderWriter: JsonStringReaderWriter.Instance); - __id.SetCurrentValueComparer(new EntryCurrentValueComparer(__id)); __id.AddAnnotation("Cosmos:PropertyName", "id"); var __jObject = runtimeEntityType.AddProperty( @@ -271,9 +270,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas new[] { id, partitionId }); runtimeEntityType.SetPrimaryKey(key); - var key0 = runtimeEntityType.AddKey( - new[] { __id, partitionId }); - return runtimeEntityType; } @@ -288,9 +284,6 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) var key = runtimeEntityType.FindKey(new[] { id, partitionId }); key.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateCompositeFactory(key)); key.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory>(key)); - var key0 = runtimeEntityType.FindKey(new[] { __id, partitionId }); - key0.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateCompositeFactory(key0)); - key0.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory>(key0)); runtimeEntityType.SetOriginalValuesFactory( ISnapshot (InternalEntityEntry source) => { @@ -309,7 +302,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (InternalEntityEntry source) => { var entity = ((CompiledModelTestBase.Data)(source.Entity)); - return ((ISnapshot)(new Snapshot(((ValueComparer)(((IProperty)id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(id)), (source.GetCurrentValue(partitionId) == null ? null : ((ValueComparer)(((IProperty)partitionId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(partitionId))), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(__id)))))); + return ((ISnapshot)(new Snapshot(((ValueComparer)(((IProperty)id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(id)), (source.GetCurrentValue(partitionId) == null ? null : ((ValueComparer)(((IProperty)partitionId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(partitionId)))))); }); runtimeEntityType.Counts = new PropertyCounts( propertyCount: 6, @@ -317,7 +310,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) complexPropertyCount: 0, originalValueCount: 6, shadowCount: 5, - relationshipCount: 3, + relationshipCount: 2, storeGeneratedCount: 2); runtimeEntityType.AddAnnotation("Cosmos:ContainerName", "DataContainer"); runtimeEntityType.AddAnnotation("Cosmos:ETagName", "_etag"); diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/DependentBaseEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/DependentBaseEntityType.cs index cee5a3c9319..4b19b39ecd1 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/DependentBaseEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/DependentBaseEntityType.cs @@ -37,7 +37,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas propertyCount: 6, navigationCount: 1, foreignKeyCount: 2, - keyCount: 2); + keyCount: 1); var principalId = runtimeEntityType.AddProperty( "PrincipalId", @@ -207,13 +207,13 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas string (InternalEntityEntry entry) => entry.ReadShadowValue(3), string (InternalEntityEntry entry) => entry.ReadShadowValue(3), string (InternalEntityEntry entry) => entry.ReadOriginalValue(__id, 4), - string (InternalEntityEntry entry) => entry.ReadRelationshipSnapshotValue(__id, 2), + string (InternalEntityEntry entry) => entry.GetCurrentValue(__id), object (ValueBuffer valueBuffer) => valueBuffer[4]); __id.SetPropertyIndexes( index: 4, originalValueIndex: 4, shadowIndex: 3, - relationshipIndex: 2, + relationshipIndex: -1, storeGenerationIndex: -1); __id.TypeMapping = CosmosTypeMapping.Default.Clone( comparer: new ValueComparer( @@ -230,7 +230,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas string (string v) => v), clrType: typeof(string), jsonValueReaderWriter: JsonStringReaderWriter.Instance); - __id.SetCurrentValueComparer(new EntryCurrentValueComparer(__id)); __id.AddAnnotation("Cosmos:PropertyName", "id"); var __jObject = runtimeEntityType.AddProperty( @@ -266,11 +265,8 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas __jObject.AddAnnotation("Cosmos:PropertyName", ""); var key = runtimeEntityType.AddKey( - new[] { __id }); - - var key0 = runtimeEntityType.AddKey( new[] { principalId, principalAlternateId }); - runtimeEntityType.SetPrimaryKey(key0); + runtimeEntityType.SetPrimaryKey(key); return runtimeEntityType; } @@ -322,7 +318,7 @@ public static RuntimeForeignKey CreateForeignKey2(RuntimeEntityType declaringEnt index: 0, originalValueIndex: -1, shadowIndex: -1, - relationshipIndex: 3, + relationshipIndex: 2, storeGenerationIndex: -1); var dependent = principalEntityType.AddNavigation("Dependent", runtimeForeignKey, @@ -352,7 +348,7 @@ public static RuntimeForeignKey CreateForeignKey2(RuntimeEntityType declaringEnt index: 2, originalValueIndex: -1, shadowIndex: -1, - relationshipIndex: 5, + relationshipIndex: 4, storeGenerationIndex: -1); return runtimeForeignKey; } @@ -365,12 +361,9 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) var id = runtimeEntityType.FindProperty("Id")!; var __id = runtimeEntityType.FindProperty("__id")!; var __jObject = runtimeEntityType.FindProperty("__jObject")!; - var key = runtimeEntityType.FindKey(new[] { __id }); - key.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateSimpleNullableFactory(key)); - key.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory(key)); - var key0 = runtimeEntityType.FindKey(new[] { principalId, principalAlternateId }); - key0.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateCompositeFactory(key0)); - key0.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory>(key0)); + var key = runtimeEntityType.FindKey(new[] { principalId, principalAlternateId }); + key.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateCompositeFactory(key)); + key.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory>(key)); var principal = runtimeEntityType.FindNavigation("Principal")!; runtimeEntityType.SetOriginalValuesFactory( ISnapshot (InternalEntityEntry source) => @@ -390,7 +383,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (InternalEntityEntry source) => { var entity = ((CompiledModelTestBase.DependentBase)(source.Entity)); - return ((ISnapshot)(new Snapshot(((ValueComparer)(((IProperty)principalId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(principalId)), ((ValueComparer)(((IProperty)principalAlternateId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(principalAlternateId)), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(__id))), DependentBaseUnsafeAccessors.Principal(entity)))); + return ((ISnapshot)(new Snapshot(((ValueComparer)(((IProperty)principalId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(principalId)), ((ValueComparer)(((IProperty)principalAlternateId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(principalAlternateId)), DependentBaseUnsafeAccessors.Principal(entity)))); }); runtimeEntityType.Counts = new PropertyCounts( propertyCount: 6, @@ -398,7 +391,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) complexPropertyCount: 0, originalValueCount: 6, shadowCount: 5, - relationshipCount: 4, + relationshipCount: 3, storeGeneratedCount: 2); runtimeEntityType.AddAnnotation("Cosmos:ContainerName", "Dependents"); runtimeEntityType.AddAnnotation("DiscriminatorMappingComplete", false); diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/DependentDerivedEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/DependentDerivedEntityType.cs index e75871136a9..8edddee0db0 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/DependentDerivedEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/DependentDerivedEntityType.cs @@ -142,7 +142,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (InternalEntityEntry source) => { var entity8 = ((CompiledModelTestBase.DependentDerived)(source.Entity)); - return ((ISnapshot)(new Snapshot(((ValueComparer)(((IProperty)principalId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(principalId)), ((ValueComparer)(((IProperty)principalAlternateId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(principalAlternateId)), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(__id))), DependentBaseUnsafeAccessors.Principal(entity8)))); + return ((ISnapshot)(new Snapshot(((ValueComparer)(((IProperty)principalId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(principalId)), ((ValueComparer)(((IProperty)principalAlternateId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(principalAlternateId)), DependentBaseUnsafeAccessors.Principal(entity8)))); }); runtimeEntityType.Counts = new PropertyCounts( propertyCount: 8, @@ -150,7 +150,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) complexPropertyCount: 0, originalValueCount: 8, shadowCount: 6, - relationshipCount: 4, + relationshipCount: 3, storeGeneratedCount: 2); runtimeEntityType.AddAnnotation("DiscriminatorMappingComplete", false); diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/ManyTypesEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/ManyTypesEntityType.cs index c5072b8c71b..1fff6f74634 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/ManyTypesEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/ManyTypesEntityType.cs @@ -40,7 +40,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas discriminatorProperty: "Discriminator", discriminatorValue: "ManyTypes", propertyCount: 261, - keyCount: 2); + keyCount: 1); var id = runtimeEntityType.AddProperty( "Id", @@ -15180,13 +15180,13 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas string (InternalEntityEntry entry) => entry.ReadShadowValue(1), string (InternalEntityEntry entry) => entry.ReadShadowValue(1), string (InternalEntityEntry entry) => entry.ReadOriginalValue(__id, 259), - string (InternalEntityEntry entry) => entry.ReadRelationshipSnapshotValue(__id, 1), + string (InternalEntityEntry entry) => entry.GetCurrentValue(__id), object (ValueBuffer valueBuffer) => valueBuffer[259]); __id.SetPropertyIndexes( index: 259, originalValueIndex: 259, shadowIndex: 1, - relationshipIndex: 1, + relationshipIndex: -1, storeGenerationIndex: -1); __id.TypeMapping = CosmosTypeMapping.Default.Clone( comparer: new ValueComparer( @@ -15203,7 +15203,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas string (string v) => v), clrType: typeof(string), jsonValueReaderWriter: JsonStringReaderWriter.Instance); - __id.SetCurrentValueComparer(new EntryCurrentValueComparer(__id)); __id.AddAnnotation("Cosmos:PropertyName", "id"); var __jObject = runtimeEntityType.AddProperty( @@ -15245,9 +15244,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas new[] { id }); runtimeEntityType.SetPrimaryKey(key); - var key0 = runtimeEntityType.AddKey( - new[] { __id }); - return runtimeEntityType; } @@ -15517,9 +15513,6 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) var key = runtimeEntityType.FindKey(new[] { id }); key.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateSimpleNonNullableFactory(key)); key.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory(key)); - var key0 = runtimeEntityType.FindKey(new[] { __id }); - key0.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateSimpleNullableFactory(key0)); - key0.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory(key0)); runtimeEntityType.SetOriginalValuesFactory( ISnapshot (InternalEntityEntry source) => { @@ -15554,7 +15547,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (InternalEntityEntry source) => { var entity8 = ((CompiledModelTestBase.ManyTypes)(source.Entity)); - return ((ISnapshot)(new Snapshot(((ValueComparer)(((IProperty)id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(id)), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(__id)))))); + return ((ISnapshot)(new Snapshot(((ValueComparer)(((IProperty)id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(id))))); }); runtimeEntityType.Counts = new PropertyCounts( propertyCount: 261, @@ -15562,7 +15555,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) complexPropertyCount: 0, originalValueCount: 261, shadowCount: 3, - relationshipCount: 2, + relationshipCount: 1, storeGeneratedCount: 2); Customize(runtimeEntityType); diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/OwnedType0EntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/OwnedType0EntityType.cs index a2d2acb486d..62ecad54415 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/OwnedType0EntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/OwnedType0EntityType.cs @@ -814,7 +814,7 @@ public static RuntimeForeignKey CreateForeignKey1(RuntimeEntityType declaringEnt index: 3, originalValueIndex: -1, shadowIndex: -1, - relationshipIndex: 6, + relationshipIndex: 5, storeGenerationIndex: -1); manyOwned.SetCollectionAccessor>, ICollection, CompiledModelTestBase.OwnedType>( ICollection (CompiledModelTestBase.PrincipalDerived> entity) => PrincipalDerivedUnsafeAccessors>.ManyOwned(entity), diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/OwnedTypeEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/OwnedTypeEntityType.cs index 2c6fe959b7e..d4629d51e10 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/OwnedTypeEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/OwnedTypeEntityType.cs @@ -796,7 +796,7 @@ public static RuntimeForeignKey CreateForeignKey1(RuntimeEntityType declaringEnt index: 0, originalValueIndex: -1, shadowIndex: -1, - relationshipIndex: 3, + relationshipIndex: 2, storeGenerationIndex: -1); return runtimeForeignKey; } diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBaseEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBaseEntityType.cs index 4922f477d23..035a10aca54 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBaseEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBaseEntityType.cs @@ -40,7 +40,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas propertyCount: 17, navigationCount: 1, skipNavigationCount: 1, - keyCount: 3); + keyCount: 2); var id = runtimeEntityType.AddProperty( "Id", @@ -869,13 +869,13 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas string (InternalEntityEntry entry) => entry.ReadShadowValue(1), string (InternalEntityEntry entry) => entry.ReadShadowValue(1), string (InternalEntityEntry entry) => entry.ReadOriginalValue(__id, 15), - string (InternalEntityEntry entry) => entry.ReadRelationshipSnapshotValue(__id, 2), + string (InternalEntityEntry entry) => entry.GetCurrentValue(__id), object (ValueBuffer valueBuffer) => valueBuffer[15]); __id.SetPropertyIndexes( index: 15, originalValueIndex: 15, shadowIndex: 1, - relationshipIndex: 2, + relationshipIndex: -1, storeGenerationIndex: -1); __id.TypeMapping = CosmosTypeMapping.Default.Clone( comparer: new ValueComparer( @@ -892,7 +892,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas string (string v) => v), clrType: typeof(string), jsonValueReaderWriter: JsonStringReaderWriter.Instance); - __id.SetCurrentValueComparer(new EntryCurrentValueComparer(__id)); __id.AddAnnotation("Cosmos:PropertyName", "id"); var __jObject = runtimeEntityType.AddProperty( @@ -931,11 +930,8 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas new[] { id }); var key0 = runtimeEntityType.AddKey( - new[] { __id }); - - var key1 = runtimeEntityType.AddKey( new[] { id, alternateId }); - runtimeEntityType.SetPrimaryKey(key1); + runtimeEntityType.SetPrimaryKey(key0); return runtimeEntityType; } @@ -981,7 +977,7 @@ public static RuntimeSkipNavigation CreateSkipNavigation1(RuntimeEntityType decl index: 1, originalValueIndex: -1, shadowIndex: -1, - relationshipIndex: 4, + relationshipIndex: 3, storeGenerationIndex: -1); skipNavigation.SetCollectionAccessor, CompiledModelTestBase.PrincipalBase>( ICollection (CompiledModelTestBase.PrincipalBase entity) => PrincipalBaseUnsafeAccessors.Deriveds(entity), @@ -1014,12 +1010,9 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) var key = runtimeEntityType.FindKey(new[] { id }); key.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateSimpleNullableFactory(key)); key.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory(key)); - var key0 = runtimeEntityType.FindKey(new[] { __id }); - key0.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateSimpleNullableFactory(key0)); - key0.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory(key0)); - var key1 = runtimeEntityType.FindKey(new[] { id, alternateId }); - key1.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateCompositeFactory(key1)); - key1.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory>(key1)); + var key0 = runtimeEntityType.FindKey(new[] { id, alternateId }); + key0.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateCompositeFactory(key0)); + key0.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory>(key0)); var owned = runtimeEntityType.FindNavigation("Owned")!; runtimeEntityType.SetOriginalValuesFactory( ISnapshot (InternalEntityEntry source) => @@ -1039,7 +1032,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (InternalEntityEntry source) => { var entity8 = ((CompiledModelTestBase.PrincipalBase)(source.Entity)); - return ((ISnapshot)(new Snapshot((source.GetCurrentValue(id) == null ? null : ((ValueComparer)(((IProperty)id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(id))), ((ValueComparer)(((IProperty)alternateId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(alternateId)), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(__id))), PrincipalBaseUnsafeAccessors._ownedField(entity8), null))); + return ((ISnapshot)(new Snapshot((source.GetCurrentValue(id) == null ? null : ((ValueComparer)(((IProperty)id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(id))), ((ValueComparer)(((IProperty)alternateId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(alternateId)), PrincipalBaseUnsafeAccessors._ownedField(entity8), null))); }); runtimeEntityType.Counts = new PropertyCounts( propertyCount: 17, @@ -1047,7 +1040,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) complexPropertyCount: 0, originalValueCount: 17, shadowCount: 3, - relationshipCount: 5, + relationshipCount: 4, storeGeneratedCount: 0); Customize(runtimeEntityType); diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs index c311823f3ac..7455b1a2274 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalBasePrincipalDerivedDependentBasebyteEntityType.cs @@ -39,7 +39,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas discriminatorValue: "PrincipalBasePrincipalDerived>", propertyCount: 8, foreignKeyCount: 2, - keyCount: 2); + keyCount: 1); var derivedsId = runtimeEntityType.AddProperty( "DerivedsId", @@ -383,13 +383,13 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas string (InternalEntityEntry entry) => ((string)((((IDictionary)((Dictionary)(entry.Entity))).ContainsKey("__id") ? ((Dictionary)(entry.Entity))["__id"] : null))), string (InternalEntityEntry entry) => ((string)((((IDictionary)((Dictionary)(entry.Entity))).ContainsKey("__id") ? ((Dictionary)(entry.Entity))["__id"] : null))), string (InternalEntityEntry entry) => entry.ReadOriginalValue(__id, 5), - string (InternalEntityEntry entry) => entry.ReadRelationshipSnapshotValue(__id, 4), + string (InternalEntityEntry entry) => entry.GetCurrentValue(__id), object (ValueBuffer valueBuffer) => valueBuffer[5]); __id.SetPropertyIndexes( index: 5, originalValueIndex: 5, shadowIndex: -1, - relationshipIndex: 4, + relationshipIndex: -1, storeGenerationIndex: -1); __id.TypeMapping = CosmosTypeMapping.Default.Clone( comparer: new ValueComparer( @@ -406,7 +406,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas string (string v) => v), clrType: typeof(string), jsonValueReaderWriter: JsonStringReaderWriter.Instance); - __id.SetCurrentValueComparer(new EntryCurrentValueComparer(__id)); __id.AddAnnotation("Cosmos:PropertyName", "id"); var __jObject = runtimeEntityType.AddProperty( @@ -503,11 +502,8 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas byte[] (string v) => Convert.FromBase64String(v)))); var key = runtimeEntityType.AddKey( - new[] { __id }); - - var key0 = runtimeEntityType.AddKey( new[] { derivedsId, derivedsAlternateId, principalsId, principalsAlternateId }); - runtimeEntityType.SetPrimaryKey(key0); + runtimeEntityType.SetPrimaryKey(key); return runtimeEntityType; } @@ -544,12 +540,9 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) var __id = runtimeEntityType.FindProperty("__id")!; var __jObject = runtimeEntityType.FindProperty("__jObject")!; var rowid = runtimeEntityType.FindProperty("rowid")!; - var key = runtimeEntityType.FindKey(new[] { __id }); - key.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateSimpleNullableFactory(key)); - key.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory(key)); - var key0 = runtimeEntityType.FindKey(new[] { derivedsId, derivedsAlternateId, principalsId, principalsAlternateId }); - key0.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateCompositeFactory(key0)); - key0.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory>(key0)); + var key = runtimeEntityType.FindKey(new[] { derivedsId, derivedsAlternateId, principalsId, principalsAlternateId }); + key.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateCompositeFactory(key)); + key.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory>(key)); runtimeEntityType.SetOriginalValuesFactory( ISnapshot (InternalEntityEntry source) => { @@ -568,7 +561,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (InternalEntityEntry source) => { var entity8 = ((Dictionary)(source.Entity)); - return ((ISnapshot)(new Snapshot(((ValueComparer)(((IProperty)derivedsId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(derivedsId)), ((ValueComparer)(((IProperty)derivedsAlternateId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(derivedsAlternateId)), ((ValueComparer)(((IProperty)principalsId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(principalsId)), ((ValueComparer)(((IProperty)principalsAlternateId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(principalsAlternateId)), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(__id)))))); + return ((ISnapshot)(new Snapshot(((ValueComparer)(((IProperty)derivedsId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(derivedsId)), ((ValueComparer)(((IProperty)derivedsAlternateId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(derivedsAlternateId)), ((ValueComparer)(((IProperty)principalsId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(principalsId)), ((ValueComparer)(((IProperty)principalsAlternateId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(principalsAlternateId))))); }); runtimeEntityType.Counts = new PropertyCounts( propertyCount: 8, @@ -576,7 +569,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) complexPropertyCount: 0, originalValueCount: 8, shadowCount: 0, - relationshipCount: 5, + relationshipCount: 4, storeGeneratedCount: 5); Customize(runtimeEntityType); diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalDerivedEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalDerivedEntityType.cs index 4df04608e96..9668904e10a 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalDerivedEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/BigModel/PrincipalDerivedEntityType.cs @@ -75,7 +75,7 @@ public static RuntimeSkipNavigation CreateSkipNavigation1(RuntimeEntityType decl index: 4, originalValueIndex: -1, shadowIndex: -1, - relationshipIndex: 7, + relationshipIndex: 6, storeGenerationIndex: -1); skipNavigation.SetCollectionAccessor>, ICollection, CompiledModelTestBase.PrincipalBase>( ICollection (CompiledModelTestBase.PrincipalDerived> entity) => PrincipalDerivedUnsafeAccessors>.Principals(entity), @@ -126,7 +126,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (InternalEntityEntry source) => { var entity8 = ((CompiledModelTestBase.PrincipalDerived>)(source.Entity)); - return ((ISnapshot)(new Snapshot((source.GetCurrentValue(id) == null ? null : ((ValueComparer)(((IProperty)id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(id))), ((ValueComparer)(((IProperty)alternateId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(alternateId)), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(__id))), PrincipalBaseUnsafeAccessors._ownedField(entity8), null, PrincipalDerivedUnsafeAccessors>.Dependent(entity8), SnapshotFactoryFactory.SnapshotCollection(PrincipalDerivedUnsafeAccessors>.ManyOwned(entity8)), null))); + return ((ISnapshot)(new Snapshot((source.GetCurrentValue(id) == null ? null : ((ValueComparer)(((IProperty)id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(id))), ((ValueComparer)(((IProperty)alternateId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(alternateId)), PrincipalBaseUnsafeAccessors._ownedField(entity8), null, PrincipalDerivedUnsafeAccessors>.Dependent(entity8), SnapshotFactoryFactory.SnapshotCollection(PrincipalDerivedUnsafeAccessors>.ManyOwned(entity8)), null))); }); runtimeEntityType.Counts = new PropertyCounts( propertyCount: 17, @@ -134,7 +134,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) complexPropertyCount: 0, originalValueCount: 17, shadowCount: 3, - relationshipCount: 8, + relationshipCount: 7, storeGeneratedCount: 0); Customize(runtimeEntityType); diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs index 5cf9423859d..ac755a0c98e 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalBaseEntityType.cs @@ -41,7 +41,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas complexPropertyCount: 1, navigationCount: 1, foreignKeyCount: 1, - keyCount: 2); + keyCount: 1); var id = runtimeEntityType.AddProperty( "Id", @@ -856,13 +856,13 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas string (InternalEntityEntry entry) => entry.ReadShadowValue(2), string (InternalEntityEntry entry) => entry.ReadShadowValue(2), string (InternalEntityEntry entry) => entry.ReadOriginalValue(__id, 15), - string (InternalEntityEntry entry) => entry.ReadRelationshipSnapshotValue(__id, 2), + string (InternalEntityEntry entry) => entry.GetCurrentValue(__id), object (ValueBuffer valueBuffer) => valueBuffer[15]); __id.SetPropertyIndexes( index: 15, originalValueIndex: 15, shadowIndex: 2, - relationshipIndex: 2, + relationshipIndex: -1, storeGenerationIndex: -1); __id.TypeMapping = CosmosTypeMapping.Default.Clone( comparer: new ValueComparer( @@ -879,7 +879,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas string (string v) => v), clrType: typeof(string), jsonValueReaderWriter: JsonStringReaderWriter.Instance); - __id.SetCurrentValueComparer(new EntryCurrentValueComparer(__id)); __id.AddAnnotation("Cosmos:PropertyName", "id"); var __jObject = runtimeEntityType.AddProperty( @@ -919,9 +918,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas new[] { id }); runtimeEntityType.SetPrimaryKey(key); - var key0 = runtimeEntityType.AddKey( - new[] { __id }); - return runtimeEntityType; } @@ -2635,7 +2631,7 @@ public static RuntimeForeignKey CreateForeignKey1(RuntimeEntityType declaringEnt index: 0, originalValueIndex: -1, shadowIndex: -1, - relationshipIndex: 3, + relationshipIndex: 2, storeGenerationIndex: -1); deriveds.SetCollectionAccessor, CompiledModelTestBase.PrincipalBase>( ICollection (CompiledModelTestBase.PrincipalBase entity) => PrincipalBaseUnsafeAccessors.Deriveds(entity), @@ -2696,9 +2692,6 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) var key = runtimeEntityType.FindKey(new[] { id }); key.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateSimpleNullableFactory(key)); key.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory(key)); - var key0 = runtimeEntityType.FindKey(new[] { __id }); - key0.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateSimpleNullableFactory(key0)); - key0.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory(key0)); var deriveds = runtimeEntityType.FindNavigation("Deriveds")!; runtimeEntityType.SetOriginalValuesFactory( ISnapshot (InternalEntityEntry source) => @@ -2720,7 +2713,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (InternalEntityEntry source) => { var entity1 = ((CompiledModelTestBase.PrincipalBase)(source.Entity)); - return ((ISnapshot)(new Snapshot((source.GetCurrentValue(id) == null ? null : ((ValueComparer)(((IProperty)id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(id))), (source.GetCurrentValue(principalBaseId) == null ? null : ((ValueComparer)(((IProperty)principalBaseId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(principalBaseId))), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(__id))), SnapshotFactoryFactory.SnapshotCollection(PrincipalBaseUnsafeAccessors.Deriveds(entity1))))); + return ((ISnapshot)(new Snapshot((source.GetCurrentValue(id) == null ? null : ((ValueComparer)(((IProperty)id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(id))), (source.GetCurrentValue(principalBaseId) == null ? null : ((ValueComparer)(((IProperty)principalBaseId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(principalBaseId))), SnapshotFactoryFactory.SnapshotCollection(PrincipalBaseUnsafeAccessors.Deriveds(entity1))))); }); runtimeEntityType.Counts = new PropertyCounts( propertyCount: 41, @@ -2728,7 +2721,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) complexPropertyCount: 2, originalValueCount: 41, shadowCount: 4, - relationshipCount: 4, + relationshipCount: 3, storeGeneratedCount: 1); Customize(runtimeEntityType); diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalDerivedEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalDerivedEntityType.cs index f48dc7cf08e..d641906db9c 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalDerivedEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/ComplexTypes/PrincipalDerivedEntityType.cs @@ -100,7 +100,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (InternalEntityEntry source) => { var entity3 = ((CompiledModelTestBase.PrincipalDerived>)(source.Entity)); - return ((ISnapshot)(new Snapshot((source.GetCurrentValue(id) == null ? null : ((ValueComparer)(((IProperty)id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(id))), (source.GetCurrentValue(principalBaseId) == null ? null : ((ValueComparer)(((IProperty)principalBaseId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(principalBaseId))), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(__id))), SnapshotFactoryFactory.SnapshotCollection(PrincipalBaseUnsafeAccessors.Deriveds(entity3))))); + return ((ISnapshot)(new Snapshot((source.GetCurrentValue(id) == null ? null : ((ValueComparer)(((IProperty)id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(id))), (source.GetCurrentValue(principalBaseId) == null ? null : ((ValueComparer)(((IProperty)principalBaseId).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(principalBaseId))), SnapshotFactoryFactory.SnapshotCollection(PrincipalBaseUnsafeAccessors.Deriveds(entity3))))); }); runtimeEntityType.Counts = new PropertyCounts( propertyCount: 41, @@ -108,7 +108,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) complexPropertyCount: 2, originalValueCount: 41, shadowCount: 4, - relationshipCount: 4, + relationshipCount: 3, storeGeneratedCount: 1); Customize(runtimeEntityType); diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs index 565c5c4f909..aaeeeedef92 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/Baselines/SimpleModel/DependentDerivedEntityType.cs @@ -32,7 +32,7 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas discriminatorProperty: "Discriminator", discriminatorValue: "DependentDerived", propertyCount: 5, - keyCount: 2); + keyCount: 1); var id = runtimeEntityType.AddProperty( "Id", @@ -164,13 +164,13 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas string (InternalEntityEntry entry) => entry.ReadShadowValue(1), string (InternalEntityEntry entry) => entry.ReadShadowValue(1), string (InternalEntityEntry entry) => entry.ReadOriginalValue(__id, 3), - string (InternalEntityEntry entry) => entry.ReadRelationshipSnapshotValue(__id, 1), + string (InternalEntityEntry entry) => entry.GetCurrentValue(__id), object (ValueBuffer valueBuffer) => valueBuffer[3]); __id.SetPropertyIndexes( index: 3, originalValueIndex: 3, shadowIndex: 1, - relationshipIndex: 1, + relationshipIndex: -1, storeGenerationIndex: -1); __id.TypeMapping = CosmosTypeMapping.Default.Clone( comparer: new ValueComparer( @@ -187,7 +187,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas string (string v) => v), clrType: typeof(string), jsonValueReaderWriter: JsonStringReaderWriter.Instance); - __id.SetCurrentValueComparer(new EntryCurrentValueComparer(__id)); __id.AddAnnotation("Cosmos:PropertyName", "id"); var __jObject = runtimeEntityType.AddProperty( @@ -229,9 +228,6 @@ public static RuntimeEntityType Create(RuntimeModel model, RuntimeEntityType bas new[] { id }); runtimeEntityType.SetPrimaryKey(key); - var key0 = runtimeEntityType.AddKey( - new[] { __id }); - return runtimeEntityType; } @@ -245,9 +241,6 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) var key = runtimeEntityType.FindKey(new[] { id }); key.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateSimpleNonNullableFactory(key)); key.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory(key)); - var key0 = runtimeEntityType.FindKey(new[] { __id }); - key0.SetPrincipalKeyValueFactory(KeyValueFactoryFactory.CreateSimpleNullableFactory(key0)); - key0.SetIdentityMapFactory(IdentityMapFactoryFactory.CreateFactory(key0)); runtimeEntityType.SetOriginalValuesFactory( ISnapshot (InternalEntityEntry source) => { @@ -266,7 +259,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) ISnapshot (InternalEntityEntry source) => { var entity = ((CompiledModelTestBase.DependentDerived)(source.Entity)); - return ((ISnapshot)(new Snapshot(((ValueComparer)(((IProperty)id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(id)), (source.GetCurrentValue(__id) == null ? null : ((ValueComparer)(((IProperty)__id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(__id)))))); + return ((ISnapshot)(new Snapshot(((ValueComparer)(((IProperty)id).GetKeyValueComparer())).Snapshot(source.GetCurrentValue(id))))); }); runtimeEntityType.Counts = new PropertyCounts( propertyCount: 5, @@ -274,7 +267,7 @@ public static void CreateAnnotations(RuntimeEntityType runtimeEntityType) complexPropertyCount: 0, originalValueCount: 5, shadowCount: 3, - relationshipCount: 2, + relationshipCount: 1, storeGeneratedCount: 1); Customize(runtimeEntityType); diff --git a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/CompiledModelCosmosTest.cs b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/CompiledModelCosmosTest.cs index f37321b37b5..d8b6e13ed54 100644 --- a/test/EFCore.Cosmos.FunctionalTests/Scaffolding/CompiledModelCosmosTest.cs +++ b/test/EFCore.Cosmos.FunctionalTests/Scaffolding/CompiledModelCosmosTest.cs @@ -141,7 +141,7 @@ public virtual Task Basic_cosmos_model() Assert.NotNull(jObject.GetValueComparer()); Assert.NotNull(jObject.GetKeyValueComparer()); - Assert.Equal(2, dataEntity.GetKeys().Count()); + Assert.Equal(1, dataEntity.GetKeys().Count()); Assert.Equal([id, partitionId, blob, storeId, jObject, eTag], dataEntity.GetProperties()); }); diff --git a/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosTestStore.cs b/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosTestStore.cs index 5da83c83566..ff58cdcadf4 100644 --- a/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosTestStore.cs +++ b/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CosmosTestStore.cs @@ -3,7 +3,6 @@ using System.Net; using System.Net.Sockets; -using System.Threading; using Azure; using Azure.Core; using Azure.ResourceManager; @@ -188,6 +187,8 @@ private async Task CreateFromFile(DbContext context) if (reader.TokenType == JsonToken.StartObject) { string? entityName = null; + string? containerName = null; + bool? discriminatorInId = null; while (reader.Read()) { if (reader.TokenType == JsonToken.PropertyName) @@ -198,6 +199,14 @@ private async Task CreateFromFile(DbContext context) reader.Read(); entityName = (string)reader.Value; break; + case "Container": + reader.Read(); + containerName = (string)reader.Value; + break; + case "DiscriminatorInId": + reader.Read(); + discriminatorInId = (bool)reader.Value; + break; case "Data": while (reader.Read()) { @@ -205,11 +214,14 @@ private async Task CreateFromFile(DbContext context) { var document = serializer.Deserialize(reader)!; - document["id"] = $"{entityName}|{document["id"]}"; + document["id"] = discriminatorInId == true + ? $"{entityName}|{document["id"]}" + : $"{document["id"]}"; + document["Discriminator"] = entityName; await cosmosClient.CreateItemAsync( - "NorthwindContext", document, new FakeUpdateEntry()).ConfigureAwait(false); + containerName!, document, new FakeUpdateEntry()).ConfigureAwait(false); } else if (reader.TokenType == JsonToken.EndObject) { diff --git a/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CustomRuntimeJsonIdDefinition.cs b/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CustomJsonIdDefinition.cs similarity index 82% rename from test/EFCore.Cosmos.FunctionalTests/TestUtilities/CustomRuntimeJsonIdDefinition.cs rename to test/EFCore.Cosmos.FunctionalTests/TestUtilities/CustomJsonIdDefinition.cs index af82dc44289..2cc9628ed95 100644 --- a/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CustomRuntimeJsonIdDefinition.cs +++ b/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CustomJsonIdDefinition.cs @@ -5,8 +5,8 @@ namespace Microsoft.EntityFrameworkCore.TestUtilities; -public class CustomJsonIdDefinition(IReadOnlyList properties) - : JsonIdDefinition(properties) +public class CustomJsonIdDefinition(IReadOnlyList properties, IEntityType? discriminatorEntityType) + : JsonIdDefinition(properties, discriminatorEntityType) { public override string GenerateIdString(IEnumerable values) { diff --git a/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CustomRuntimeJsonIdDefinitionFactory.cs b/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CustomJsonIdDefinitionFactory.cs similarity index 59% rename from test/EFCore.Cosmos.FunctionalTests/TestUtilities/CustomRuntimeJsonIdDefinitionFactory.cs rename to test/EFCore.Cosmos.FunctionalTests/TestUtilities/CustomJsonIdDefinitionFactory.cs index cab262e21af..2e2585db62f 100644 --- a/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CustomRuntimeJsonIdDefinitionFactory.cs +++ b/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CustomJsonIdDefinitionFactory.cs @@ -7,6 +7,9 @@ namespace Microsoft.EntityFrameworkCore.TestUtilities; public class CustomJsonIdDefinitionFactory : JsonIdDefinitionFactory { - public override IJsonIdDefinition? Create(IEntityType entityType) - => new CustomJsonIdDefinition(base.Create(entityType)!.Properties); + public override IJsonIdDefinition Create(IEntityType entityType) + { + var baseDef = base.Create(entityType)!; + return new CustomJsonIdDefinition(baseDef.Properties, baseDef.DiscriminatorEntityType); + } } diff --git a/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CustomPartitionKeyIdGenerator.cs b/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CustomPartitionKeyIdGenerator.cs index 11dd9703290..ce73f7cad6f 100644 --- a/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CustomPartitionKeyIdGenerator.cs +++ b/test/EFCore.Cosmos.FunctionalTests/TestUtilities/CustomPartitionKeyIdGenerator.cs @@ -33,7 +33,7 @@ protected override object NextValue(EntityEntry entry) foreach (var property in primaryKey.Properties) { if (partitionKeyNames.Contains(property.Name) - || property.GetJsonPropertyName() == StoreKeyConvention.IdPropertyJsonName) + || property.GetJsonPropertyName() == CosmosJsonIdConvention.IdPropertyJsonName) { continue; } diff --git a/test/EFCore.Cosmos.Tests/Infrastructure/CosmosModelValidatorTest.cs b/test/EFCore.Cosmos.Tests/Infrastructure/CosmosModelValidatorTest.cs index 6a65e2d667e..6ca72a5b034 100644 --- a/test/EFCore.Cosmos.Tests/Infrastructure/CosmosModelValidatorTest.cs +++ b/test/EFCore.Cosmos.Tests/Infrastructure/CosmosModelValidatorTest.cs @@ -46,25 +46,6 @@ public virtual void Detects_missing_id_property() VerifyError(CosmosStrings.NoIdProperty(nameof(Order)), modelBuilder); } - [ConditionalFact] - public virtual void Detects_non_key_id_property() - { - var modelBuilder = CreateConventionlessModelBuilder(); - modelBuilder.Entity( - b => - { - b.Property(o => o.Id); - b.HasKey(o => o.Id); - b.Property("id"); - b.Ignore(o => o.PartitionId); - b.Ignore(o => o.Customer); - b.Ignore(o => o.OrderDetails); - b.Ignore(o => o.Products); - }); - - VerifyError(CosmosStrings.NoIdKey(nameof(Order), "id"), modelBuilder); - } - [ConditionalFact] public virtual void Detects_non_string_id_property() { @@ -115,26 +96,6 @@ public virtual void Passes_PK_partition_key() Validate(modelBuilder); } - [ConditionalFact] - public virtual void Detects_non_key_partition_key_property() - { - var modelBuilder = CreateConventionlessModelBuilder(); - modelBuilder.Entity( - b => - { - b.Property(o => o.Id); - b.Property("id"); - b.HasKey("id"); - b.Property(o => o.PartitionId); - b.HasPartitionKey(o => o.PartitionId); - b.Ignore(o => o.Customer); - b.Ignore(o => o.OrderDetails); - b.Ignore(o => o.Products); - }); - - VerifyError(CosmosStrings.NoPartitionKeyKey(nameof(Order), nameof(Order.PartitionId), "id"), modelBuilder); - } - [ConditionalFact] public virtual void Detects_missing_partition_key_property() { @@ -340,11 +301,16 @@ public virtual void Detects_owned_type_mapped_to_a_container() var modelBuilder = CreateConventionModelBuilder(); modelBuilder.Entity(); modelBuilder.Entity( - ob => + ob => ob.OwnsOne(o => o.OrderDetails, b => { - var ownedType = ob.OwnsOne(o => o.OrderDetails).OwnedEntityType; - ownedType.SetContainer("Details"); - }); + b.Property(CosmosJsonIdConvention.DefaultIdPropertyName) + .ToJsonProperty(CosmosJsonIdConvention.IdPropertyJsonName); + })); + + modelBuilder.Model + .GetEntityTypes() + .Single(e => e.ClrType == typeof(OrderDetails)) + .SetContainer("Details"); VerifyError( CosmosStrings.OwnedTypeDifferentContainer( diff --git a/test/EFCore.Cosmos.Tests/ValueGeneration/IdValueGeneratorTest.cs b/test/EFCore.Cosmos.Tests/ValueGeneration/IdValueGeneratorTest.cs index 5edf68d9006..b04a9c41cfb 100644 --- a/test/EFCore.Cosmos.Tests/ValueGeneration/IdValueGeneratorTest.cs +++ b/test/EFCore.Cosmos.Tests/ValueGeneration/IdValueGeneratorTest.cs @@ -10,6 +10,8 @@ public void Generated_ids_do_not_clash() { var modelBuilder = CosmosTestHelpers.Instance.CreateConventionBuilder(); + modelBuilder.IncludeDiscriminatorInJsonId(); + modelBuilder.Entity().HasKey(p => new { p.OtherId, p.Id }); modelBuilder.Entity().HasKey(p => new { p.OtherId, p.Id }); @@ -39,7 +41,7 @@ public void Generated_ids_do_not_clash() string Create(TEntity entity) where TEntity : class, new() => (string)CosmosTestHelpers.Instance.CreateInternalEntry(model, EntityState.Added, entity) - [model.FindEntityType(typeof(TEntity)).FindProperty(StoreKeyConvention.DefaultIdPropertyName)]; + [model.FindEntityType(typeof(TEntity)).FindProperty(CosmosJsonIdConvention.DefaultIdPropertyName)]; } private class Blog diff --git a/test/EFCore.Specification.Tests/Query/NorthwindMiscellaneousQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/NorthwindMiscellaneousQueryTestBase.cs index dee6147bff4..635b88b57e9 100644 --- a/test/EFCore.Specification.Tests/Query/NorthwindMiscellaneousQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/NorthwindMiscellaneousQueryTestBase.cs @@ -2183,7 +2183,7 @@ orderby c.CustomerID from o in ss.Set() select c)); - private class Foo + protected class Foo { public string Bar { get; set; } }