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/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs index c4d4cac1cef..345d7f2b541 100644 --- a/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs +++ b/src/EFCore.Relational/Query/RelationalQueryableMethodTranslatingExpressionVisitor.ExecuteUpdate.cs @@ -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()) @@ -473,8 +473,7 @@ void ProcessColumn(ColumnExpression column) targetColumnModel = complexType.ContainingEntityType.GetTableMappings() .SelectMany(m => m.Table.Columns) .Where(c => c.Name == containerColumnName) - .Single(); - + .SingleOrDefault(); break; } @@ -510,14 +509,17 @@ 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()) { + 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.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/BulkUpdates/NonSharedModelBulkUpdatesSqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqlServerTest.cs index dbd19852f1b..79db8e7e787 100644 --- a/test/EFCore.SqlServer.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/BulkUpdates/NonSharedModelBulkUpdatesSqlServerTest.cs @@ -227,8 +227,31 @@ 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) + { + await base.Update_complex_type_property_with_view_mapping(async); + + AssertSql( + """ +@p='6' + +UPDATE [b] +SET [b].[ComplexThing_Prop1] = @p +FROM [Blogs] AS [b] +"""); } private void AssertSql(params string[] expected) 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(); 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>(); 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)