diff --git a/test/EFCore.Specification.Tests/CustomConvertersTestBase.cs b/test/EFCore.Specification.Tests/CustomConvertersTestBase.cs index 086e8160bb2..f450c1891e5 100644 --- a/test/EFCore.Specification.Tests/CustomConvertersTestBase.cs +++ b/test/EFCore.Specification.Tests/CustomConvertersTestBase.cs @@ -4,6 +4,7 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.ChangeTracking; using Microsoft.EntityFrameworkCore.Diagnostics; @@ -767,6 +768,41 @@ public override int GetHashCode() => Id.GetHashCode(); } + [ConditionalFact] + public virtual void Composition_over_collection_of_complex_mapped_as_scalar() + { + using var context = CreateContext(); + Assert.Equal( + CoreStrings.TranslationFailed( + @"l => new { H = l.Height, W = l.Width }"), + Assert.Throws( + () => context.Set().AsNoTracking().Select(d => new + { + Id = d.Id, + Name = d.Name, + Layouts = d.Layouts.Select(l => new { H = l.Height, W = l.Width }).ToList() + }).ToList()) + .Message.Replace("\r", "").Replace("\n", "")); + } + + public class Dashboard + { + public Dashboard() + { + Layouts = new List(); + } + + public int Id { get; set; } + public string Name { get; set; } + public List Layouts { get; set; } + } + + public class Layout + { + public int Width { get; set; } + public int Height { get; set; } + } + public abstract class CustomConvertersFixtureBase : BuiltInDataTypesFixtureBase { protected override string StoreName { get; } = "CustomConverters"; @@ -1269,6 +1305,15 @@ protected override void OnModelCreating(ModelBuilder modelBuilder, DbContext con new User23059 { Id = 1, IsSoftDeleted = true, MessageGroups = new List { MessageGroup.SomeGroup } }, new User23059 { Id = 2, IsSoftDeleted = false, MessageGroups = new List { MessageGroup.SomeGroup } }); }); + + modelBuilder.Entity() + .Property(e => e.Layouts).HasConversion( + v => LayoutsToStringSerializer.Serialize(v), + v => LayoutsToStringSerializer.Deserialize(v), + new ValueComparer>( + (v1, v2) => v1.SequenceEqual(v2), + v => v.GetHashCode(), + v => new List(v))); } private static class StringToDictionarySerializer @@ -1291,6 +1336,30 @@ public static IDictionary Deserialize(string s) return dictionary; } } + private static class LayoutsToStringSerializer + { + public static string Serialize(List layouts) + { + return string.Join(Environment.NewLine, layouts.Select(layout => $"({layout.Height},{layout.Width})")); + } + + public static List Deserialize(string s) + { + var list = new List(); + var keyValuePairs = s.Split(Environment.NewLine, StringSplitOptions.RemoveEmptyEntries); + foreach (var keyValuePair in keyValuePairs) + { + var parts = keyValuePair[1..^1].Split(","); + list.Add(new Layout + { + Height = int.Parse(parts[0]), + Width = int.Parse(parts[1]), + }); + } + + return list; + } + } private class OrderIdEntityFrameworkValueConverter : ValueConverter {