From 13bb7d28e0022edab5e7a47ca5538bf7aab496f0 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Sun, 3 Dec 2023 13:27:11 +0100 Subject: [PATCH] Handle updating complex type properties in ExecuteUpdate Closes #32058 --- ...nslatingExpressionVisitor.ExecuteUpdate.cs | 416 ++++++++++++++---- .../ComplexTypeBulkUpdatesTestBase.cs | 115 +++++ .../TestUtilities/TestSqlLoggerFactory.cs | 2 +- .../Query/ComplexTypeQueryTestBase.cs | 34 +- .../ComplexTypeModel/ComplexTypeData.cs | 12 +- .../TestModels/ComplexTypeModel/Model.cs | 1 + .../ComplexTypeBulkUpdatesSqlServerTest.cs | 128 ++++++ .../Query/ComplexTypeQuerySqlServerTest.cs | 62 +-- .../Query/ComplexTypeQuerySqliteTest.cs | 62 +-- 9 files changed, 669 insertions(+), 163 deletions(-) diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs index 29caad46004..9473fb1ab9a 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs @@ -9,6 +9,11 @@ namespace Microsoft.EntityFrameworkCore.Query; public partial class RelationalQueryableMethodTranslatingExpressionVisitor { + private const string ExecuteUpdateRuntimeParameterPrefix = QueryCompilationContext.QueryParameterPrefix + "complex_type_"; + + private static readonly MethodInfo ParameterValueExtractorMethod = + typeof(RelationalSqlTranslatingExpressionVisitor).GetTypeInfo().GetDeclaredMethod(nameof(ParameterValueExtractor))!; + /// /// Translates /// (); - PopulateSetPropertyCalls(setPropertyCalls.Body, propertyValueLambdaExpressions, setPropertyCalls.Parameters[0]); + var setters = new List<(LambdaExpression PropertySelector, Expression ValueExpression)>(); + PopulateSetPropertyCalls(setPropertyCalls.Body, setters, setPropertyCalls.Parameters[0]); if (TranslationErrorDetails != null) { return null; } - if (propertyValueLambdaExpressions.Count == 0) + if (setters.Count == 0) { AddTranslationErrorDetails(RelationalStrings.NoSetPropertyInvocation); return null; } - // Go over the SetProperty calls, and translate the property selectors (left lambda). - // The property selectors should get translated to ColumnExpressions (otherwise they' invalid - columns are what we need to update). - // All columns must also refer to the same table (since that's how SQL UPDATE works), extract that target table from the translated - // columns and validate that only one table is being referenced. - // Note that we don't translate the value expressions in this pass, since if the query is complicated, we may need to do a pushdown - // (see PushdownWithPkInnerJoinPredicate below); so we defer translation until we have the final source/select. For the property - // selectors we need to translate now since we need the table. - TableExpressionBase? targetTable = null; - Expression? targetTablePropertySelector = null; - var columns = new ColumnExpression[propertyValueLambdaExpressions.Count]; - for (var i = 0; i < propertyValueLambdaExpressions.Count; i++) - { - var (propertySelector, _) = propertyValueLambdaExpressions[i]; - var propertySelectorBody = RemapLambdaBody(source, propertySelector).UnwrapTypeConversion(out _); - if (_sqlTranslator.Translate(propertySelectorBody) is not ColumnExpression column) - { - AddTranslationErrorDetails(RelationalStrings.InvalidPropertyInSetProperty(propertySelector.Print())); - return null; - } - - if (targetTable is null) - { - targetTable = column.Table; - targetTablePropertySelector = propertySelector; - } - else if (!ReferenceEquals(column.Table, targetTable)) - { - AddTranslationErrorDetails( - RelationalStrings.MultipleTablesInExecuteUpdate(propertySelector.Print(), targetTablePropertySelector!.Print())); - return null; - } - - columns[i] = column; - } - - Check.DebugAssert(targetTable is not null, "Target table should have a value"); - - if (targetTable is TpcTablesExpression tpcTablesExpression) + // Translate the setters: the left (property) selectors get translated to ColumnExpressions, the right (value) selectors to + // arbitrary SqlExpressions. + // Note that if the query isn't natively supported, we'll do a pushdown (see PushdownWithPkInnerJoinPredicate below); if that + // happens, we'll have to re-translate the setters over the new query (which includes a JOIN). However, we still translate here + // since we need the target table in order to perform the check below. + if (!TranslateSetters(source, setters, out var translatedSetters, out var targetTable)) { - AddTranslationErrorDetails( - RelationalStrings.ExecuteOperationOnTPC( - nameof(RelationalQueryableExtensions.ExecuteUpdate), tpcTablesExpression.EntityType.DisplayName())); return null; } - // First, check if the provider has a native translation for the update represented by the select expression. + // Check if the provider has a native translation for the update represented by the select expression. // The default relational implementation handles simple, universally-supported cases (i.e. no operators except for predicate). // Providers may override IsValidSelectExpressionForExecuteUpdate to add support for more cases via provider-specific UPDATE syntax. var selectExpression = (SelectExpression)source.QueryExpression; - return IsValidSelectExpressionForExecuteUpdate(selectExpression, targetTable, out var tableExpression) - ? TranslateValueExpressions(this, source, selectExpression, tableExpression, propertyValueLambdaExpressions, columns) - : PushdownWithPkInnerJoinPredicate(); + if (IsValidSelectExpressionForExecuteUpdate(selectExpression, targetTable, out var tableExpression)) + { + selectExpression.ReplaceProjection(new List()); + selectExpression.ApplyProjection(); + + return new NonQueryExpression(new UpdateExpression(tableExpression, selectExpression, translatedSetters)); + } + + return PushdownWithPkInnerJoinPredicate(); void PopulateSetPropertyCalls( Expression expression, @@ -132,49 +108,274 @@ when methodCallExpression.Method.DeclaringType.GetGenericTypeDefinition() == typ } } - static NonQueryExpression? TranslateValueExpressions( - RelationalQueryableMethodTranslatingExpressionVisitor visitor, + bool TranslateSetters( ShapedQueryExpression source, - SelectExpression selectExpression, - TableExpression tableExpression, - List<(LambdaExpression PropertySelector, Expression ValueExpression)> propertyValueLambdaExpression, - ColumnExpression[] columns) + List<(LambdaExpression PropertySelector, Expression ValueExpression)> setters, + [NotNullWhen(true)] out List? translatedSetters, + [NotNullWhen(true)] out TableExpressionBase? targetTable) { - var setters = new ColumnValueSetter[columns.Length]; + var selectExpression = (SelectExpression)source.QueryExpression; + + targetTable = null; + TableExpressionBase? tempTargetTable = null; + var tempTranslatedSetters = new List(); + translatedSetters = null; + + LambdaExpression? propertySelector; + Expression? targetTablePropertySelector = null; + + for (var i = 0; i < setters.Count; i++) + { + (propertySelector, var valueSelector) = setters[i]; + var propertySelectorBody = RemapLambdaBody(source, propertySelector).UnwrapTypeConversion(out _); + + switch (_sqlTranslator.TranslateProjection(propertySelectorBody)) + { + case ColumnExpression column: + { + if (!IsColumnOnSameTable(column, propertySelector) + || TranslateSqlSetterValueSelector(source, valueSelector, column, selectExpression) is not SqlExpression + translatedValueSelector) + { + return false; + } - for (var i = 0; i < propertyValueLambdaExpression.Count; i++) + tempTranslatedSetters.Add(new(column, translatedValueSelector)); + break; + } + + // TODO: This is for column flattening; implement JSON complex type support as well. + case StructuralTypeShaperExpression + { + StructuralType: IComplexType, + ValueBufferExpression: StructuralTypeProjectionExpression + } shaper: + { + if (TranslateSetterValueSelector(source, valueSelector, shaper.Type) is not Expression translatedValueSelector + || !TryProcessComplexType(shaper, translatedValueSelector)) + { + return false; + } + + break; + } + + default: + AddTranslationErrorDetails(RelationalStrings.InvalidPropertyInSetProperty(propertySelector.Print())); + return false; + } + } + + targetTable = tempTargetTable; + translatedSetters = tempTranslatedSetters; + + Check.DebugAssert(targetTable is not null, "Target table should have a value"); + + if (targetTable is TpcTablesExpression tpcTablesExpression) + { + AddTranslationErrorDetails( + RelationalStrings.ExecuteOperationOnTPC( + nameof(RelationalQueryableExtensions.ExecuteUpdate), tpcTablesExpression.EntityType.DisplayName())); + return false; + } + + return true; + + bool IsColumnOnSameTable(ColumnExpression column, LambdaExpression propertySelector) + { + if (tempTargetTable is null) + { + tempTargetTable = column.Table; + targetTablePropertySelector = propertySelector; + } + else if (!ReferenceEquals(column.Table, tempTargetTable)) + { + AddTranslationErrorDetails( + RelationalStrings.MultipleTablesInExecuteUpdate( + propertySelector.Print(), targetTablePropertySelector!.Print())); + return false; + } + + return true; + } + + bool TryProcessComplexType(StructuralTypeShaperExpression shaperExpression, Expression valueExpression) { - var column = columns[i]; - var (_, valueSelector) = propertyValueLambdaExpression[i]; + if (shaperExpression.StructuralType is not IComplexType complexType + || shaperExpression.ValueBufferExpression is not StructuralTypeProjectionExpression projection) + { + return false; + } + + foreach (var property in complexType.GetProperties()) + { + var column = projection.BindProperty(property); + if (!IsColumnOnSameTable(column, propertySelector)) + { + return false; + } + + var rewrittenValueSelector = CreatePropertyAccessExpression(valueExpression, property); + if (TranslateSqlSetterValueSelector(source, rewrittenValueSelector, column, selectExpression) is not SqlExpression + translatedValueSelector) + { + return false; + } - var remappedValueSelector = valueSelector is LambdaExpression lambdaExpression - ? visitor.RemapLambdaBody(source, lambdaExpression) - : valueSelector; + tempTranslatedSetters.Add(new(column, translatedValueSelector)); + } - if (remappedValueSelector.Type != column.Type) + foreach (var complexProperty in complexType.GetComplexProperties()) { - remappedValueSelector = Expression.Convert(remappedValueSelector, column.Type); + // Note that TranslateProjection currently returns null for StructuralTypeReferenceExpression with a subquery (as + // opposed to a parameter); this ensures that we don't generate an efficient translation where the subquery is + // duplicated for every property on the complex type. + // TODO: Make this work by using a common table expression (CTE) + + var nestedShaperExpression = projection.BindComplexProperty(complexProperty); + var nestedValueExpression = CreateComplexPropertyAccessExpression(valueExpression, complexProperty); + if (!TryProcessComplexType(nestedShaperExpression, nestedValueExpression)) + { + return false; + } } - if (visitor.TranslateExpression(remappedValueSelector, applyDefaultTypeMapping: false) - is not SqlExpression translatedValueSelector) + return true; + } + + Expression CreatePropertyAccessExpression(Expression target, IProperty property) + { + return target is LambdaExpression lambda + ? Expression.Lambda(Core(lambda.Body, property), lambda.Parameters[0]) + : Core(target, property); + + Expression Core(Expression target, IProperty property) { - visitor.AddTranslationErrorDetails(RelationalStrings.InvalidValueInSetProperty(valueSelector.Print())); - return null; + switch (target) + { + case SqlConstantExpression constantExpression: + return Expression.Constant( + constantExpression.Value is null + ? null + : property.GetGetter().GetClrValue(constantExpression.Value), + property.ClrType.MakeNullable()); + + case SqlParameterExpression parameterExpression + when parameterExpression.Name.StartsWith( + QueryCompilationContext.QueryParameterPrefix, StringComparison.Ordinal): + { + var lambda = Expression.Lambda( + Expression.Call( + ParameterValueExtractorMethod.MakeGenericMethod(property.ClrType.MakeNullable()), + QueryCompilationContext.QueryContextParameter, + Expression.Constant(parameterExpression.Name, typeof(string)), + Expression.Constant(null, typeof(List)), + Expression.Constant(property, typeof(IProperty))), + QueryCompilationContext.QueryContextParameter); + + var newParameterName = + $"{ExecuteUpdateRuntimeParameterPrefix}" + + $"{parameterExpression.Name[QueryCompilationContext.QueryParameterPrefix.Length..]}_{property.Name}"; + + return _queryCompilationContext.RegisterRuntimeParameter(newParameterName, lambda); + } + + case ParameterBasedComplexPropertyChainExpression chainExpression: + { + var lambda = Expression.Lambda( + Expression.Call( + ParameterValueExtractorMethod.MakeGenericMethod(property.ClrType.MakeNullable()), + QueryCompilationContext.QueryContextParameter, + Expression.Constant(chainExpression.ParameterExpression.Name, typeof(string)), + Expression.Constant(chainExpression.ComplexPropertyChain, typeof(List)), + Expression.Constant(property, typeof(IProperty))), + QueryCompilationContext.QueryContextParameter); + + var newParameterName = + $"{ExecuteUpdateRuntimeParameterPrefix}" + + $"{chainExpression.ParameterExpression.Name![QueryCompilationContext.QueryParameterPrefix.Length..]}_{property.Name}"; + + return _queryCompilationContext.RegisterRuntimeParameter(newParameterName, lambda); + } + + case MemberInitExpression memberInitExpression + when memberInitExpression.Bindings.SingleOrDefault( + mb => mb.Member.Name == property.Name) is MemberAssignment memberAssignment: + return memberAssignment.Expression; + + default: + return target.CreateEFPropertyExpression(property); + } } + } - // Apply the type mapping of the column (translated from the property selector above) to the value, - // and apply alias uniquification to it. - translatedValueSelector = visitor._sqlExpressionFactory.ApplyTypeMapping(translatedValueSelector, column.TypeMapping); - translatedValueSelector = selectExpression.AssignUniqueAliases(translatedValueSelector); + Expression CreateComplexPropertyAccessExpression(Expression target, IComplexProperty complexProperty) + { + return target is LambdaExpression lambda + ? Expression.Lambda(Core(lambda.Body, complexProperty), lambda.Parameters[0]) + : Core(target, complexProperty); - setters[i] = new ColumnValueSetter(column, translatedValueSelector); + Expression Core(Expression target, IComplexProperty complexProperty) + => target switch + { + SqlConstantExpression constant => _sqlExpressionFactory.Constant( + constant.Value is null ? null : complexProperty.GetGetter().GetClrValue(constant.Value), + complexProperty.ClrType.MakeNullable()), + + SqlParameterExpression parameter + when parameter.Name.StartsWith(QueryCompilationContext.QueryParameterPrefix, StringComparison.Ordinal) + => new ParameterBasedComplexPropertyChainExpression(parameter, complexProperty), + + StructuralTypeShaperExpression + { + StructuralType: IComplexType, + ValueBufferExpression: StructuralTypeProjectionExpression projection + } + => projection.BindComplexProperty(complexProperty), + + _ => throw new UnreachableException() + }; } + } - selectExpression.ReplaceProjection(new List()); - selectExpression.ApplyProjection(); + SqlExpression? TranslateSqlSetterValueSelector( + ShapedQueryExpression source, + Expression valueSelector, + ColumnExpression column, + SelectExpression selectExpression) + { + if (TranslateSetterValueSelector(source, valueSelector, column.Type) is not SqlExpression translatedSelector) + { + AddTranslationErrorDetails(RelationalStrings.InvalidValueInSetProperty(valueSelector.Print())); + return null; + } + + // Apply the type mapping of the column (translated from the property selector above) to the value, + // and apply alias uniquification to it. + translatedSelector = _sqlExpressionFactory.ApplyTypeMapping(translatedSelector, column.TypeMapping); + translatedSelector = selectExpression.AssignUniqueAliases(translatedSelector); + return translatedSelector; + } + + Expression? TranslateSetterValueSelector(ShapedQueryExpression source, Expression valueSelector, Type propertyType) + { + var remappedValueSelector = valueSelector is LambdaExpression lambdaExpression + ? RemapLambdaBody(source, lambdaExpression) + : valueSelector; + + if (remappedValueSelector.Type != propertyType) + { + remappedValueSelector = Expression.Convert(remappedValueSelector, propertyType); + } + + if (_sqlTranslator.TranslateProjection(remappedValueSelector, applyDefaultTypeMapping: false) is not Expression + translatedValueSelector) + { + AddTranslationErrorDetails(RelationalStrings.InvalidValueInSetProperty(valueSelector.Print())); + return null; + } - return new NonQueryExpression(new UpdateExpression(tableExpression, selectExpression, setters)); + return translatedValueSelector; } NonQueryExpression? PushdownWithPkInnerJoinPredicate() @@ -195,7 +396,7 @@ when methodCallExpression.Method.DeclaringType.GetGenericTypeDefinition() == typ // EF.Function, etc. We also unwrap casts to interface/base class (#29618). Note that owned IncludeExpressions have already // been pruned from the source before remapping the lambda (#28727). - var firstPropertySelector = propertyValueLambdaExpressions[0].PropertySelector; + var firstPropertySelector = setters[0].PropertySelector; var shaper = RemapLambdaBody(source, firstPropertySelector).UnwrapTypeConversion(out _) switch { MemberExpression { Expression : not null } memberExpression @@ -240,7 +441,7 @@ MethodCallExpression mce when mce.TryGetIndexerArguments(RelationalDependencies. var inner = source; var outerParameter = Expression.Parameter(entityType.ClrType); var outerKeySelector = Expression.Lambda(outerParameter.CreateKeyValuesExpression(pk.Properties), outerParameter); - var firstPropertyLambdaExpression = propertyValueLambdaExpressions[0].Item1; + var firstPropertyLambdaExpression = setters[0].Item1; var entitySource = GetEntitySource(RelationalDependencies.Model, firstPropertyLambdaExpression.Body); var innerKeySelector = Expression.Lambda( entitySource.CreateKeyValuesExpression(pk.Properties), firstPropertyLambdaExpression.Parameters); @@ -257,9 +458,9 @@ MethodCallExpression mce when mce.TryGetIndexerArguments(RelationalDependencies. var propertyReplacement = AccessField(transparentIdentifierType, transparentIdentifierParameter, "Outer"); var valueReplacement = AccessField(transparentIdentifierType, transparentIdentifierParameter, "Inner"); - for (var i = 0; i < propertyValueLambdaExpressions.Count; i++) + for (var i = 0; i < setters.Count; i++) { - var (propertyExpression, valueExpression) = propertyValueLambdaExpressions[i]; + var (propertyExpression, valueExpression) = setters[i]; propertyExpression = Expression.Lambda( ReplacingExpressionVisitor.Replace( ReplacingExpressionVisitor.Replace( @@ -275,28 +476,21 @@ MethodCallExpression mce when mce.TryGetIndexerArguments(RelationalDependencies. transparentIdentifierParameter) : valueExpression; - propertyValueLambdaExpressions[i] = (propertyExpression, valueExpression); + setters[i] = (propertyExpression, valueExpression); } tableExpression = (TableExpression)outerSelectExpression.Tables[0]; // Re-translate the property selectors to get column expressions pointing to the new outer select expression (the original one // has been pushed down into a subquery). - for (var i = 0; i < propertyValueLambdaExpressions.Count; i++) + if (!TranslateSetters(outer, setters, out var translatedSetters, out _)) { - var (propertySelector, _) = propertyValueLambdaExpressions[i]; - var propertySelectorBody = RemapLambdaBody(outer, propertySelector).UnwrapTypeConversion(out _); - - if (TranslateExpression(propertySelectorBody) is not ColumnExpression column) - { - AddTranslationErrorDetails(RelationalStrings.InvalidPropertyInSetProperty(propertySelector.Print())); - return null; - } - - columns[i] = column; + return null; } - return TranslateValueExpressions(this, outer, outerSelectExpression, tableExpression, propertyValueLambdaExpressions, columns); + outerSelectExpression.ReplaceProjection(new List()); + outerSelectExpression.ApplyProjection(); + return new NonQueryExpression(new UpdateExpression(tableExpression, outerSelectExpression, translatedSetters)); } static Expression GetEntitySource(IModel model, Expression propertyAccessExpression) @@ -382,4 +576,42 @@ protected virtual bool IsValidSelectExpressionForExecuteUpdate( return false; } + + private static T? ParameterValueExtractor( + QueryContext context, + string baseParameterName, + List? complexPropertyChain, + IProperty property) + { + var baseValue = context.ParameterValues[baseParameterName]; + + if (complexPropertyChain is not null) + { + foreach (var complexProperty in complexPropertyChain) + { + if (baseValue is null) + { + break; + } + + baseValue = complexProperty.GetGetter().GetClrValue(baseValue); + } + } + + return baseValue == null ? (T?)(object?)null : (T?)property.GetGetter().GetClrValue(baseValue); + } + + private sealed class ParameterBasedComplexPropertyChainExpression : Expression + { + public ParameterBasedComplexPropertyChainExpression( + SqlParameterExpression parameterExpression, + IComplexProperty firstComplexProperty) + { + ParameterExpression = parameterExpression; + ComplexPropertyChain = new List { firstComplexProperty }; + } + + public SqlParameterExpression ParameterExpression { get; } + public List ComplexPropertyChain { get; } + } } diff --git a/test/EFCore.Relational.Specification.Tests/BulkUpdates/ComplexTypeBulkUpdatesTestBase.cs b/test/EFCore.Relational.Specification.Tests/BulkUpdates/ComplexTypeBulkUpdatesTestBase.cs index 45e2a1e1f6e..0296f6c1168 100644 --- a/test/EFCore.Relational.Specification.Tests/BulkUpdates/ComplexTypeBulkUpdatesTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/BulkUpdates/ComplexTypeBulkUpdatesTestBase.cs @@ -106,6 +106,121 @@ public virtual Task Update_projected_complex_type_via_OrderBy_Skip_throws(bool a s => s.SetProperty(c => c.ZipCode, 12345), rowsAffectedCount: 3)); + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Update_complex_type_to_parameter(bool async) + { + var newAddress = new Address + { + AddressLine1 = "New AddressLine1", + AddressLine2 = "New AddressLine2", + ZipCode = 99999, + Country = new() + { + Code = "FR", + FullName = "France" + }, + Tags = new List { "new_tag1", "new_tag2" } + }; + + return AssertUpdate( + async, + ss => ss.Set(), + c => c, + s => s.SetProperty(x => x.ShippingAddress, newAddress), + rowsAffectedCount: 3); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Update_nested_complex_type_to_parameter(bool async) + { + var newCountry = new Country + { + Code = "FR", + FullName = "France" + }; + + return AssertUpdate( + async, + ss => ss.Set(), + c => c, + s => s.SetProperty(x => x.ShippingAddress.Country, newCountry), + rowsAffectedCount: 3); + } + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Update_complex_type_to_another_database_complex_type(bool async) + => AssertUpdate( + async, + ss => ss.Set(), + c => c, + s => s.SetProperty(x => x.ShippingAddress, x => x.BillingAddress), + rowsAffectedCount: 3); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Update_complex_type_to_inline_without_lambda(bool async) + => AssertUpdate( + async, + ss => ss.Set(), + c => c, + s => s.SetProperty(x => x.ShippingAddress, new Address + { + AddressLine1 = "New AddressLine1", + AddressLine2 = "New AddressLine2", + ZipCode = 99999, + Country = new() + { + Code = "FR", + FullName = "France" + }, + Tags = new List { "new_tag1", "new_tag2" } + }), + rowsAffectedCount: 3); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Update_complex_type_to_inline_with_lambda(bool async) + => AssertUpdate( + async, + ss => ss.Set(), + c => c, + s => s.SetProperty(x => x.ShippingAddress, x => new Address + { + AddressLine1 = "New AddressLine1", + AddressLine2 = "New AddressLine2", + ZipCode = 99999, + Country = new() + { + Code = "FR", + FullName = "France" + }, + Tags = new List { "new_tag1", "new_tag2" } + }), + rowsAffectedCount: 3); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Update_complex_type_to_another_database_complex_type_with_subquery(bool async) + => AssertUpdate( + async, + ss => ss.Set().OrderBy(c => c.Id).Skip(1), + c => c, + s => s.SetProperty(x => x.ShippingAddress, x => x.BillingAddress), + rowsAffectedCount: 2); + + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Update_collection_inside_complex_type(bool async) + => AssertUpdate( + async, + ss => ss.Set(), + c => c, + s => s.SetProperty(x => x.ShippingAddress.Tags, new List { "new_tag1", "new_tag2" }), + rowsAffectedCount: 3); + private void ClearLog() => Fixture.TestSqlLoggerFactory.Clear(); } diff --git a/test/EFCore.Relational.Specification.Tests/TestUtilities/TestSqlLoggerFactory.cs b/test/EFCore.Relational.Specification.Tests/TestUtilities/TestSqlLoggerFactory.cs index bf57b50d51e..12eb14f7557 100644 --- a/test/EFCore.Relational.Specification.Tests/TestUtilities/TestSqlLoggerFactory.cs +++ b/test/EFCore.Relational.Specification.Tests/TestUtilities/TestSqlLoggerFactory.cs @@ -254,7 +254,7 @@ void RewriteSourceWithNewBaseline(string fileName, int lineNumber) indentBuilder.Append(" "); var indent = indentBuilder.ToString(); var newBaseLine = $@"Assert{(forUpdate ? "ExecuteUpdate" : "")}Sql( -{string.Join("," + Environment.NewLine + indent + "//" + Environment.NewLine, SqlStatements.Skip(offset).Take(count).Select(sql => "\"\"\"" + Environment.NewLine + sql + Environment.NewLine + "\"\"\""))})"; +{string.Join("," + Environment.NewLine + indent + "//" + Environment.NewLine, SqlStatements.Skip(offset).Take(count).Select(sql => indent + "\"\"\"" + Environment.NewLine + sql + Environment.NewLine + "\"\"\""))})"; var numNewlinesInRewritten = newBaseLine.Count(c => c is '\n' or '\r'); writer.Write(newBaseLine); diff --git a/test/EFCore.Specification.Tests/Query/ComplexTypeQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/ComplexTypeQueryTestBase.cs index ceb4a5d65af..c91a7ae046b 100644 --- a/test/EFCore.Specification.Tests/Query/ComplexTypeQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/ComplexTypeQueryTestBase.cs @@ -143,8 +143,15 @@ public virtual Task Complex_type_equals_constant(bool async) { AddressLine1 = "804 S. Lakeshore Road", ZipCode = 38654, - Country = new Country { FullName = "United States", Code = "US" } - })); + Country = new Country { FullName = "United States", Code = "US" }, + Tags = new List { "foo", "bar" } + }), + ss => ss.Set().Where( + c => + c.ShippingAddress.AddressLine1 == "804 S. Lakeshore Road" + && c.ShippingAddress.ZipCode == 38654 + && c.ShippingAddress.Country == new Country { FullName = "United States", Code = "US" } + && c.ShippingAddress.Tags.SequenceEqual(new List { "foo", "bar" }))); [ConditionalTheory] [MemberData(nameof(IsAsyncData))] @@ -154,12 +161,19 @@ public virtual Task Complex_type_equals_parameter(bool async) { AddressLine1 = "804 S. Lakeshore Road", ZipCode = 38654, - Country = new Country { FullName = "United States", Code = "US" } + Country = new Country { FullName = "United States", Code = "US" }, + Tags = new List { "foo", "bar" } }; return AssertQuery( async, - ss => ss.Set().Where(c => c.ShippingAddress == address)); + ss => ss.Set().Where(c => c.ShippingAddress == address), + ss => ss.Set().Where( + c => + c.ShippingAddress.AddressLine1 == "804 S. Lakeshore Road" + && c.ShippingAddress.ZipCode == 38654 + && c.ShippingAddress.Country == new Country { FullName = "United States", Code = "US" } + && c.ShippingAddress.Tags.SequenceEqual(new List { "foo", "bar" }))); } [ConditionalTheory] @@ -194,13 +208,21 @@ public virtual Task Contains_over_complex_type(bool async) { AddressLine1 = "804 S. Lakeshore Road", ZipCode = 38654, - Country = new Country { FullName = "United States", Code = "US" } + Country = new Country { FullName = "United States", Code = "US" }, + Tags = new List { "foo", "bar" } }; return AssertQuery( async, ss => ss.Set().Where( - c => ss.Set().Select(c => c.ShippingAddress).Contains(address))); + c => ss.Set().Select(c => c.ShippingAddress).Contains(address)), + ss => ss.Set().Where( + c => ss.Set().Select(c => c.ShippingAddress).Any( + a => + a.AddressLine1 == "804 S. Lakeshore Road" + && a.ZipCode == 38654 + && a.Country == new Country { FullName = "United States", Code = "US" } + && a.Tags.SequenceEqual(new List { "foo", "bar" })))); } [ConditionalTheory] diff --git a/test/EFCore.Specification.Tests/TestModels/ComplexTypeModel/ComplexTypeData.cs b/test/EFCore.Specification.Tests/TestModels/ComplexTypeModel/ComplexTypeData.cs index cbba0e79225..e10e3c5a721 100644 --- a/test/EFCore.Specification.Tests/TestModels/ComplexTypeModel/ComplexTypeData.cs +++ b/test/EFCore.Specification.Tests/TestModels/ComplexTypeModel/ComplexTypeData.cs @@ -52,7 +52,8 @@ private static IReadOnlyList CreateCustomers() { AddressLine1 = "804 S. Lakeshore Road", ZipCode = 38654, - Country = new Country { FullName = "United States", Code = "US" } + Country = new Country { FullName = "United States", Code = "US" }, + Tags = new List { "foo", "bar" } }; var customer1 = new Customer @@ -71,13 +72,15 @@ private static IReadOnlyList CreateCustomers() { AddressLine1 = "72 Hickory Rd.", ZipCode = 07728, - Country = new Country { FullName = "Germany", Code = "DE" } + Country = new Country { FullName = "Germany", Code = "DE" }, + Tags = new List { "baz" } }, BillingAddress = new Address { AddressLine1 = "79 Main St.", ZipCode = 29293, - Country = new Country { FullName = "Germany", Code = "DE" } + Country = new Country { FullName = "Germany", Code = "DE" }, + Tags = new List { "a1", "a2", "a3" } } }; @@ -85,7 +88,8 @@ private static IReadOnlyList CreateCustomers() { AddressLine1 = "79 Main St.", ZipCode = 29293, - Country = new Country { FullName = "Germany", Code = "DE" } + Country = new Country { FullName = "Germany", Code = "DE" }, + Tags = new List { "foo", "moo" } }; var customer3 = new Customer diff --git a/test/EFCore.Specification.Tests/TestModels/ComplexTypeModel/Model.cs b/test/EFCore.Specification.Tests/TestModels/ComplexTypeModel/Model.cs index 689bc1cdafa..a35c5782bd2 100644 --- a/test/EFCore.Specification.Tests/TestModels/ComplexTypeModel/Model.cs +++ b/test/EFCore.Specification.Tests/TestModels/ComplexTypeModel/Model.cs @@ -19,6 +19,7 @@ public record Address public required string AddressLine1 { get; set; } public string? AddressLine2 { get; set; } public int ZipCode { get; set; } + public List Tags { get; set; } = new(); public required Country Country { get; set; } } diff --git a/test/EFCore.SqlServer.FunctionalTests/BulkUpdates/ComplexTypeBulkUpdatesSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/BulkUpdates/ComplexTypeBulkUpdatesSqlServerTest.cs index 1d6aab91a85..d6d4ffd52da 100644 --- a/test/EFCore.SqlServer.FunctionalTests/BulkUpdates/ComplexTypeBulkUpdatesSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/BulkUpdates/ComplexTypeBulkUpdatesSqlServerTest.cs @@ -103,6 +103,134 @@ public override async Task Update_projected_complex_type_via_OrderBy_Skip_throws AssertExecuteUpdateSql(); } + public override async Task Update_complex_type_to_parameter(bool async) + { + await base.Update_complex_type_to_parameter(async); + + AssertExecuteUpdateSql( + """ +@__complex_type_newAddress_0_AddressLine1='New AddressLine1' (Size = 4000) +@__complex_type_newAddress_0_AddressLine2='New AddressLine2' (Size = 4000) +@__complex_type_newAddress_0_Tags='["new_tag1","new_tag2"]' (Size = 4000) +@__complex_type_newAddress_0_ZipCode='99999' (Nullable = true) +@__complex_type_newAddress_0_Code='FR' (Size = 4000) +@__complex_type_newAddress_0_FullName='France' (Size = 4000) + +UPDATE [c] +SET [c].[ShippingAddress_AddressLine1] = @__complex_type_newAddress_0_AddressLine1, + [c].[ShippingAddress_AddressLine2] = @__complex_type_newAddress_0_AddressLine2, + [c].[ShippingAddress_Tags] = @__complex_type_newAddress_0_Tags, + [c].[ShippingAddress_ZipCode] = @__complex_type_newAddress_0_ZipCode, + [c].[ShippingAddress_Country_Code] = @__complex_type_newAddress_0_Code, + [c].[ShippingAddress_Country_FullName] = @__complex_type_newAddress_0_FullName +FROM [Customer] AS [c] +"""); + } + + public override async Task Update_nested_complex_type_to_parameter(bool async) + { + await base.Update_nested_complex_type_to_parameter(async); + + AssertExecuteUpdateSql( + """ +@__complex_type_newCountry_0_Code='FR' (Size = 4000) +@__complex_type_newCountry_0_FullName='France' (Size = 4000) + +UPDATE [c] +SET [c].[ShippingAddress_Country_Code] = @__complex_type_newCountry_0_Code, + [c].[ShippingAddress_Country_FullName] = @__complex_type_newCountry_0_FullName +FROM [Customer] AS [c] +"""); + } + + public override async Task Update_complex_type_to_another_database_complex_type(bool async) + { + await base.Update_complex_type_to_another_database_complex_type(async); + + AssertExecuteUpdateSql( + """ +UPDATE [c] +SET [c].[ShippingAddress_AddressLine1] = [c].[BillingAddress_AddressLine1], + [c].[ShippingAddress_AddressLine2] = [c].[BillingAddress_AddressLine2], + [c].[ShippingAddress_Tags] = [c].[BillingAddress_Tags], + [c].[ShippingAddress_ZipCode] = [c].[BillingAddress_ZipCode], + [c].[ShippingAddress_Country_Code] = [c].[ShippingAddress_Country_Code], + [c].[ShippingAddress_Country_FullName] = [c].[ShippingAddress_Country_FullName] +FROM [Customer] AS [c] +"""); + } + + public override async Task Update_complex_type_to_inline_without_lambda(bool async) + { + await base.Update_complex_type_to_inline_without_lambda(async); + + AssertExecuteUpdateSql( + """ +UPDATE [c] +SET [c].[ShippingAddress_AddressLine1] = N'New AddressLine1', + [c].[ShippingAddress_AddressLine2] = N'New AddressLine2', + [c].[ShippingAddress_Tags] = N'["new_tag1","new_tag2"]', + [c].[ShippingAddress_ZipCode] = 99999, + [c].[ShippingAddress_Country_Code] = N'FR', + [c].[ShippingAddress_Country_FullName] = N'France' +FROM [Customer] AS [c] +"""); + } + + public override async Task Update_complex_type_to_inline_with_lambda(bool async) + { + await base.Update_complex_type_to_inline_with_lambda(async); + + AssertExecuteUpdateSql( + """ +UPDATE [c] +SET [c].[ShippingAddress_AddressLine1] = N'New AddressLine1', + [c].[ShippingAddress_AddressLine2] = N'New AddressLine2', + [c].[ShippingAddress_Tags] = N'["new_tag1","new_tag2"]', + [c].[ShippingAddress_ZipCode] = 99999, + [c].[ShippingAddress_Country_Code] = N'FR', + [c].[ShippingAddress_Country_FullName] = N'France' +FROM [Customer] AS [c] +"""); + } + + public override async Task Update_complex_type_to_another_database_complex_type_with_subquery(bool async) + { + await base.Update_complex_type_to_another_database_complex_type_with_subquery(async); + + AssertExecuteUpdateSql( + """ +@__p_0='1' + +UPDATE [c] +SET [c].[ShippingAddress_AddressLine1] = [t].[BillingAddress_AddressLine1], + [c].[ShippingAddress_AddressLine2] = [t].[BillingAddress_AddressLine2], + [c].[ShippingAddress_Tags] = [t].[BillingAddress_Tags], + [c].[ShippingAddress_ZipCode] = [t].[BillingAddress_ZipCode], + [c].[ShippingAddress_Country_Code] = [t].[ShippingAddress_Country_Code], + [c].[ShippingAddress_Country_FullName] = [t].[ShippingAddress_Country_FullName] +FROM [Customer] AS [c] +INNER JOIN ( + SELECT [c0].[Id], [c0].[Name], [c0].[BillingAddress_AddressLine1], [c0].[BillingAddress_AddressLine2], [c0].[BillingAddress_Tags], [c0].[BillingAddress_ZipCode], [c0].[BillingAddress_Country_Code], [c0].[BillingAddress_Country_FullName], [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_Tags], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName] + FROM [Customer] AS [c0] + ORDER BY [c0].[Id] + OFFSET @__p_0 ROWS +) AS [t] ON [c].[Id] = [t].[Id] +"""); + } + + public override async Task Update_collection_inside_complex_type(bool async) + { + await base.Update_collection_inside_complex_type(async); + + AssertExecuteUpdateSql( + """ +UPDATE [c] +SET [c].[ShippingAddress_Tags] = N'["new_tag1","new_tag2"]' +FROM [Customer] AS [c] +"""); + } + [ConditionalFact] public virtual void Check_all_tests_overridden() => TestHelpers.AssertAllMethodsOverridden(GetType()); diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexTypeQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexTypeQuerySqlServerTest.cs index 52ed43e3ea5..c106961995b 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/ComplexTypeQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/ComplexTypeQuerySqlServerTest.cs @@ -19,7 +19,7 @@ public override async Task Filter_on_property_inside_complex_type(bool async) AssertSql( """ -SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] +SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] FROM [Customer] AS [c] WHERE [c].[ShippingAddress_ZipCode] = 7728 """); @@ -31,7 +31,7 @@ public override async Task Filter_on_property_inside_nested_complex_type(bool as AssertSql( """ -SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] +SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] FROM [Customer] AS [c] WHERE [c].[ShippingAddress_Country_Code] = N'DE' """); @@ -45,9 +45,9 @@ public override async Task Filter_on_property_inside_complex_type_after_subquery """ @__p_0='1' -SELECT DISTINCT [t].[Id], [t].[Name], [t].[BillingAddress_AddressLine1], [t].[BillingAddress_AddressLine2], [t].[BillingAddress_ZipCode], [t].[BillingAddress_Country_Code], [t].[BillingAddress_Country_FullName], [t].[ShippingAddress_AddressLine1], [t].[ShippingAddress_AddressLine2], [t].[ShippingAddress_ZipCode], [t].[ShippingAddress_Country_Code], [t].[ShippingAddress_Country_FullName] +SELECT DISTINCT [t].[Id], [t].[Name], [t].[BillingAddress_AddressLine1], [t].[BillingAddress_AddressLine2], [t].[BillingAddress_Tags], [t].[BillingAddress_ZipCode], [t].[BillingAddress_Country_Code], [t].[BillingAddress_Country_FullName], [t].[ShippingAddress_AddressLine1], [t].[ShippingAddress_AddressLine2], [t].[ShippingAddress_Tags], [t].[ShippingAddress_ZipCode], [t].[ShippingAddress_Country_Code], [t].[ShippingAddress_Country_FullName] FROM ( - SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] + SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] FROM [Customer] AS [c] ORDER BY [c].[Id] OFFSET @__p_0 ROWS @@ -64,9 +64,9 @@ public override async Task Filter_on_property_inside_nested_complex_type_after_s """ @__p_0='1' -SELECT DISTINCT [t].[Id], [t].[Name], [t].[BillingAddress_AddressLine1], [t].[BillingAddress_AddressLine2], [t].[BillingAddress_ZipCode], [t].[BillingAddress_Country_Code], [t].[BillingAddress_Country_FullName], [t].[ShippingAddress_AddressLine1], [t].[ShippingAddress_AddressLine2], [t].[ShippingAddress_ZipCode], [t].[ShippingAddress_Country_Code], [t].[ShippingAddress_Country_FullName] +SELECT DISTINCT [t].[Id], [t].[Name], [t].[BillingAddress_AddressLine1], [t].[BillingAddress_AddressLine2], [t].[BillingAddress_Tags], [t].[BillingAddress_ZipCode], [t].[BillingAddress_Country_Code], [t].[BillingAddress_Country_FullName], [t].[ShippingAddress_AddressLine1], [t].[ShippingAddress_AddressLine2], [t].[ShippingAddress_Tags], [t].[ShippingAddress_ZipCode], [t].[ShippingAddress_Country_Code], [t].[ShippingAddress_Country_FullName] FROM ( - SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] + SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] FROM [Customer] AS [c] ORDER BY [c].[Id] OFFSET @__p_0 ROWS @@ -81,7 +81,7 @@ public override async Task Filter_on_required_property_inside_required_complex_t AssertSql( """ -SELECT [c].[Id], [c].[OptionalCustomerId], [c].[RequiredCustomerId], [c0].[Id], [c0].[Name], [c0].[BillingAddress_AddressLine1], [c0].[BillingAddress_AddressLine2], [c0].[BillingAddress_ZipCode], [c0].[BillingAddress_Country_Code], [c0].[BillingAddress_Country_FullName], [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName], [c1].[Id], [c1].[Name], [c1].[BillingAddress_AddressLine1], [c1].[BillingAddress_AddressLine2], [c1].[BillingAddress_ZipCode], [c1].[BillingAddress_Country_Code], [c1].[BillingAddress_Country_FullName], [c1].[ShippingAddress_AddressLine1], [c1].[ShippingAddress_AddressLine2], [c1].[ShippingAddress_ZipCode], [c1].[ShippingAddress_Country_Code], [c1].[ShippingAddress_Country_FullName] +SELECT [c].[Id], [c].[OptionalCustomerId], [c].[RequiredCustomerId], [c0].[Id], [c0].[Name], [c0].[BillingAddress_AddressLine1], [c0].[BillingAddress_AddressLine2], [c0].[BillingAddress_Tags], [c0].[BillingAddress_ZipCode], [c0].[BillingAddress_Country_Code], [c0].[BillingAddress_Country_FullName], [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_Tags], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName], [c1].[Id], [c1].[Name], [c1].[BillingAddress_AddressLine1], [c1].[BillingAddress_AddressLine2], [c1].[BillingAddress_Tags], [c1].[BillingAddress_ZipCode], [c1].[BillingAddress_Country_Code], [c1].[BillingAddress_Country_FullName], [c1].[ShippingAddress_AddressLine1], [c1].[ShippingAddress_AddressLine2], [c1].[ShippingAddress_Tags], [c1].[ShippingAddress_ZipCode], [c1].[ShippingAddress_Country_Code], [c1].[ShippingAddress_Country_FullName] FROM [CustomerGroup] AS [c] LEFT JOIN [Customer] AS [c0] ON [c].[OptionalCustomerId] = [c0].[Id] INNER JOIN [Customer] AS [c1] ON [c].[RequiredCustomerId] = [c1].[Id] @@ -95,7 +95,7 @@ public override async Task Filter_on_required_property_inside_required_complex_t AssertSql( """ -SELECT [c].[Id], [c].[OptionalCustomerId], [c].[RequiredCustomerId], [c1].[Id], [c1].[Name], [c1].[BillingAddress_AddressLine1], [c1].[BillingAddress_AddressLine2], [c1].[BillingAddress_ZipCode], [c1].[BillingAddress_Country_Code], [c1].[BillingAddress_Country_FullName], [c1].[ShippingAddress_AddressLine1], [c1].[ShippingAddress_AddressLine2], [c1].[ShippingAddress_ZipCode], [c1].[ShippingAddress_Country_Code], [c1].[ShippingAddress_Country_FullName], [c0].[Id], [c0].[Name], [c0].[BillingAddress_AddressLine1], [c0].[BillingAddress_AddressLine2], [c0].[BillingAddress_ZipCode], [c0].[BillingAddress_Country_Code], [c0].[BillingAddress_Country_FullName], [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName] +SELECT [c].[Id], [c].[OptionalCustomerId], [c].[RequiredCustomerId], [c1].[Id], [c1].[Name], [c1].[BillingAddress_AddressLine1], [c1].[BillingAddress_AddressLine2], [c1].[BillingAddress_Tags], [c1].[BillingAddress_ZipCode], [c1].[BillingAddress_Country_Code], [c1].[BillingAddress_Country_FullName], [c1].[ShippingAddress_AddressLine1], [c1].[ShippingAddress_AddressLine2], [c1].[ShippingAddress_Tags], [c1].[ShippingAddress_ZipCode], [c1].[ShippingAddress_Country_Code], [c1].[ShippingAddress_Country_FullName], [c0].[Id], [c0].[Name], [c0].[BillingAddress_AddressLine1], [c0].[BillingAddress_AddressLine2], [c0].[BillingAddress_Tags], [c0].[BillingAddress_ZipCode], [c0].[BillingAddress_Country_Code], [c0].[BillingAddress_Country_FullName], [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_Tags], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName] FROM [CustomerGroup] AS [c] INNER JOIN [Customer] AS [c0] ON [c].[RequiredCustomerId] = [c0].[Id] LEFT JOIN [Customer] AS [c1] ON [c].[OptionalCustomerId] = [c1].[Id] @@ -119,7 +119,7 @@ public override async Task Project_complex_type_via_required_navigation(bool asy AssertSql( """ -SELECT [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName] +SELECT [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_Tags], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName] FROM [CustomerGroup] AS [c] INNER JOIN [Customer] AS [c0] ON [c].[RequiredCustomerId] = [c0].[Id] """); @@ -133,9 +133,9 @@ public override async Task Load_complex_type_after_subquery_on_entity_type(bool """ @__p_0='1' -SELECT DISTINCT [t].[Id], [t].[Name], [t].[BillingAddress_AddressLine1], [t].[BillingAddress_AddressLine2], [t].[BillingAddress_ZipCode], [t].[BillingAddress_Country_Code], [t].[BillingAddress_Country_FullName], [t].[ShippingAddress_AddressLine1], [t].[ShippingAddress_AddressLine2], [t].[ShippingAddress_ZipCode], [t].[ShippingAddress_Country_Code], [t].[ShippingAddress_Country_FullName] +SELECT DISTINCT [t].[Id], [t].[Name], [t].[BillingAddress_AddressLine1], [t].[BillingAddress_AddressLine2], [t].[BillingAddress_Tags], [t].[BillingAddress_ZipCode], [t].[BillingAddress_Country_Code], [t].[BillingAddress_Country_FullName], [t].[ShippingAddress_AddressLine1], [t].[ShippingAddress_AddressLine2], [t].[ShippingAddress_Tags], [t].[ShippingAddress_ZipCode], [t].[ShippingAddress_Country_Code], [t].[ShippingAddress_Country_FullName] FROM ( - SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] + SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] FROM [Customer] AS [c] ORDER BY [c].[Id] OFFSET @__p_0 ROWS @@ -149,7 +149,7 @@ public override async Task Select_complex_type(bool async) AssertSql( """ -SELECT [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] +SELECT [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] FROM [Customer] AS [c] """); } @@ -182,7 +182,7 @@ public override async Task Select_complex_type_Where(bool async) AssertSql( """ -SELECT [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] +SELECT [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] FROM [Customer] AS [c] WHERE [c].[ShippingAddress_ZipCode] = 7728 """); @@ -194,7 +194,7 @@ public override async Task Select_complex_type_Distinct(bool async) AssertSql( """ -SELECT DISTINCT [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] +SELECT DISTINCT [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] FROM [Customer] AS [c] """); } @@ -205,9 +205,9 @@ public override async Task Complex_type_equals_complex_type(bool async) AssertSql( """ -SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] +SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] FROM [Customer] AS [c] -WHERE [c].[ShippingAddress_AddressLine1] = [c].[BillingAddress_AddressLine1] AND ([c].[ShippingAddress_AddressLine2] = [c].[BillingAddress_AddressLine2] OR ([c].[ShippingAddress_AddressLine2] IS NULL AND [c].[BillingAddress_AddressLine2] IS NULL)) AND [c].[ShippingAddress_ZipCode] = [c].[BillingAddress_ZipCode] +WHERE [c].[ShippingAddress_AddressLine1] = [c].[BillingAddress_AddressLine1] AND ([c].[ShippingAddress_AddressLine2] = [c].[BillingAddress_AddressLine2] OR ([c].[ShippingAddress_AddressLine2] IS NULL AND [c].[BillingAddress_AddressLine2] IS NULL)) AND [c].[ShippingAddress_Tags] = [c].[BillingAddress_Tags] AND [c].[ShippingAddress_ZipCode] = [c].[BillingAddress_ZipCode] """); } @@ -217,9 +217,9 @@ public override async Task Complex_type_equals_constant(bool async) AssertSql( """ -SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] +SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] FROM [Customer] AS [c] -WHERE [c].[ShippingAddress_AddressLine1] = N'804 S. Lakeshore Road' AND [c].[ShippingAddress_AddressLine2] IS NULL AND [c].[ShippingAddress_ZipCode] = 38654 AND [c].[ShippingAddress_Country_Code] = N'US' AND [c].[ShippingAddress_Country_FullName] = N'United States' +WHERE [c].[ShippingAddress_AddressLine1] = N'804 S. Lakeshore Road' AND [c].[ShippingAddress_AddressLine2] IS NULL AND [c].[ShippingAddress_Tags] = N'["foo","bar"]' AND [c].[ShippingAddress_ZipCode] = 38654 AND [c].[ShippingAddress_Country_Code] = N'US' AND [c].[ShippingAddress_Country_FullName] = N'United States' """); } @@ -230,13 +230,14 @@ public override async Task Complex_type_equals_parameter(bool async) AssertSql( """ @__entity_equality_address_0_AddressLine1='804 S. Lakeshore Road' (Size = 4000) +@__entity_equality_address_0_Tags='["foo","bar"]' (Size = 4000) @__entity_equality_address_0_ZipCode='38654' (Nullable = true) @__entity_equality_address_0_Code='US' (Size = 4000) @__entity_equality_address_0_FullName='United States' (Size = 4000) -SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] +SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] FROM [Customer] AS [c] -WHERE [c].[ShippingAddress_AddressLine1] = @__entity_equality_address_0_AddressLine1 AND [c].[ShippingAddress_AddressLine2] IS NULL AND [c].[ShippingAddress_ZipCode] = @__entity_equality_address_0_ZipCode AND [c].[ShippingAddress_Country_Code] = @__entity_equality_address_0_Code AND [c].[ShippingAddress_Country_FullName] = @__entity_equality_address_0_FullName +WHERE [c].[ShippingAddress_AddressLine1] = @__entity_equality_address_0_AddressLine1 AND [c].[ShippingAddress_AddressLine2] IS NULL AND [c].[ShippingAddress_Tags] = @__entity_equality_address_0_Tags AND [c].[ShippingAddress_ZipCode] = @__entity_equality_address_0_ZipCode AND [c].[ShippingAddress_Country_Code] = @__entity_equality_address_0_Code AND [c].[ShippingAddress_Country_FullName] = @__entity_equality_address_0_FullName """); } @@ -261,16 +262,17 @@ public override async Task Contains_over_complex_type(bool async) AssertSql( """ @__entity_equality_address_0_AddressLine1='804 S. Lakeshore Road' (Size = 4000) +@__entity_equality_address_0_Tags='["foo","bar"]' (Size = 4000) @__entity_equality_address_0_ZipCode='38654' (Nullable = true) @__entity_equality_address_0_Code='US' (Size = 4000) @__entity_equality_address_0_FullName='United States' (Size = 4000) -SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] +SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] FROM [Customer] AS [c] WHERE EXISTS ( SELECT 1 FROM [Customer] AS [c0] - WHERE [c0].[ShippingAddress_AddressLine1] = @__entity_equality_address_0_AddressLine1 AND [c0].[ShippingAddress_AddressLine2] IS NULL AND [c0].[ShippingAddress_ZipCode] = @__entity_equality_address_0_ZipCode AND [c0].[ShippingAddress_Country_Code] = @__entity_equality_address_0_Code AND [c0].[ShippingAddress_Country_FullName] = @__entity_equality_address_0_FullName) + WHERE [c0].[ShippingAddress_AddressLine1] = @__entity_equality_address_0_AddressLine1 AND [c0].[ShippingAddress_AddressLine2] IS NULL AND [c0].[ShippingAddress_Tags] = @__entity_equality_address_0_Tags AND [c0].[ShippingAddress_ZipCode] = @__entity_equality_address_0_ZipCode AND [c0].[ShippingAddress_Country_Code] = @__entity_equality_address_0_Code AND [c0].[ShippingAddress_Country_FullName] = @__entity_equality_address_0_FullName) """); } @@ -280,11 +282,11 @@ public override async Task Concat_complex_type(bool async) AssertSql( """ -SELECT [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] +SELECT [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] FROM [Customer] AS [c] WHERE [c].[Id] = 1 UNION ALL -SELECT [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName] +SELECT [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_Tags], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName] FROM [Customer] AS [c0] WHERE [c0].[Id] = 2 """); @@ -296,11 +298,11 @@ public override async Task Concat_entity_type_containing_complex_property(bool a AssertSql( """ -SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] +SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] FROM [Customer] AS [c] WHERE [c].[Id] = 1 UNION ALL -SELECT [c0].[Id], [c0].[Name], [c0].[BillingAddress_AddressLine1], [c0].[BillingAddress_AddressLine2], [c0].[BillingAddress_ZipCode], [c0].[BillingAddress_Country_Code], [c0].[BillingAddress_Country_FullName], [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName] +SELECT [c0].[Id], [c0].[Name], [c0].[BillingAddress_AddressLine1], [c0].[BillingAddress_AddressLine2], [c0].[BillingAddress_Tags], [c0].[BillingAddress_ZipCode], [c0].[BillingAddress_Country_Code], [c0].[BillingAddress_Country_FullName], [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_Tags], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName] FROM [Customer] AS [c0] WHERE [c0].[Id] = 2 """); @@ -312,11 +314,11 @@ public override async Task Union_entity_type_containing_complex_property(bool as AssertSql( """ -SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] +SELECT [c].[Id], [c].[Name], [c].[BillingAddress_AddressLine1], [c].[BillingAddress_AddressLine2], [c].[BillingAddress_Tags], [c].[BillingAddress_ZipCode], [c].[BillingAddress_Country_Code], [c].[BillingAddress_Country_FullName], [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] FROM [Customer] AS [c] WHERE [c].[Id] = 1 UNION -SELECT [c0].[Id], [c0].[Name], [c0].[BillingAddress_AddressLine1], [c0].[BillingAddress_AddressLine2], [c0].[BillingAddress_ZipCode], [c0].[BillingAddress_Country_Code], [c0].[BillingAddress_Country_FullName], [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName] +SELECT [c0].[Id], [c0].[Name], [c0].[BillingAddress_AddressLine1], [c0].[BillingAddress_AddressLine2], [c0].[BillingAddress_Tags], [c0].[BillingAddress_ZipCode], [c0].[BillingAddress_Country_Code], [c0].[BillingAddress_Country_FullName], [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_Tags], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName] FROM [Customer] AS [c0] WHERE [c0].[Id] = 2 """); @@ -328,11 +330,11 @@ public override async Task Union_complex_type(bool async) AssertSql( """ -SELECT [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] +SELECT [c].[ShippingAddress_AddressLine1], [c].[ShippingAddress_AddressLine2], [c].[ShippingAddress_Tags], [c].[ShippingAddress_ZipCode], [c].[ShippingAddress_Country_Code], [c].[ShippingAddress_Country_FullName] FROM [Customer] AS [c] WHERE [c].[Id] = 1 UNION -SELECT [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName] +SELECT [c0].[ShippingAddress_AddressLine1], [c0].[ShippingAddress_AddressLine2], [c0].[ShippingAddress_Tags], [c0].[ShippingAddress_ZipCode], [c0].[ShippingAddress_Country_Code], [c0].[ShippingAddress_Country_FullName] FROM [Customer] AS [c0] WHERE [c0].[Id] = 2 """); diff --git a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexTypeQuerySqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexTypeQuerySqliteTest.cs index d3423b9e7d0..3dd4ff5cec3 100644 --- a/test/EFCore.Sqlite.FunctionalTests/Query/ComplexTypeQuerySqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/Query/ComplexTypeQuerySqliteTest.cs @@ -19,7 +19,7 @@ public override async Task Filter_on_property_inside_complex_type(bool async) AssertSql( """ -SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" +SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" FROM "Customer" AS "c" WHERE "c"."ShippingAddress_ZipCode" = 7728 """); @@ -31,7 +31,7 @@ public override async Task Filter_on_property_inside_nested_complex_type(bool as AssertSql( """ -SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" +SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" FROM "Customer" AS "c" WHERE "c"."ShippingAddress_Country_Code" = 'DE' """); @@ -45,9 +45,9 @@ public override async Task Filter_on_property_inside_complex_type_after_subquery """ @__p_0='1' -SELECT DISTINCT "t"."Id", "t"."Name", "t"."BillingAddress_AddressLine1", "t"."BillingAddress_AddressLine2", "t"."BillingAddress_ZipCode", "t"."BillingAddress_Country_Code", "t"."BillingAddress_Country_FullName", "t"."ShippingAddress_AddressLine1", "t"."ShippingAddress_AddressLine2", "t"."ShippingAddress_ZipCode", "t"."ShippingAddress_Country_Code", "t"."ShippingAddress_Country_FullName" +SELECT DISTINCT "t"."Id", "t"."Name", "t"."BillingAddress_AddressLine1", "t"."BillingAddress_AddressLine2", "t"."BillingAddress_Tags", "t"."BillingAddress_ZipCode", "t"."BillingAddress_Country_Code", "t"."BillingAddress_Country_FullName", "t"."ShippingAddress_AddressLine1", "t"."ShippingAddress_AddressLine2", "t"."ShippingAddress_Tags", "t"."ShippingAddress_ZipCode", "t"."ShippingAddress_Country_Code", "t"."ShippingAddress_Country_FullName" FROM ( - SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" + SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" FROM "Customer" AS "c" ORDER BY "c"."Id" LIMIT -1 OFFSET @__p_0 @@ -64,9 +64,9 @@ public override async Task Filter_on_property_inside_nested_complex_type_after_s """ @__p_0='1' -SELECT DISTINCT "t"."Id", "t"."Name", "t"."BillingAddress_AddressLine1", "t"."BillingAddress_AddressLine2", "t"."BillingAddress_ZipCode", "t"."BillingAddress_Country_Code", "t"."BillingAddress_Country_FullName", "t"."ShippingAddress_AddressLine1", "t"."ShippingAddress_AddressLine2", "t"."ShippingAddress_ZipCode", "t"."ShippingAddress_Country_Code", "t"."ShippingAddress_Country_FullName" +SELECT DISTINCT "t"."Id", "t"."Name", "t"."BillingAddress_AddressLine1", "t"."BillingAddress_AddressLine2", "t"."BillingAddress_Tags", "t"."BillingAddress_ZipCode", "t"."BillingAddress_Country_Code", "t"."BillingAddress_Country_FullName", "t"."ShippingAddress_AddressLine1", "t"."ShippingAddress_AddressLine2", "t"."ShippingAddress_Tags", "t"."ShippingAddress_ZipCode", "t"."ShippingAddress_Country_Code", "t"."ShippingAddress_Country_FullName" FROM ( - SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" + SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" FROM "Customer" AS "c" ORDER BY "c"."Id" LIMIT -1 OFFSET @__p_0 @@ -81,7 +81,7 @@ public override async Task Filter_on_required_property_inside_required_complex_t AssertSql( """ -SELECT "c"."Id", "c"."OptionalCustomerId", "c"."RequiredCustomerId", "c0"."Id", "c0"."Name", "c0"."BillingAddress_AddressLine1", "c0"."BillingAddress_AddressLine2", "c0"."BillingAddress_ZipCode", "c0"."BillingAddress_Country_Code", "c0"."BillingAddress_Country_FullName", "c0"."ShippingAddress_AddressLine1", "c0"."ShippingAddress_AddressLine2", "c0"."ShippingAddress_ZipCode", "c0"."ShippingAddress_Country_Code", "c0"."ShippingAddress_Country_FullName", "c1"."Id", "c1"."Name", "c1"."BillingAddress_AddressLine1", "c1"."BillingAddress_AddressLine2", "c1"."BillingAddress_ZipCode", "c1"."BillingAddress_Country_Code", "c1"."BillingAddress_Country_FullName", "c1"."ShippingAddress_AddressLine1", "c1"."ShippingAddress_AddressLine2", "c1"."ShippingAddress_ZipCode", "c1"."ShippingAddress_Country_Code", "c1"."ShippingAddress_Country_FullName" +SELECT "c"."Id", "c"."OptionalCustomerId", "c"."RequiredCustomerId", "c0"."Id", "c0"."Name", "c0"."BillingAddress_AddressLine1", "c0"."BillingAddress_AddressLine2", "c0"."BillingAddress_Tags", "c0"."BillingAddress_ZipCode", "c0"."BillingAddress_Country_Code", "c0"."BillingAddress_Country_FullName", "c0"."ShippingAddress_AddressLine1", "c0"."ShippingAddress_AddressLine2", "c0"."ShippingAddress_Tags", "c0"."ShippingAddress_ZipCode", "c0"."ShippingAddress_Country_Code", "c0"."ShippingAddress_Country_FullName", "c1"."Id", "c1"."Name", "c1"."BillingAddress_AddressLine1", "c1"."BillingAddress_AddressLine2", "c1"."BillingAddress_Tags", "c1"."BillingAddress_ZipCode", "c1"."BillingAddress_Country_Code", "c1"."BillingAddress_Country_FullName", "c1"."ShippingAddress_AddressLine1", "c1"."ShippingAddress_AddressLine2", "c1"."ShippingAddress_Tags", "c1"."ShippingAddress_ZipCode", "c1"."ShippingAddress_Country_Code", "c1"."ShippingAddress_Country_FullName" FROM "CustomerGroup" AS "c" LEFT JOIN "Customer" AS "c0" ON "c"."OptionalCustomerId" = "c0"."Id" INNER JOIN "Customer" AS "c1" ON "c"."RequiredCustomerId" = "c1"."Id" @@ -95,7 +95,7 @@ public override async Task Filter_on_required_property_inside_required_complex_t AssertSql( """ -SELECT "c"."Id", "c"."OptionalCustomerId", "c"."RequiredCustomerId", "c1"."Id", "c1"."Name", "c1"."BillingAddress_AddressLine1", "c1"."BillingAddress_AddressLine2", "c1"."BillingAddress_ZipCode", "c1"."BillingAddress_Country_Code", "c1"."BillingAddress_Country_FullName", "c1"."ShippingAddress_AddressLine1", "c1"."ShippingAddress_AddressLine2", "c1"."ShippingAddress_ZipCode", "c1"."ShippingAddress_Country_Code", "c1"."ShippingAddress_Country_FullName", "c0"."Id", "c0"."Name", "c0"."BillingAddress_AddressLine1", "c0"."BillingAddress_AddressLine2", "c0"."BillingAddress_ZipCode", "c0"."BillingAddress_Country_Code", "c0"."BillingAddress_Country_FullName", "c0"."ShippingAddress_AddressLine1", "c0"."ShippingAddress_AddressLine2", "c0"."ShippingAddress_ZipCode", "c0"."ShippingAddress_Country_Code", "c0"."ShippingAddress_Country_FullName" +SELECT "c"."Id", "c"."OptionalCustomerId", "c"."RequiredCustomerId", "c1"."Id", "c1"."Name", "c1"."BillingAddress_AddressLine1", "c1"."BillingAddress_AddressLine2", "c1"."BillingAddress_Tags", "c1"."BillingAddress_ZipCode", "c1"."BillingAddress_Country_Code", "c1"."BillingAddress_Country_FullName", "c1"."ShippingAddress_AddressLine1", "c1"."ShippingAddress_AddressLine2", "c1"."ShippingAddress_Tags", "c1"."ShippingAddress_ZipCode", "c1"."ShippingAddress_Country_Code", "c1"."ShippingAddress_Country_FullName", "c0"."Id", "c0"."Name", "c0"."BillingAddress_AddressLine1", "c0"."BillingAddress_AddressLine2", "c0"."BillingAddress_Tags", "c0"."BillingAddress_ZipCode", "c0"."BillingAddress_Country_Code", "c0"."BillingAddress_Country_FullName", "c0"."ShippingAddress_AddressLine1", "c0"."ShippingAddress_AddressLine2", "c0"."ShippingAddress_Tags", "c0"."ShippingAddress_ZipCode", "c0"."ShippingAddress_Country_Code", "c0"."ShippingAddress_Country_FullName" FROM "CustomerGroup" AS "c" INNER JOIN "Customer" AS "c0" ON "c"."RequiredCustomerId" = "c0"."Id" LEFT JOIN "Customer" AS "c1" ON "c"."OptionalCustomerId" = "c1"."Id" @@ -119,7 +119,7 @@ public override async Task Project_complex_type_via_required_navigation(bool asy AssertSql( """ -SELECT "c0"."ShippingAddress_AddressLine1", "c0"."ShippingAddress_AddressLine2", "c0"."ShippingAddress_ZipCode", "c0"."ShippingAddress_Country_Code", "c0"."ShippingAddress_Country_FullName" +SELECT "c0"."ShippingAddress_AddressLine1", "c0"."ShippingAddress_AddressLine2", "c0"."ShippingAddress_Tags", "c0"."ShippingAddress_ZipCode", "c0"."ShippingAddress_Country_Code", "c0"."ShippingAddress_Country_FullName" FROM "CustomerGroup" AS "c" INNER JOIN "Customer" AS "c0" ON "c"."RequiredCustomerId" = "c0"."Id" """); @@ -133,9 +133,9 @@ public override async Task Load_complex_type_after_subquery_on_entity_type(bool """ @__p_0='1' -SELECT DISTINCT "t"."Id", "t"."Name", "t"."BillingAddress_AddressLine1", "t"."BillingAddress_AddressLine2", "t"."BillingAddress_ZipCode", "t"."BillingAddress_Country_Code", "t"."BillingAddress_Country_FullName", "t"."ShippingAddress_AddressLine1", "t"."ShippingAddress_AddressLine2", "t"."ShippingAddress_ZipCode", "t"."ShippingAddress_Country_Code", "t"."ShippingAddress_Country_FullName" +SELECT DISTINCT "t"."Id", "t"."Name", "t"."BillingAddress_AddressLine1", "t"."BillingAddress_AddressLine2", "t"."BillingAddress_Tags", "t"."BillingAddress_ZipCode", "t"."BillingAddress_Country_Code", "t"."BillingAddress_Country_FullName", "t"."ShippingAddress_AddressLine1", "t"."ShippingAddress_AddressLine2", "t"."ShippingAddress_Tags", "t"."ShippingAddress_ZipCode", "t"."ShippingAddress_Country_Code", "t"."ShippingAddress_Country_FullName" FROM ( - SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" + SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" FROM "Customer" AS "c" ORDER BY "c"."Id" LIMIT -1 OFFSET @__p_0 @@ -149,7 +149,7 @@ public override async Task Select_complex_type(bool async) AssertSql( """ -SELECT "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" +SELECT "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" FROM "Customer" AS "c" """); } @@ -182,7 +182,7 @@ public override async Task Select_complex_type_Where(bool async) AssertSql( """ -SELECT "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" +SELECT "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" FROM "Customer" AS "c" WHERE "c"."ShippingAddress_ZipCode" = 7728 """); @@ -194,7 +194,7 @@ public override async Task Select_complex_type_Distinct(bool async) AssertSql( """ -SELECT DISTINCT "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" +SELECT DISTINCT "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" FROM "Customer" AS "c" """); } @@ -205,9 +205,9 @@ public override async Task Complex_type_equals_complex_type(bool async) AssertSql( """ -SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" +SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" FROM "Customer" AS "c" -WHERE "c"."ShippingAddress_AddressLine1" = "c"."BillingAddress_AddressLine1" AND ("c"."ShippingAddress_AddressLine2" = "c"."BillingAddress_AddressLine2" OR ("c"."ShippingAddress_AddressLine2" IS NULL AND "c"."BillingAddress_AddressLine2" IS NULL)) AND "c"."ShippingAddress_ZipCode" = "c"."BillingAddress_ZipCode" +WHERE "c"."ShippingAddress_AddressLine1" = "c"."BillingAddress_AddressLine1" AND ("c"."ShippingAddress_AddressLine2" = "c"."BillingAddress_AddressLine2" OR ("c"."ShippingAddress_AddressLine2" IS NULL AND "c"."BillingAddress_AddressLine2" IS NULL)) AND "c"."ShippingAddress_Tags" = "c"."BillingAddress_Tags" AND "c"."ShippingAddress_ZipCode" = "c"."BillingAddress_ZipCode" """); } @@ -217,9 +217,9 @@ public override async Task Complex_type_equals_constant(bool async) AssertSql( """ -SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" +SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" FROM "Customer" AS "c" -WHERE "c"."ShippingAddress_AddressLine1" = '804 S. Lakeshore Road' AND "c"."ShippingAddress_AddressLine2" IS NULL AND "c"."ShippingAddress_ZipCode" = 38654 AND "c"."ShippingAddress_Country_Code" = 'US' AND "c"."ShippingAddress_Country_FullName" = 'United States' +WHERE "c"."ShippingAddress_AddressLine1" = '804 S. Lakeshore Road' AND "c"."ShippingAddress_AddressLine2" IS NULL AND "c"."ShippingAddress_Tags" = '["foo","bar"]' AND "c"."ShippingAddress_ZipCode" = 38654 AND "c"."ShippingAddress_Country_Code" = 'US' AND "c"."ShippingAddress_Country_FullName" = 'United States' """); } @@ -230,13 +230,14 @@ public override async Task Complex_type_equals_parameter(bool async) AssertSql( """ @__entity_equality_address_0_AddressLine1='804 S. Lakeshore Road' (Size = 21) +@__entity_equality_address_0_Tags='["foo","bar"]' (Size = 13) @__entity_equality_address_0_ZipCode='38654' (Nullable = true) @__entity_equality_address_0_Code='US' (Size = 2) @__entity_equality_address_0_FullName='United States' (Size = 13) -SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" +SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" FROM "Customer" AS "c" -WHERE "c"."ShippingAddress_AddressLine1" = @__entity_equality_address_0_AddressLine1 AND "c"."ShippingAddress_AddressLine2" IS NULL AND "c"."ShippingAddress_ZipCode" = @__entity_equality_address_0_ZipCode AND "c"."ShippingAddress_Country_Code" = @__entity_equality_address_0_Code AND "c"."ShippingAddress_Country_FullName" = @__entity_equality_address_0_FullName +WHERE "c"."ShippingAddress_AddressLine1" = @__entity_equality_address_0_AddressLine1 AND "c"."ShippingAddress_AddressLine2" IS NULL AND "c"."ShippingAddress_Tags" = @__entity_equality_address_0_Tags AND "c"."ShippingAddress_ZipCode" = @__entity_equality_address_0_ZipCode AND "c"."ShippingAddress_Country_Code" = @__entity_equality_address_0_Code AND "c"."ShippingAddress_Country_FullName" = @__entity_equality_address_0_FullName """); } @@ -261,16 +262,17 @@ public override async Task Contains_over_complex_type(bool async) AssertSql( """ @__entity_equality_address_0_AddressLine1='804 S. Lakeshore Road' (Size = 21) +@__entity_equality_address_0_Tags='["foo","bar"]' (Size = 13) @__entity_equality_address_0_ZipCode='38654' (Nullable = true) @__entity_equality_address_0_Code='US' (Size = 2) @__entity_equality_address_0_FullName='United States' (Size = 13) -SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" +SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" FROM "Customer" AS "c" WHERE EXISTS ( SELECT 1 FROM "Customer" AS "c0" - WHERE "c0"."ShippingAddress_AddressLine1" = @__entity_equality_address_0_AddressLine1 AND "c0"."ShippingAddress_AddressLine2" IS NULL AND "c0"."ShippingAddress_ZipCode" = @__entity_equality_address_0_ZipCode AND "c0"."ShippingAddress_Country_Code" = @__entity_equality_address_0_Code AND "c0"."ShippingAddress_Country_FullName" = @__entity_equality_address_0_FullName) + WHERE "c0"."ShippingAddress_AddressLine1" = @__entity_equality_address_0_AddressLine1 AND "c0"."ShippingAddress_AddressLine2" IS NULL AND "c0"."ShippingAddress_Tags" = @__entity_equality_address_0_Tags AND "c0"."ShippingAddress_ZipCode" = @__entity_equality_address_0_ZipCode AND "c0"."ShippingAddress_Country_Code" = @__entity_equality_address_0_Code AND "c0"."ShippingAddress_Country_FullName" = @__entity_equality_address_0_FullName) """); } @@ -280,11 +282,11 @@ public override async Task Concat_complex_type(bool async) AssertSql( """ -SELECT "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" +SELECT "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" FROM "Customer" AS "c" WHERE "c"."Id" = 1 UNION ALL -SELECT "c0"."ShippingAddress_AddressLine1", "c0"."ShippingAddress_AddressLine2", "c0"."ShippingAddress_ZipCode", "c0"."ShippingAddress_Country_Code", "c0"."ShippingAddress_Country_FullName" +SELECT "c0"."ShippingAddress_AddressLine1", "c0"."ShippingAddress_AddressLine2", "c0"."ShippingAddress_Tags", "c0"."ShippingAddress_ZipCode", "c0"."ShippingAddress_Country_Code", "c0"."ShippingAddress_Country_FullName" FROM "Customer" AS "c0" WHERE "c0"."Id" = 2 """); @@ -296,11 +298,11 @@ public override async Task Concat_entity_type_containing_complex_property(bool a AssertSql( """ -SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" +SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" FROM "Customer" AS "c" WHERE "c"."Id" = 1 UNION ALL -SELECT "c0"."Id", "c0"."Name", "c0"."BillingAddress_AddressLine1", "c0"."BillingAddress_AddressLine2", "c0"."BillingAddress_ZipCode", "c0"."BillingAddress_Country_Code", "c0"."BillingAddress_Country_FullName", "c0"."ShippingAddress_AddressLine1", "c0"."ShippingAddress_AddressLine2", "c0"."ShippingAddress_ZipCode", "c0"."ShippingAddress_Country_Code", "c0"."ShippingAddress_Country_FullName" +SELECT "c0"."Id", "c0"."Name", "c0"."BillingAddress_AddressLine1", "c0"."BillingAddress_AddressLine2", "c0"."BillingAddress_Tags", "c0"."BillingAddress_ZipCode", "c0"."BillingAddress_Country_Code", "c0"."BillingAddress_Country_FullName", "c0"."ShippingAddress_AddressLine1", "c0"."ShippingAddress_AddressLine2", "c0"."ShippingAddress_Tags", "c0"."ShippingAddress_ZipCode", "c0"."ShippingAddress_Country_Code", "c0"."ShippingAddress_Country_FullName" FROM "Customer" AS "c0" WHERE "c0"."Id" = 2 """); @@ -312,11 +314,11 @@ public override async Task Union_entity_type_containing_complex_property(bool as AssertSql( """ -SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" +SELECT "c"."Id", "c"."Name", "c"."BillingAddress_AddressLine1", "c"."BillingAddress_AddressLine2", "c"."BillingAddress_Tags", "c"."BillingAddress_ZipCode", "c"."BillingAddress_Country_Code", "c"."BillingAddress_Country_FullName", "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" FROM "Customer" AS "c" WHERE "c"."Id" = 1 UNION -SELECT "c0"."Id", "c0"."Name", "c0"."BillingAddress_AddressLine1", "c0"."BillingAddress_AddressLine2", "c0"."BillingAddress_ZipCode", "c0"."BillingAddress_Country_Code", "c0"."BillingAddress_Country_FullName", "c0"."ShippingAddress_AddressLine1", "c0"."ShippingAddress_AddressLine2", "c0"."ShippingAddress_ZipCode", "c0"."ShippingAddress_Country_Code", "c0"."ShippingAddress_Country_FullName" +SELECT "c0"."Id", "c0"."Name", "c0"."BillingAddress_AddressLine1", "c0"."BillingAddress_AddressLine2", "c0"."BillingAddress_Tags", "c0"."BillingAddress_ZipCode", "c0"."BillingAddress_Country_Code", "c0"."BillingAddress_Country_FullName", "c0"."ShippingAddress_AddressLine1", "c0"."ShippingAddress_AddressLine2", "c0"."ShippingAddress_Tags", "c0"."ShippingAddress_ZipCode", "c0"."ShippingAddress_Country_Code", "c0"."ShippingAddress_Country_FullName" FROM "Customer" AS "c0" WHERE "c0"."Id" = 2 """); @@ -328,11 +330,11 @@ public override async Task Union_complex_type(bool async) AssertSql( """ -SELECT "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" +SELECT "c"."ShippingAddress_AddressLine1", "c"."ShippingAddress_AddressLine2", "c"."ShippingAddress_Tags", "c"."ShippingAddress_ZipCode", "c"."ShippingAddress_Country_Code", "c"."ShippingAddress_Country_FullName" FROM "Customer" AS "c" WHERE "c"."Id" = 1 UNION -SELECT "c0"."ShippingAddress_AddressLine1", "c0"."ShippingAddress_AddressLine2", "c0"."ShippingAddress_ZipCode", "c0"."ShippingAddress_Country_Code", "c0"."ShippingAddress_Country_FullName" +SELECT "c0"."ShippingAddress_AddressLine1", "c0"."ShippingAddress_AddressLine2", "c0"."ShippingAddress_Tags", "c0"."ShippingAddress_ZipCode", "c0"."ShippingAddress_Country_Code", "c0"."ShippingAddress_Country_FullName" FROM "Customer" AS "c0" WHERE "c0"."Id" = 2 """);