From 0d1f0c147f5e02e71086fac798905c2536798ee2 Mon Sep 17 00:00:00 2001 From: "kirolous.nashaat" Date: Sun, 28 Sep 2025 20:56:41 +0300 Subject: [PATCH 1/8] Added test for select complex property from tvf Added metadata for complextypes for AddViews in RelationalModel --- .../Metadata/Internal/RelationalModel.cs | 39 ++++++++++- .../Internal/RelationalTypeBaseExtensions.cs | 7 +- .../Metadata/Internal/ViewMapping.cs | 2 +- .../Query/UdfDbFunctionTestBase.cs | 65 ++++++++++++++++++- .../Query/UdfDbFunctionSqlServerTests.cs | 12 ++++ 5 files changed, 116 insertions(+), 9 deletions(-) diff --git a/src/EFCore.Relational/Metadata/Internal/RelationalModel.cs b/src/EFCore.Relational/Metadata/Internal/RelationalModel.cs index 9f6c26fb8fb..5fe2631911f 100644 --- a/src/EFCore.Relational/Metadata/Internal/RelationalModel.cs +++ b/src/EFCore.Relational/Metadata/Internal/RelationalModel.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 System.Data; using System.Text; namespace Microsoft.EntityFrameworkCore.Metadata.Internal; @@ -713,8 +714,8 @@ private static void AddViews( private static void CreateViewMapping( IRelationalTypeMappingSource relationalTypeMappingSource, - IEntityType entityType, - IEntityType mappedType, + ITypeBase entityType, + ITypeBase mappedType, StoreObjectIdentifier mappedView, RelationalModel databaseModel, List viewMappings, @@ -770,11 +771,43 @@ private static void CreateViewMapping( } } + // TODO: Change this to call GetComplexProperties() + // Issue #31248 + foreach (var complexProperty in mappedType.GetDeclaredComplexProperties()) + { + var complexType = complexProperty.ComplexType; + + var complexViewMappings = + (List?)complexType.FindRuntimeAnnotationValue(RelationalAnnotationNames.ViewMappings); + if (complexViewMappings == null) + { + complexViewMappings = []; + complexType.AddRuntimeAnnotation(RelationalAnnotationNames.ViewMappings, complexViewMappings); + } + + CreateViewMapping( + relationalTypeMappingSource, + complexType, + complexType, + mappedView, + databaseModel, + complexViewMappings, + includesDerivedTypes: true, + isSplitEntityTypePrincipal: isSplitEntityTypePrincipal == true ? false : isSplitEntityTypePrincipal); + } + if (((ITableMappingBase)viewMapping).ColumnMappings.Any() || viewMappings.Count == 0) { viewMappings.Add(viewMapping); - view.EntityTypeMappings.Add(viewMapping); + if(entityType is IEntityType) + { + view.EntityTypeMappings.Add(viewMapping); + } + else + { + view.ComplexTypeMappings.Add(viewMapping); + } } } diff --git a/src/EFCore.Relational/Metadata/Internal/RelationalTypeBaseExtensions.cs b/src/EFCore.Relational/Metadata/Internal/RelationalTypeBaseExtensions.cs index 0c30e6610b6..36fac663d64 100644 --- a/src/EFCore.Relational/Metadata/Internal/RelationalTypeBaseExtensions.cs +++ b/src/EFCore.Relational/Metadata/Internal/RelationalTypeBaseExtensions.cs @@ -22,9 +22,8 @@ public static class RelationalTypeBaseExtensions public static IEnumerable GetViewOrTableMappings(this ITypeBase typeBase) { typeBase.Model.EnsureRelationalModel(); - return (IEnumerable?)(typeBase.FindRuntimeAnnotationValue( - RelationalAnnotationNames.ViewMappings) - ?? typeBase.FindRuntimeAnnotationValue(RelationalAnnotationNames.TableMappings)) - ?? []; + var viewMapping = typeBase.FindRuntimeAnnotationValue(RelationalAnnotationNames.ViewMappings); + var tableMapping = typeBase.FindRuntimeAnnotationValue(RelationalAnnotationNames.TableMappings); + return (IEnumerable?)(viewMapping ?? tableMapping) ?? []; } } diff --git a/src/EFCore.Relational/Metadata/Internal/ViewMapping.cs b/src/EFCore.Relational/Metadata/Internal/ViewMapping.cs index 7faf3af154c..d6d7ae000d1 100644 --- a/src/EFCore.Relational/Metadata/Internal/ViewMapping.cs +++ b/src/EFCore.Relational/Metadata/Internal/ViewMapping.cs @@ -18,7 +18,7 @@ public class ViewMapping : TableMappingBase, IViewMapping /// doing so can result in application failures when updating to a new Entity Framework Core release. /// public ViewMapping( - IEntityType entityType, + ITypeBase entityType, View view, bool? includesDerivedTypes) : base(entityType, view, includesDerivedTypes) diff --git a/test/EFCore.Relational.Specification.Tests/Query/UdfDbFunctionTestBase.cs b/test/EFCore.Relational.Specification.Tests/Query/UdfDbFunctionTestBase.cs index f47dd2a4414..dd13c7db404 100644 --- a/test/EFCore.Relational.Specification.Tests/Query/UdfDbFunctionTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/Query/UdfDbFunctionTestBase.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 System.ComponentModel.DataAnnotations.Schema; using Microsoft.EntityFrameworkCore.Query.SqlExpressions; namespace Microsoft.EntityFrameworkCore.Query; @@ -17,12 +18,23 @@ protected UDFSqlContext CreateContext() #region Model + [ComplexType] + public class Phone + { + public Phone(int code, int number) + { + Code = code; + Number = number; + } + + public int Code { get; set; } + public int Number { get; set; } + } public class Customer { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } - public List Orders { get; set; } public List
Addresses { get; set; } } @@ -92,6 +104,31 @@ public class TopSellingProduct public int? AmountSold { get; set; } } + [ComplexType] + public class ComplexGpsCoordinates + { + public ComplexGpsCoordinates(double latitude, double longitude) + { + Latitude = latitude; + Longitude = longitude; + } + + public double Latitude { get; set; } + public double Longitude { get; set; } + } + + public class MapLocation + { + public int Id { get; set; } + public ComplexGpsCoordinates GpsCoordinates { get; set; } + } + + public class MapLocationData + { + public int Id { get; set; } + public ComplexGpsCoordinates GpsCoordinates { get; set; } + } + public class CustomerData { public int Id { get; set; } @@ -107,6 +144,7 @@ protected class UDFSqlContext(DbContextOptions options) : PoolableDbContext(opti public DbSet Orders { get; set; } public DbSet Products { get; set; } public DbSet
Addresses { get; set; } + public DbSet MapLocations { get; set; } #endregion @@ -355,6 +393,7 @@ protected override void OnModelCreating(ModelBuilder modelBuilder) modelBuilder.Entity().HasNoKey(); modelBuilder.Entity().HasNoKey().ToFunction("GetTopTwoSellingProducts"); modelBuilder.Entity().ToView("Customers"); + modelBuilder.Entity().ToView("MapLocations"); } } @@ -520,11 +559,22 @@ protected override async Task SeedAsync(DbContext context) ] }; + var location1 = new MapLocation + { + GpsCoordinates = new ComplexGpsCoordinates(1.0, 2.0), + }; + + var location2 = new MapLocation + { + GpsCoordinates = new ComplexGpsCoordinates(1.0, 2.0), + }; + ((UDFSqlContext)context).Products.AddRange(product1, product2, product3, product4, product5); ((UDFSqlContext)context).Addresses.AddRange( address11, address12, address21, address31, address32, address41, address42, address43); ((UDFSqlContext)context).Customers.AddRange(customer1, customer2, customer3, customer4); ((UDFSqlContext)context).Orders.AddRange(order11, order12, order13, order21, order22, order31); + ((UDFSqlContext)context).MapLocations.AddRange(location1, location2); } } @@ -2182,6 +2232,19 @@ orderby t.FirstName } } + [ConditionalFact] + public virtual void TVF_backing_entity_type_with_complextype_mapped_to_view() + { + using (var context = CreateContext()) + { + var locations = (from t in context.Set() + orderby t.Id + select t).ToList(); + + Assert.Equal(2, locations.Count); + } + } + [ConditionalFact] public virtual void Udf_with_argument_being_comparison_to_null_parameter() { diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/UdfDbFunctionSqlServerTests.cs b/test/EFCore.SqlServer.FunctionalTests/Query/UdfDbFunctionSqlServerTests.cs index 661e354256e..591fdc855db 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/UdfDbFunctionSqlServerTests.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/UdfDbFunctionSqlServerTests.cs @@ -969,6 +969,18 @@ ORDER BY [c].[FirstName] """); } + public override void TVF_backing_entity_type_with_complextype_mapped_to_view() + { + base.TVF_backing_entity_type_with_complextype_mapped_to_view(); + + AssertSql( + """ +SELECT [m].[Id], [m].[GpsCoordinates_Latitude], [m].[GpsCoordinates_Longitude] +FROM [MapLocations] AS [m] +ORDER BY [m].[Id] +"""); + } + public override void Udf_with_argument_being_comparison_to_null_parameter() { base.Udf_with_argument_being_comparison_to_null_parameter(); From a4f32d1decb78889d1599e55a41cb7309a3a93d2 Mon Sep 17 00:00:00 2001 From: Kirolous Nashaat Date: Sun, 12 Oct 2025 23:38:45 +0300 Subject: [PATCH 2/8] Fixed Update_complex_type_with_view_mapping tests --- ...leMethodTranslatingExpressionVisitor.ExecuteUpdate.cs | 6 +++--- .../Query/RelationalSqlTranslatingExpressionVisitor.cs | 9 +++++---- .../Query/SqlExpressions/SelectExpression.cs | 5 +++-- .../Query/StructuralTypeProjectionExpression.cs | 7 ++++++- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs index c4d4cac1cef..c1559ed0cdb 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs @@ -300,7 +300,7 @@ bool TryTranslateMemberAccess( [NotNullWhen(true)] out IPropertyBase? property) { if (IsMemberAccess(expression, QueryCompilationContext.Model, out var baseExpression, out var member) - && _sqlTranslator.TryBindMember(_sqlTranslator.Visit(baseExpression), member, out var target, out var targetProperty)) + && _sqlTranslator.TryBindMember(_sqlTranslator.Visit(baseExpression), member, out var target, out var targetProperty, forUpdate: true)) { translation = target; property = targetProperty; @@ -540,7 +540,7 @@ void ProcessComplexType(StructuralTypeShaperExpression shaperExpression, Express RelationalStrings.ExecuteUpdateOverJsonIsNotSupported(complexProperty.ComplexType.DisplayName())); } - var nestedShaperExpression = (StructuralTypeShaperExpression)projection.BindComplexProperty(complexProperty); + var nestedShaperExpression = (StructuralTypeShaperExpression)projection.BindComplexProperty(complexProperty, forUpdate: true); var nestedValueExpression = CreateComplexPropertyAccessExpression(valueExpression, complexProperty); ProcessComplexType(nestedShaperExpression, nestedValueExpression); } @@ -635,7 +635,7 @@ SqlParameterExpression parameter StructuralType: IComplexType, ValueBufferExpression: StructuralTypeProjectionExpression projection } - => projection.BindComplexProperty(complexProperty), + => projection.BindComplexProperty(complexProperty, forUpdate: true), _ => throw new UnreachableException() }; diff --git a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs index c68f69f514c..bb710be2272 100644 --- a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs @@ -1219,7 +1219,8 @@ public virtual bool TryBindMember( Expression? source, MemberIdentity member, [NotNullWhen(true)] out Expression? expression, - [NotNullWhen(true)] out IPropertyBase? property) + [NotNullWhen(true)] out IPropertyBase? property, + bool forUpdate = false) { if (source is not StructuralTypeReferenceExpression typeReference) { @@ -1247,7 +1248,7 @@ public virtual bool TryBindMember( if (complexProperty is not null) { - expression = BindComplexProperty(typeReference, complexProperty); + expression = BindComplexProperty(typeReference, complexProperty, forUpdate: forUpdate); property = complexProperty; return true; } @@ -1359,7 +1360,7 @@ private SqlExpression BindProperty(StructuralTypeReferenceExpression typeReferen } } - private Expression BindComplexProperty(StructuralTypeReferenceExpression typeReference, IComplexProperty complexProperty) + private Expression BindComplexProperty(StructuralTypeReferenceExpression typeReference, IComplexProperty complexProperty, bool forUpdate = false) { switch (typeReference) { @@ -1370,7 +1371,7 @@ private Expression BindComplexProperty(StructuralTypeReferenceExpression typeRef // TODO: Move all this logic into StructuralTypeProjectionExpression, #31376 Check.DebugAssert(structuralTypeProjection.IsNullable == shaper.IsNullable, "Nullability mismatch"); - return structuralTypeProjection.BindComplexProperty(complexProperty) switch + return structuralTypeProjection.BindComplexProperty(complexProperty, forUpdate: forUpdate) switch { StructuralTypeShaperExpression s => new StructuralTypeReferenceExpression(s), CollectionResultExpression c => c, diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index 2d57cfb6298..df4cca48246 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -2855,14 +2855,15 @@ static TableExpressionBase FindRootTableExpressionForColumn(SelectExpression sel [EntityFrameworkInternal] public static Expression GenerateComplexPropertyShaperExpression( StructuralTypeProjectionExpression containerProjection, - IComplexProperty complexProperty) + IComplexProperty complexProperty, + bool forUpdate = false) { var complexType = complexProperty.ComplexType; var propertyExpressionMap = new Dictionary(); // We do not support complex type splitting, so we will only ever have a single table/view mapping to it. // See Issue #32853 and Issue #31248 - var complexTypeTable = complexType.GetViewOrTableMappings().Single().Table; + ITableBase complexTypeTable = forUpdate ? complexType.GetTableMappings().Single().Table : complexType.GetViewOrTableMappings().Single().Table; if (!containerProjection.TableMap.TryGetValue(complexTypeTable, out var tableAlias)) { diff --git a/src/EFCore.Relational/Query/StructuralTypeProjectionExpression.cs b/src/EFCore.Relational/Query/StructuralTypeProjectionExpression.cs index 8ca55f5227e..e6792228d2b 100644 --- a/src/EFCore.Relational/Query/StructuralTypeProjectionExpression.cs +++ b/src/EFCore.Relational/Query/StructuralTypeProjectionExpression.cs @@ -369,9 +369,14 @@ public virtual ColumnExpression BindProperty(IProperty property) /// Binds a complex property with this structural type projection to get a shaper expression for the target complex type. /// /// A complex property to bind. + /// Is the mapping for read (false) or update (true). /// A shaper expression for the target complex type. - public virtual Expression BindComplexProperty(IComplexProperty complexProperty) + public virtual Expression BindComplexProperty(IComplexProperty complexProperty, bool forUpdate = false) { + if (forUpdate) + { + return SelectExpression.GenerateComplexPropertyShaperExpression(this, complexProperty, forUpdate: true); + } if (_complexPropertyCache is null || !_complexPropertyCache.TryGetValue(complexProperty, out var resultShaper)) { _complexPropertyCache ??= new Dictionary(); From d84fcf55408b98a61f91f3387c42b7177db78cc1 Mon Sep 17 00:00:00 2001 From: Kirolous Nashaat Date: Tue, 4 Nov 2025 18:40:23 +0200 Subject: [PATCH 3/8] Revert "Fixed Update_complex_type_with_view_mapping tests" This reverts commit a4f32d1decb78889d1599e55a41cb7309a3a93d2. --- ...leMethodTranslatingExpressionVisitor.ExecuteUpdate.cs | 6 +++--- .../Query/RelationalSqlTranslatingExpressionVisitor.cs | 9 ++++----- .../Query/SqlExpressions/SelectExpression.cs | 5 ++--- .../Query/StructuralTypeProjectionExpression.cs | 7 +------ 4 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs index c1559ed0cdb..c4d4cac1cef 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs @@ -300,7 +300,7 @@ bool TryTranslateMemberAccess( [NotNullWhen(true)] out IPropertyBase? property) { if (IsMemberAccess(expression, QueryCompilationContext.Model, out var baseExpression, out var member) - && _sqlTranslator.TryBindMember(_sqlTranslator.Visit(baseExpression), member, out var target, out var targetProperty, forUpdate: true)) + && _sqlTranslator.TryBindMember(_sqlTranslator.Visit(baseExpression), member, out var target, out var targetProperty)) { translation = target; property = targetProperty; @@ -540,7 +540,7 @@ void ProcessComplexType(StructuralTypeShaperExpression shaperExpression, Express RelationalStrings.ExecuteUpdateOverJsonIsNotSupported(complexProperty.ComplexType.DisplayName())); } - var nestedShaperExpression = (StructuralTypeShaperExpression)projection.BindComplexProperty(complexProperty, forUpdate: true); + var nestedShaperExpression = (StructuralTypeShaperExpression)projection.BindComplexProperty(complexProperty); var nestedValueExpression = CreateComplexPropertyAccessExpression(valueExpression, complexProperty); ProcessComplexType(nestedShaperExpression, nestedValueExpression); } @@ -635,7 +635,7 @@ SqlParameterExpression parameter StructuralType: IComplexType, ValueBufferExpression: StructuralTypeProjectionExpression projection } - => projection.BindComplexProperty(complexProperty, forUpdate: true), + => projection.BindComplexProperty(complexProperty), _ => throw new UnreachableException() }; diff --git a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs index bb710be2272..c68f69f514c 100644 --- a/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs +++ b/src/EFCore.Relational/Query/RelationalSqlTranslatingExpressionVisitor.cs @@ -1219,8 +1219,7 @@ public virtual bool TryBindMember( Expression? source, MemberIdentity member, [NotNullWhen(true)] out Expression? expression, - [NotNullWhen(true)] out IPropertyBase? property, - bool forUpdate = false) + [NotNullWhen(true)] out IPropertyBase? property) { if (source is not StructuralTypeReferenceExpression typeReference) { @@ -1248,7 +1247,7 @@ public virtual bool TryBindMember( if (complexProperty is not null) { - expression = BindComplexProperty(typeReference, complexProperty, forUpdate: forUpdate); + expression = BindComplexProperty(typeReference, complexProperty); property = complexProperty; return true; } @@ -1360,7 +1359,7 @@ private SqlExpression BindProperty(StructuralTypeReferenceExpression typeReferen } } - private Expression BindComplexProperty(StructuralTypeReferenceExpression typeReference, IComplexProperty complexProperty, bool forUpdate = false) + private Expression BindComplexProperty(StructuralTypeReferenceExpression typeReference, IComplexProperty complexProperty) { switch (typeReference) { @@ -1371,7 +1370,7 @@ private Expression BindComplexProperty(StructuralTypeReferenceExpression typeRef // TODO: Move all this logic into StructuralTypeProjectionExpression, #31376 Check.DebugAssert(structuralTypeProjection.IsNullable == shaper.IsNullable, "Nullability mismatch"); - return structuralTypeProjection.BindComplexProperty(complexProperty, forUpdate: forUpdate) switch + return structuralTypeProjection.BindComplexProperty(complexProperty) switch { StructuralTypeShaperExpression s => new StructuralTypeReferenceExpression(s), CollectionResultExpression c => c, diff --git a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs index df4cca48246..2d57cfb6298 100644 --- a/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs +++ b/src/EFCore.Relational/Query/SqlExpressions/SelectExpression.cs @@ -2855,15 +2855,14 @@ static TableExpressionBase FindRootTableExpressionForColumn(SelectExpression sel [EntityFrameworkInternal] public static Expression GenerateComplexPropertyShaperExpression( StructuralTypeProjectionExpression containerProjection, - IComplexProperty complexProperty, - bool forUpdate = false) + IComplexProperty complexProperty) { var complexType = complexProperty.ComplexType; var propertyExpressionMap = new Dictionary(); // We do not support complex type splitting, so we will only ever have a single table/view mapping to it. // See Issue #32853 and Issue #31248 - ITableBase complexTypeTable = forUpdate ? complexType.GetTableMappings().Single().Table : complexType.GetViewOrTableMappings().Single().Table; + var complexTypeTable = complexType.GetViewOrTableMappings().Single().Table; if (!containerProjection.TableMap.TryGetValue(complexTypeTable, out var tableAlias)) { diff --git a/src/EFCore.Relational/Query/StructuralTypeProjectionExpression.cs b/src/EFCore.Relational/Query/StructuralTypeProjectionExpression.cs index e6792228d2b..8ca55f5227e 100644 --- a/src/EFCore.Relational/Query/StructuralTypeProjectionExpression.cs +++ b/src/EFCore.Relational/Query/StructuralTypeProjectionExpression.cs @@ -369,14 +369,9 @@ public virtual ColumnExpression BindProperty(IProperty property) /// Binds a complex property with this structural type projection to get a shaper expression for the target complex type. /// /// A complex property to bind. - /// Is the mapping for read (false) or update (true). /// A shaper expression for the target complex type. - public virtual Expression BindComplexProperty(IComplexProperty complexProperty, bool forUpdate = false) + public virtual Expression BindComplexProperty(IComplexProperty complexProperty) { - if (forUpdate) - { - return SelectExpression.GenerateComplexPropertyShaperExpression(this, complexProperty, forUpdate: true); - } if (_complexPropertyCache is null || !_complexPropertyCache.TryGetValue(complexProperty, out var resultShaper)) { _complexPropertyCache ??= new Dictionary(); From 540972a10ae73c360f78447b985ff64f6ff81edb Mon Sep 17 00:00:00 2001 From: Kirolous Nashaat Date: Tue, 4 Nov 2025 19:30:59 +0200 Subject: [PATCH 4/8] Fixed execute update on two cases update property in a complextype and setting the complextype itself --- ...nslatingExpressionVisitor.ExecuteUpdate.cs | 61 ++++++++++++------- ...haredModelBulkUpdatesRelationalTestBase.cs | 20 ++++-- .../NonSharedModelBulkUpdatesSqlServerTest.cs | 13 ++++ .../NonSharedModelBulkUpdatesSqliteTest.cs | 24 +++++++- 4 files changed, 88 insertions(+), 30 deletions(-) diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs index c4d4cac1cef..0a8a8807236 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs @@ -276,10 +276,10 @@ protected virtual IReadOnlyList TranslateSetters( Arguments: [ MethodCallExpression - { - Method: { Name: nameof(Queryable.AsQueryable), IsGenericMethod: true } asQueryableMethod, - Arguments: [var elementAtSource] - }, + { + Method: { Name: nameof(Queryable.AsQueryable), IsGenericMethod: true } asQueryableMethod, + Arguments: [var elementAtSource] + }, _ ] } methodCall @@ -294,23 +294,23 @@ when elementAtMethod.GetGenericMethodDefinition() == QueryableMethods.ElementAt default: throw new InvalidOperationException(RelationalStrings.InvalidPropertyInSetProperty(propertySelector.Print())); - bool TryTranslateMemberAccess( - Expression expression, - [NotNullWhen(true)] out Expression? translation, - [NotNullWhen(true)] out IPropertyBase? property) - { - if (IsMemberAccess(expression, QueryCompilationContext.Model, out var baseExpression, out var member) - && _sqlTranslator.TryBindMember(_sqlTranslator.Visit(baseExpression), member, out var target, out var targetProperty)) + bool TryTranslateMemberAccess( + Expression expression, + [NotNullWhen(true)] out Expression? translation, + [NotNullWhen(true)] out IPropertyBase? property) { - translation = target; - property = targetProperty; - return true; - } + if (IsMemberAccess(expression, QueryCompilationContext.Model, out var baseExpression, out var member) + && _sqlTranslator.TryBindMember(_sqlTranslator.Visit(baseExpression), member, out var target, out var targetProperty)) + { + translation = target; + property = targetProperty; + return true; + } - translation = null; - property = null; - return false; - } + translation = null; + property = null; + return false; + } } if (targetProperty.DeclaringType is IEntityType entityType && entityType.IsMappedToJson()) @@ -470,11 +470,18 @@ void ProcessColumn(ColumnExpression column) // Note that we assume exactly one column with the given name mapped to the entity (despite entity splitting). // See #36647 and #36646 about improving this. var containerColumnName = complexType.GetContainerColumnName(); - targetColumnModel = complexType.ContainingEntityType.GetTableMappings() + if (containerColumnName == null) + { + //todo + targetColumnModel = null; + } + else + { + targetColumnModel = complexType.ContainingEntityType.GetTableMappings() .SelectMany(m => m.Table.Columns) .Where(c => c.Name == containerColumnName) - .Single(); - + .SingleOrDefault(); + } break; } @@ -510,14 +517,22 @@ void ProcessColumn(ColumnExpression column) void ProcessComplexType(StructuralTypeShaperExpression shaperExpression, Expression valueExpression) { if (shaperExpression.StructuralType is not IComplexType complexType - || shaperExpression.ValueBufferExpression is not StructuralTypeProjectionExpression projection) + || shaperExpression.ValueBufferExpression is not StructuralTypeProjectionExpression projection) { throw new UnreachableException(); } foreach (var property in complexType.GetProperties()) { + // If the entity is also mapped to a view, the SelectExpression will refer to the view instead, since + // translation happens with the assumption that we're querying, not deleting. + // For this case, we must replace the TableExpression in the SelectExpression - referring to the view - with the + // one that refers to the mutable table. + + targetProperty = property; var column = projection.BindProperty(property); + ProcessColumn(column); + CheckColumnOnSameTable(column, propertySelector); var rewrittenValueSelector = CreatePropertyAccessExpression(valueExpression, property); diff --git a/test/EFCore.Relational.Specification.Tests/BulkUpdates/NonSharedModelBulkUpdatesRelationalTestBase.cs b/test/EFCore.Relational.Specification.Tests/BulkUpdates/NonSharedModelBulkUpdatesRelationalTestBase.cs index 538853f98b3..340e903d6d3 100644 --- a/test/EFCore.Relational.Specification.Tests/BulkUpdates/NonSharedModelBulkUpdatesRelationalTestBase.cs +++ b/test/EFCore.Relational.Specification.Tests/BulkUpdates/NonSharedModelBulkUpdatesRelationalTestBase.cs @@ -108,20 +108,30 @@ await AssertUpdate( rowsAffectedCount: 1); } - [ConditionalTheory, MemberData(nameof(IsAsyncData))] // #34677, #34706 + [ConditionalTheory, MemberData(nameof(IsAsyncData))] // #34677 public virtual async Task Update_complex_type_with_view_mapping(bool async) { var contextFactory = await InitializeAsync(seed: async context => await context.Seed()); - // #34706 - var exception = await Assert.ThrowsAsync(() => AssertUpdate( + await AssertUpdate( async, contextFactory.CreateContext, ss => ss.Foos, s => s.SetProperty(f => f.ComplexThing, new Context34677.ComplexThing { Prop1 = 3, Prop2 = 4 }), - rowsAffectedCount: 1)); + rowsAffectedCount: 1); + } - Assert.IsType(exception.InnerException); + [ConditionalTheory, MemberData(nameof(IsAsyncData))] // #34677 + public virtual async Task Update_complex_type_property_with_view_mapping(bool async) + { + var contextFactory = await InitializeAsync(seed: async context => await context.Seed()); + + await AssertUpdate( + async, + contextFactory.CreateContext, + ss => ss.Foos, + s => s.SetProperty(f => f.ComplexThing.Prop1, 6), + rowsAffectedCount: 1); } protected class Context34677(DbContextOptions options) : DbContext(options) diff --git a/test/EFCore.SqlServer.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqlServerTest.cs index dbd19852f1b..4bdcb01239d 100644 --- a/test/EFCore.SqlServer.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqlServerTest.cs @@ -231,6 +231,19 @@ public override async Task Update_complex_type_with_view_mapping(bool async) AssertSql(); } + public override async Task Update_complex_type_property_with_view_mapping(bool async) + { + await base.Update_complex_type_property_with_view_mapping(async); + + AssertSql( + """ +@p='6' + +UPDATE "Blogs" AS "b" +SET "ComplexThing_Prop1" = @p +"""); + } + private void AssertSql(params string[] expected) => TestSqlLoggerFactory.AssertBaseline(expected); diff --git a/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqliteTest.cs b/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqliteTest.cs index 505e637ad09..a41ee6f5bc7 100644 --- a/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqliteTest.cs +++ b/test/EFCore.Sqlite.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqliteTest.cs @@ -223,8 +223,28 @@ public override async Task Update_complex_type_with_view_mapping(bool async) { await base.Update_complex_type_with_view_mapping(async); - // #34706 - AssertSql(); + AssertSql( + """ +@complex_type_p_Prop1='3' (Nullable = true) +@complex_type_p_Prop2='4' (Nullable = true) + +UPDATE "Blogs" AS "b" +SET "ComplexThing_Prop1" = @complex_type_p_Prop1, + "ComplexThing_Prop2" = @complex_type_p_Prop2 +"""); + } + + public override async Task Update_complex_type_property_with_view_mapping(bool async) + { + await base.Update_complex_type_property_with_view_mapping(async); + + AssertSql( + """ +@p='6' + +UPDATE "Blogs" AS "b" +SET "ComplexThing_Prop1" = @p +"""); } protected override DbContextOptionsBuilder AddOptions(DbContextOptionsBuilder builder) From b180d96a6692a6810da8ef4a552c1d403e754300 Mon Sep 17 00:00:00 2001 From: Kirolous Nashaat Date: Tue, 4 Nov 2025 19:34:24 +0200 Subject: [PATCH 5/8] fix minor change --- ...MethodTranslatingExpressionVisitor.ExecuteUpdate.cs | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs index 0a8a8807236..ae63a50f913 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs @@ -470,18 +470,10 @@ void ProcessColumn(ColumnExpression column) // Note that we assume exactly one column with the given name mapped to the entity (despite entity splitting). // See #36647 and #36646 about improving this. var containerColumnName = complexType.GetContainerColumnName(); - if (containerColumnName == null) - { - //todo - targetColumnModel = null; - } - else - { - targetColumnModel = complexType.ContainingEntityType.GetTableMappings() + targetColumnModel = complexType.ContainingEntityType.GetTableMappings() .SelectMany(m => m.Table.Columns) .Where(c => c.Name == containerColumnName) .SingleOrDefault(); - } break; } From 1a8bfbe390b0f4cc5fbb52692657cc628cb4e757 Mon Sep 17 00:00:00 2001 From: Kirolous Nashaat Date: Tue, 4 Nov 2025 19:39:28 +0200 Subject: [PATCH 6/8] revert format removed comment --- ...hodTranslatingExpressionVisitor.ExecuteUpdate.cs | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs index ae63a50f913..345d7f2b541 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs @@ -276,10 +276,10 @@ protected virtual IReadOnlyList TranslateSetters( Arguments: [ MethodCallExpression - { - Method: { Name: nameof(Queryable.AsQueryable), IsGenericMethod: true } asQueryableMethod, - Arguments: [var elementAtSource] - }, + { + Method: { Name: nameof(Queryable.AsQueryable), IsGenericMethod: true } asQueryableMethod, + Arguments: [var elementAtSource] + }, _ ] } methodCall @@ -516,11 +516,6 @@ void ProcessComplexType(StructuralTypeShaperExpression shaperExpression, Express foreach (var property in complexType.GetProperties()) { - // If the entity is also mapped to a view, the SelectExpression will refer to the view instead, since - // translation happens with the assumption that we're querying, not deleting. - // For this case, we must replace the TableExpression in the SelectExpression - referring to the view - with the - // one that refers to the mutable table. - targetProperty = property; var column = projection.BindProperty(property); ProcessColumn(column); From 3606f2ac56b305fae180edf93c6bac91cc263de0 Mon Sep 17 00:00:00 2001 From: "kirolous.nashaat" Date: Tue, 4 Nov 2025 21:18:03 +0200 Subject: [PATCH 7/8] fixed sql queries baseline for sqlserver tests --- .../NonSharedModelBulkUpdatesSqlServerTest.cs | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/test/EFCore.SqlServer.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqlServerTest.cs index 4bdcb01239d..79db8e7e787 100644 --- a/test/EFCore.SqlServer.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqlServerTest.cs @@ -227,8 +227,17 @@ public override async Task Update_complex_type_with_view_mapping(bool async) { await base.Update_complex_type_with_view_mapping(async); - // #34706 - AssertSql(); + AssertSql( + """ +@complex_type_p_Prop1='3' (Nullable = true) +@complex_type_p_Prop2='4' (Nullable = true) + +UPDATE [b] +SET [b].[ComplexThing_Prop1] = @complex_type_p_Prop1, + [b].[ComplexThing_Prop2] = @complex_type_p_Prop2 +FROM [Blogs] AS [b] +"""); + } public override async Task Update_complex_type_property_with_view_mapping(bool async) @@ -239,8 +248,9 @@ public override async Task Update_complex_type_property_with_view_mapping(bool a """ @p='6' -UPDATE "Blogs" AS "b" -SET "ComplexThing_Prop1" = @p +UPDATE [b] +SET [b].[ComplexThing_Prop1] = @p +FROM [Blogs] AS [b] """); } From d0e14fdca81bdc1790e3a2fc17de9561724068ac Mon Sep 17 00:00:00 2001 From: Kirolous Nashaat Date: Tue, 4 Nov 2025 21:18:42 +0200 Subject: [PATCH 8/8] update baseline for complextypes after runtime annotations --- .../ComplexTypes/DbContextModelBuilder.cs | 153 ++++++++++++++++++ 1 file changed, 153 insertions(+) diff --git a/test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/ComplexTypes/DbContextModelBuilder.cs b/test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/ComplexTypes/DbContextModelBuilder.cs index e7e1b974016..0a21db7d54b 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/ComplexTypes/DbContextModelBuilder.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Scaffolding/Baselines/ComplexTypes/DbContextModelBuilder.cs @@ -624,6 +624,11 @@ private IRelationalModel CreateRelationalModel() var viewMappings = new List(); principalBase.SetRuntimeAnnotation("Relational:ViewMappings", viewMappings); var principalBaseViewView = new View("PrincipalBaseView", null, relationalModel); + var deetsViewColumn = new ViewColumn("Deets", "varchar(64)", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Deets", deetsViewColumn); var discriminatorViewColumn = new ViewColumn("Discriminator", "nvarchar(55)", principalBaseViewView); principalBaseViewView.Columns.Add("Discriminator", discriminatorViewColumn); var enum1ViewColumn = new ViewColumn("Enum1", "int", principalBaseViewView); @@ -639,6 +644,118 @@ private IRelationalModel CreateRelationalModel() principalBaseViewView.Columns.Add("FlagsEnum2", flagsEnum2ViewColumn); var idViewColumn = new ViewColumn("Id", "bigint", principalBaseViewView); principalBaseViewView.Columns.Add("Id", idViewColumn); + var owned_NumberViewColumn = new ViewColumn("Owned_Number", "int", principalBaseViewView); + principalBaseViewView.Columns.Add("Owned_Number", owned_NumberViewColumn); + var owned_Principal_AlternateIdViewColumn = new ViewColumn("Owned_Principal_AlternateId", "uniqueidentifier", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_Principal_AlternateId", owned_Principal_AlternateIdViewColumn); + var owned_Principal_Enum1ViewColumn = new ViewColumn("Owned_Principal_Enum1", "int", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_Principal_Enum1", owned_Principal_Enum1ViewColumn); + var owned_Principal_Enum2ViewColumn = new ViewColumn("Owned_Principal_Enum2", "int", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_Principal_Enum2", owned_Principal_Enum2ViewColumn); + var owned_Principal_FlagsEnum1ViewColumn = new ViewColumn("Owned_Principal_FlagsEnum1", "int", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_Principal_FlagsEnum1", owned_Principal_FlagsEnum1ViewColumn); + var owned_Principal_FlagsEnum2ViewColumn = new ViewColumn("Owned_Principal_FlagsEnum2", "int", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_Principal_FlagsEnum2", owned_Principal_FlagsEnum2ViewColumn); + var owned_Principal_IdViewColumn = new ViewColumn("Owned_Principal_Id", "bigint", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_Principal_Id", owned_Principal_IdViewColumn); + var owned_Principal_RefTypeArrayViewColumn = new ViewColumn("Owned_Principal_RefTypeArray", "nvarchar(max)", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_Principal_RefTypeArray", owned_Principal_RefTypeArrayViewColumn); + var owned_Principal_RefTypeEnumerableViewColumn = new ViewColumn("Owned_Principal_RefTypeEnumerable", "nvarchar(max)", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_Principal_RefTypeEnumerable", owned_Principal_RefTypeEnumerableViewColumn); + var owned_Principal_RefTypeIListViewColumn = new ViewColumn("Owned_Principal_RefTypeIList", "nvarchar(max)", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_Principal_RefTypeIList", owned_Principal_RefTypeIListViewColumn); + var owned_Principal_RefTypeListViewColumn = new ViewColumn("Owned_Principal_RefTypeList", "nvarchar(max)", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_Principal_RefTypeList", owned_Principal_RefTypeListViewColumn); + var owned_Principal_ValueTypeArrayViewColumn = new ViewColumn("Owned_Principal_ValueTypeArray", "nvarchar(max)", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_Principal_ValueTypeArray", owned_Principal_ValueTypeArrayViewColumn); + var owned_Principal_ValueTypeEnumerableViewColumn = new ViewColumn("Owned_Principal_ValueTypeEnumerable", "nvarchar(max)", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_Principal_ValueTypeEnumerable", owned_Principal_ValueTypeEnumerableViewColumn); + var owned_Principal_ValueTypeIListViewColumn = new ViewColumn("Owned_Principal_ValueTypeIList", "nvarchar(max)", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_Principal_ValueTypeIList", owned_Principal_ValueTypeIListViewColumn); + var owned_Principal_ValueTypeListViewColumn = new ViewColumn("Owned_Principal_ValueTypeList", "nvarchar(max)", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_Principal_ValueTypeList", owned_Principal_ValueTypeListViewColumn); + var owned_RefTypeArrayViewColumn = new ViewColumn("Owned_RefTypeArray", "nvarchar(max)", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_RefTypeArray", owned_RefTypeArrayViewColumn); + var owned_RefTypeEnumerableViewColumn = new ViewColumn("Owned_RefTypeEnumerable", "nvarchar(max)", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_RefTypeEnumerable", owned_RefTypeEnumerableViewColumn); + var owned_RefTypeIListViewColumn = new ViewColumn("Owned_RefTypeIList", "nvarchar(max)", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_RefTypeIList", owned_RefTypeIListViewColumn); + var owned_RefTypeListViewColumn = new ViewColumn("Owned_RefTypeList", "nvarchar(max)", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_RefTypeList", owned_RefTypeListViewColumn); + var owned_ValueTypeArrayViewColumn = new ViewColumn("Owned_ValueTypeArray", "nvarchar(max)", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_ValueTypeArray", owned_ValueTypeArrayViewColumn); + var owned_ValueTypeEnumerableViewColumn = new ViewColumn("Owned_ValueTypeEnumerable", "nvarchar(max)", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_ValueTypeEnumerable", owned_ValueTypeEnumerableViewColumn); + var owned_ValueTypeIListViewColumn = new ViewColumn("Owned_ValueTypeIList", "nvarchar(max)", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_ValueTypeIList", owned_ValueTypeIListViewColumn); + var owned_ValueTypeListViewColumn = new ViewColumn("Owned_ValueTypeList", "nvarchar(max)", principalBaseViewView) + { + IsNullable = true + }; + principalBaseViewView.Columns.Add("Owned_ValueTypeList", owned_ValueTypeListViewColumn); var principalBaseIdViewColumn = new ViewColumn("PrincipalBaseId", "bigint", principalBaseViewView) { IsNullable = true @@ -1094,6 +1211,22 @@ private IRelationalModel CreateRelationalModel() RelationalModel.CreateColumnMapping(owned_ValueTypeIListColumn, ownedType.FindProperty("ValueTypeIList")!, principalBaseTableMapping0); RelationalModel.CreateColumnMapping(owned_ValueTypeListColumn, ownedType.FindProperty("ValueTypeList")!, principalBaseTableMapping0); + var viewMappings0 = new List(); + ownedType.SetRuntimeAnnotation("Relational:ViewMappings", viewMappings0); + var principalBaseViewViewMapping0 = new ViewMapping(ownedType, principalBaseViewView, true); + principalBaseViewView.AddTypeMapping(principalBaseViewViewMapping0, false); + viewMappings0.Add(principalBaseViewViewMapping0); + RelationalModel.CreateViewColumnMapping(deetsViewColumn, ownedType.FindProperty("Details")!, principalBaseViewViewMapping0); + RelationalModel.CreateViewColumnMapping(owned_NumberViewColumn, ownedType.FindProperty("Number")!, principalBaseViewViewMapping0); + RelationalModel.CreateViewColumnMapping(owned_RefTypeArrayViewColumn, ownedType.FindProperty("RefTypeArray")!, principalBaseViewViewMapping0); + RelationalModel.CreateViewColumnMapping(owned_RefTypeEnumerableViewColumn, ownedType.FindProperty("RefTypeEnumerable")!, principalBaseViewViewMapping0); + RelationalModel.CreateViewColumnMapping(owned_RefTypeIListViewColumn, ownedType.FindProperty("RefTypeIList")!, principalBaseViewViewMapping0); + RelationalModel.CreateViewColumnMapping(owned_RefTypeListViewColumn, ownedType.FindProperty("RefTypeList")!, principalBaseViewViewMapping0); + RelationalModel.CreateViewColumnMapping(owned_ValueTypeArrayViewColumn, ownedType.FindProperty("ValueTypeArray")!, principalBaseViewViewMapping0); + RelationalModel.CreateViewColumnMapping(owned_ValueTypeEnumerableViewColumn, ownedType.FindProperty("ValueTypeEnumerable")!, principalBaseViewViewMapping0); + RelationalModel.CreateViewColumnMapping(owned_ValueTypeIListViewColumn, ownedType.FindProperty("ValueTypeIList")!, principalBaseViewViewMapping0); + RelationalModel.CreateViewColumnMapping(owned_ValueTypeListViewColumn, ownedType.FindProperty("ValueTypeList")!, principalBaseViewViewMapping0); + var principalBase0 = ownedType.FindComplexProperty("Principal")!.ComplexType; var defaultTableMappings1 = new List>(); @@ -1136,6 +1269,26 @@ private IRelationalModel CreateRelationalModel() RelationalModel.CreateColumnMapping(owned_Principal_ValueTypeIListColumn, principalBase0.FindProperty("ValueTypeIList")!, principalBaseTableMapping1); RelationalModel.CreateColumnMapping(owned_Principal_ValueTypeListColumn, principalBase0.FindProperty("ValueTypeList")!, principalBaseTableMapping1); + var viewMappings1 = new List(); + principalBase0.SetRuntimeAnnotation("Relational:ViewMappings", viewMappings1); + var principalBaseViewViewMapping1 = new ViewMapping(principalBase0, principalBaseViewView, true); + principalBaseViewView.AddTypeMapping(principalBaseViewViewMapping1, true); + viewMappings1.Add(principalBaseViewViewMapping1); + RelationalModel.CreateViewColumnMapping(owned_Principal_AlternateIdViewColumn, principalBase0.FindProperty("AlternateId")!, principalBaseViewViewMapping1); + RelationalModel.CreateViewColumnMapping(owned_Principal_Enum1ViewColumn, principalBase0.FindProperty("Enum1")!, principalBaseViewViewMapping1); + RelationalModel.CreateViewColumnMapping(owned_Principal_Enum2ViewColumn, principalBase0.FindProperty("Enum2")!, principalBaseViewViewMapping1); + RelationalModel.CreateViewColumnMapping(owned_Principal_FlagsEnum1ViewColumn, principalBase0.FindProperty("FlagsEnum1")!, principalBaseViewViewMapping1); + RelationalModel.CreateViewColumnMapping(owned_Principal_FlagsEnum2ViewColumn, principalBase0.FindProperty("FlagsEnum2")!, principalBaseViewViewMapping1); + RelationalModel.CreateViewColumnMapping(owned_Principal_IdViewColumn, principalBase0.FindProperty("Id")!, principalBaseViewViewMapping1); + RelationalModel.CreateViewColumnMapping(owned_Principal_RefTypeArrayViewColumn, principalBase0.FindProperty("RefTypeArray")!, principalBaseViewViewMapping1); + RelationalModel.CreateViewColumnMapping(owned_Principal_RefTypeEnumerableViewColumn, principalBase0.FindProperty("RefTypeEnumerable")!, principalBaseViewViewMapping1); + RelationalModel.CreateViewColumnMapping(owned_Principal_RefTypeIListViewColumn, principalBase0.FindProperty("RefTypeIList")!, principalBaseViewViewMapping1); + RelationalModel.CreateViewColumnMapping(owned_Principal_RefTypeListViewColumn, principalBase0.FindProperty("RefTypeList")!, principalBaseViewViewMapping1); + RelationalModel.CreateViewColumnMapping(owned_Principal_ValueTypeArrayViewColumn, principalBase0.FindProperty("ValueTypeArray")!, principalBaseViewViewMapping1); + RelationalModel.CreateViewColumnMapping(owned_Principal_ValueTypeEnumerableViewColumn, principalBase0.FindProperty("ValueTypeEnumerable")!, principalBaseViewViewMapping1); + RelationalModel.CreateViewColumnMapping(owned_Principal_ValueTypeIListViewColumn, principalBase0.FindProperty("ValueTypeIList")!, principalBaseViewViewMapping1); + RelationalModel.CreateViewColumnMapping(owned_Principal_ValueTypeListViewColumn, principalBase0.FindProperty("ValueTypeList")!, principalBaseViewViewMapping1); + var principalDerived = FindEntityType("Microsoft.EntityFrameworkCore.Scaffolding.CompiledModelTestBase+PrincipalDerived>")!; var defaultTableMappings2 = new List>();