From cda096e938ba486a87e69eaaf93a585b500fabf3 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Mon, 23 Aug 2021 19:35:13 +0200 Subject: [PATCH] Support value conversion for ReadOnlyIPAddress (#25587) Fixes #21159 --- .../ValueConversion/ValueConverterSelector.cs | 4 +- .../Query/GearsOfWarQueryInMemoryTest.cs | 4 ++ .../Query/GearsOfWarQueryTestBase.cs | 10 +++++ .../TestModels/GearsOfWarModel/Faction.cs | 3 ++ .../Query/GearsOfWarQuerySqlServerTest.cs | 38 ++++++++++++------- .../Query/TPTGearsOfWarQuerySqlServerTest.cs | 28 +++++++------- .../Storage/ValueConverterSelectorTest.cs | 8 ++++ 7 files changed, 66 insertions(+), 29 deletions(-) diff --git a/src/EFCore/Storage/ValueConversion/ValueConverterSelector.cs b/src/EFCore/Storage/ValueConversion/ValueConverterSelector.cs index c329456f9a7..02e98531199 100644 --- a/src/EFCore/Storage/ValueConversion/ValueConverterSelector.cs +++ b/src/EFCore/Storage/ValueConversion/ValueConverterSelector.cs @@ -58,6 +58,8 @@ public class ValueConverterSelector : IValueConverterSelector typeof(float) }; + private static readonly Type? _readOnlyIPAddressType = IPAddress.Loopback.GetType(); + /// /// Initializes a new instance of the class. /// @@ -291,7 +293,7 @@ public virtual IEnumerable Select( NumberToBytesConverter.DefaultInfo.MappingHints)); } } - else if (modelClrType == typeof(IPAddress)) + else if (modelClrType == typeof(IPAddress) || modelClrType == _readOnlyIPAddressType) { if (providerClrType == null || providerClrType == typeof(string)) diff --git a/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs b/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs index e52560d87d0..ed438ebe77e 100644 --- a/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs +++ b/test/EFCore.InMemory.FunctionalTests/Query/GearsOfWarQueryInMemoryTest.cs @@ -55,6 +55,10 @@ public override Task Projecting_entity_as_well_as_correlated_collection_of_scala public override Task Correlated_collection_with_distinct_3_levels(bool async) => base.Correlated_collection_with_distinct_3_levels(async); + [ConditionalTheory(Skip = "Issue #25615")] + public override Task Comparison_with_value_converted_subclass(bool async) + => base.Comparison_with_value_converted_subclass(async); + public override async Task Projecting_correlated_collection_followed_by_Distinct(bool async) { var message = (await Assert.ThrowsAsync( diff --git a/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs b/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs index 2374fc3ed5e..ee21cd42a2f 100644 --- a/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs +++ b/test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; +using System.Net; using System.Threading.Tasks; using Microsoft.EntityFrameworkCore.Diagnostics; using Microsoft.EntityFrameworkCore.Diagnostics.Internal; @@ -8997,6 +8998,15 @@ public virtual Task Include_on_entity_that_is_not_present_in_final_projection_bu }); } + [ConditionalTheory] + [MemberData(nameof(IsAsyncData))] + public virtual Task Comparison_with_value_converted_subclass(bool async) + { + return AssertQuery( + async, + ss => ss.Set().Where(f => f.ServerAddress == IPAddress.Loopback)); + } + protected GearsOfWarContext CreateContext() => Fixture.CreateContext(); diff --git a/test/EFCore.Specification.Tests/TestModels/GearsOfWarModel/Faction.cs b/test/EFCore.Specification.Tests/TestModels/GearsOfWarModel/Faction.cs index 3a68f6a65d2..c878dde59ae 100644 --- a/test/EFCore.Specification.Tests/TestModels/GearsOfWarModel/Faction.cs +++ b/test/EFCore.Specification.Tests/TestModels/GearsOfWarModel/Faction.cs @@ -1,12 +1,15 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Net; + namespace Microsoft.EntityFrameworkCore.TestModels.GearsOfWarModel { public abstract class Faction { public int Id { get; set; } public string Name { get; set; } + public IPAddress ServerAddress { get; set; } public string CapitalName { get; set; } public City Capital { get; set; } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs index 34a2f65fa36..b9e8335fbb8 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/GearsOfWarQuerySqlServerTest.cs @@ -3088,7 +3088,7 @@ public override async Task Member_access_on_derived_materialized_entity_using_ca await base.Member_access_on_derived_materialized_entity_using_cast(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated] + @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[ServerAddress], [f].[CommanderName], [f].[Eradicated] FROM [Factions] AS [f] ORDER BY [f].[Name]"); } @@ -3133,7 +3133,7 @@ public override async Task Navigation_access_on_derived_materialized_entity_usin await base.Navigation_access_on_derived_materialized_entity_using_cast(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated], [t].[ThreatLevel] AS [Threat] + @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[ServerAddress], [f].[CommanderName], [f].[Eradicated], [t].[ThreatLevel] AS [Threat] FROM [Factions] AS [f] LEFT JOIN ( SELECT [l].[Name], [l].[ThreatLevel] @@ -3202,7 +3202,7 @@ public override async Task Include_on_derived_entity_using_OfType(bool async) await base.Include_on_derived_entity_using_OfType(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[ThreatLevelByte], [t].[ThreatLevelNullableByte], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [l0].[Name], [l0].[Discriminator], [l0].[LocustHordeId], [l0].[ThreatLevel], [l0].[ThreatLevelByte], [l0].[ThreatLevelNullableByte], [l0].[DefeatedByNickname], [l0].[DefeatedBySquadId], [l0].[HighCommandId] + @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[ServerAddress], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[ThreatLevelByte], [t].[ThreatLevelNullableByte], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [l0].[Name], [l0].[Discriminator], [l0].[LocustHordeId], [l0].[ThreatLevel], [l0].[ThreatLevelByte], [l0].[ThreatLevelNullableByte], [l0].[DefeatedByNickname], [l0].[DefeatedBySquadId], [l0].[HighCommandId] FROM [Factions] AS [f] LEFT JOIN ( SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[ThreatLevelByte], [l].[ThreatLevelNullableByte], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId] @@ -3512,7 +3512,7 @@ public override async Task ThenInclude_collection_on_derived_after_derived_refer await base.ThenInclude_collection_on_derived_after_derived_reference(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[ThreatLevelByte], [t].[ThreatLevelNullableByte], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOfBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank] + @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[ServerAddress], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[ThreatLevelByte], [t].[ThreatLevelNullableByte], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOfBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank] FROM [Factions] AS [f] LEFT JOIN ( SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[ThreatLevelByte], [l].[ThreatLevelNullableByte], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId] @@ -3544,7 +3544,7 @@ public override async Task ThenInclude_reference_on_derived_after_derived_collec await base.ThenInclude_reference_on_derived_after_derived_collection(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[ThreatLevelByte], [t].[ThreatLevelNullableByte], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOfBirthName], [t].[Discriminator0], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] + @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[ServerAddress], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[ThreatLevelByte], [t].[ThreatLevelNullableByte], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [t].[Nickname], [t].[SquadId], [t].[AssignedCityName], [t].[CityOfBirthName], [t].[Discriminator0], [t].[FullName], [t].[HasSoulPatch], [t].[LeaderNickname], [t].[LeaderSquadId], [t].[Rank] FROM [Factions] AS [f] LEFT JOIN ( SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[ThreatLevelByte], [l].[ThreatLevelNullableByte], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId], [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator] AS [Discriminator0], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank] @@ -3559,7 +3559,7 @@ public override async Task Multiple_derived_included_on_one_method(bool async) await base.Multiple_derived_included_on_one_method(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[ThreatLevelByte], [t].[ThreatLevelNullableByte], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOfBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank] + @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[ServerAddress], [f].[CommanderName], [f].[Eradicated], [t].[Name], [t].[Discriminator], [t].[LocustHordeId], [t].[ThreatLevel], [t].[ThreatLevelByte], [t].[ThreatLevelNullableByte], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [g].[Nickname], [g].[SquadId], [g].[AssignedCityName], [g].[CityOfBirthName], [g].[Discriminator], [g].[FullName], [g].[HasSoulPatch], [g].[LeaderNickname], [g].[LeaderSquadId], [g].[Rank], [g0].[Nickname], [g0].[SquadId], [g0].[AssignedCityName], [g0].[CityOfBirthName], [g0].[Discriminator], [g0].[FullName], [g0].[HasSoulPatch], [g0].[LeaderNickname], [g0].[LeaderSquadId], [g0].[Rank] FROM [Factions] AS [f] LEFT JOIN ( SELECT [l].[Name], [l].[Discriminator], [l].[LocustHordeId], [l].[ThreatLevel], [l].[ThreatLevelByte], [l].[ThreatLevelNullableByte], [l].[DefeatedByNickname], [l].[DefeatedBySquadId], [l].[HighCommandId] @@ -4511,10 +4511,10 @@ public override async Task Null_semantics_on_nullable_bool_from_inner_join_subqu await base.Null_semantics_on_nullable_bool_from_inner_join_subquery_is_fully_applied(async); AssertSql( - @"SELECT [t].[Id], [t].[CapitalName], [t].[Discriminator], [t].[Name], [t].[CommanderName], [t].[Eradicated] + @"SELECT [t].[Id], [t].[CapitalName], [t].[Discriminator], [t].[Name], [t].[ServerAddress], [t].[CommanderName], [t].[Eradicated] FROM [LocustLeaders] AS [l] INNER JOIN ( - SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated] + SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[ServerAddress], [f].[CommanderName], [f].[Eradicated] FROM [Factions] AS [f] WHERE [f].[Name] = N'Swarm' ) AS [t] ON [l].[Name] = [t].[CommanderName] @@ -4526,10 +4526,10 @@ public override async Task Null_semantics_on_nullable_bool_from_left_join_subque await base.Null_semantics_on_nullable_bool_from_left_join_subquery_is_fully_applied(async); AssertSql( - @"SELECT [t].[Id], [t].[CapitalName], [t].[Discriminator], [t].[Name], [t].[CommanderName], [t].[Eradicated] + @"SELECT [t].[Id], [t].[CapitalName], [t].[Discriminator], [t].[Name], [t].[ServerAddress], [t].[CommanderName], [t].[Eradicated] FROM [LocustLeaders] AS [l] LEFT JOIN ( - SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated] + SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[ServerAddress], [f].[CommanderName], [f].[Eradicated] FROM [Factions] AS [f] WHERE [f].[Name] = N'Swarm' ) AS [t] ON [l].[Name] = [t].[CommanderName] @@ -5902,7 +5902,7 @@ public override async Task Nav_rewrite_with_convert2(bool async) await base.Nav_rewrite_with_convert2(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated] + @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[ServerAddress], [f].[CommanderName], [f].[Eradicated] FROM [Factions] AS [f] LEFT JOIN [Cities] AS [c] ON [f].[CapitalName] = [c].[Name] LEFT JOIN ( @@ -5918,7 +5918,7 @@ public override async Task Nav_rewrite_with_convert3(bool async) await base.Nav_rewrite_with_convert3(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated] + @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[ServerAddress], [f].[CommanderName], [f].[Eradicated] FROM [Factions] AS [f] LEFT JOIN [Cities] AS [c] ON [f].[CapitalName] = [c].[Name] LEFT JOIN ( @@ -6163,7 +6163,7 @@ public override async Task Navigation_based_on_complex_expression2(bool async) await base.Navigation_based_on_complex_expression2(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated] + @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[ServerAddress], [f].[CommanderName], [f].[Eradicated] FROM [Factions] AS [f] LEFT JOIN ( SELECT [l].[Name] @@ -6597,7 +6597,7 @@ public override async Task FirstOrDefault_navigation_access_entity_equality_in_w await base.FirstOrDefault_navigation_access_entity_equality_in_where_predicate_apply_peneding_selector(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[CommanderName], [f].[Eradicated] + @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[ServerAddress], [f].[CommanderName], [f].[Eradicated] FROM [Factions] AS [f] LEFT JOIN [Cities] AS [c] ON [f].[CapitalName] = [c].[Name] WHERE ([c].[Name] = ( @@ -8154,6 +8154,16 @@ END AS [IsOfficer] FROM [Gears] AS [g]"); } + public override async Task Comparison_with_value_converted_subclass(bool async) + { + await base.Comparison_with_value_converted_subclass(async); + + AssertSql( + @"SELECT [f].[Id], [f].[CapitalName], [f].[Discriminator], [f].[Name], [f].[ServerAddress], [f].[CommanderName], [f].[Eradicated] +FROM [Factions] AS [f] +WHERE [f].[ServerAddress] = CAST(N'127.0.0.1' AS nvarchar(45))"); + } + private void AssertSql(params string[] expected) => Fixture.TestSqlLoggerFactory.AssertBaseline(expected); } diff --git a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs index 7fc21c48354..72515653cf6 100644 --- a/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs +++ b/test/EFCore.SqlServer.FunctionalTests/Query/TPTGearsOfWarQuerySqlServerTest.cs @@ -3614,7 +3614,7 @@ public override async Task Member_access_on_derived_materialized_entity_using_ca await base.Member_access_on_derived_materialized_entity_using_cast(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [l].[CommanderName], [l].[Eradicated], CASE + @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [f].[ServerAddress], [l].[CommanderName], [l].[Eradicated], CASE WHEN [l].[Id] IS NOT NULL THEN N'LocustHorde' END AS [Discriminator] FROM [Factions] AS [f] @@ -3669,7 +3669,7 @@ public override async Task Navigation_access_on_derived_materialized_entity_usin await base.Navigation_access_on_derived_materialized_entity_using_cast(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [l].[CommanderName], [l].[Eradicated], CASE + @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [f].[ServerAddress], [l].[CommanderName], [l].[Eradicated], CASE WHEN [l].[Id] IS NOT NULL THEN N'LocustHorde' END AS [Discriminator], [t].[ThreatLevel] AS [Threat] FROM [Factions] AS [f] @@ -3754,7 +3754,7 @@ public override async Task Include_on_derived_entity_using_OfType(bool async) await base.Include_on_derived_entity_using_OfType(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [l].[CommanderName], [l].[Eradicated], CASE + @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [f].[ServerAddress], [l].[CommanderName], [l].[Eradicated], CASE WHEN [l].[Id] IS NOT NULL THEN N'LocustHorde' END AS [Discriminator], [t].[Name], [t].[LocustHordeId], [t].[ThreatLevel], [t].[ThreatLevelByte], [t].[ThreatLevelNullableByte], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [t0].[Name], [t0].[LocustHordeId], [t0].[ThreatLevel], [t0].[ThreatLevelByte], [t0].[ThreatLevelNullableByte], [t0].[DefeatedByNickname], [t0].[DefeatedBySquadId], [t0].[HighCommandId], [t0].[Discriminator] FROM [Factions] AS [f] @@ -4228,7 +4228,7 @@ public override async Task ThenInclude_collection_on_derived_after_derived_refer await base.ThenInclude_collection_on_derived_after_derived_reference(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [l].[CommanderName], [l].[Eradicated], CASE + @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [f].[ServerAddress], [l].[CommanderName], [l].[Eradicated], CASE WHEN [l].[Id] IS NOT NULL THEN N'LocustHorde' END AS [Discriminator], [t].[Name], [t].[LocustHordeId], [t].[ThreatLevel], [t].[ThreatLevelByte], [t].[ThreatLevelNullableByte], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOfBirthName], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank], [t0].[Discriminator], [t1].[Nickname], [t1].[SquadId], [t1].[AssignedCityName], [t1].[CityOfBirthName], [t1].[FullName], [t1].[HasSoulPatch], [t1].[LeaderNickname], [t1].[LeaderSquadId], [t1].[Rank], [t1].[Discriminator] FROM [Factions] AS [f] @@ -4287,7 +4287,7 @@ public override async Task ThenInclude_reference_on_derived_after_derived_collec await base.ThenInclude_reference_on_derived_after_derived_collection(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [l].[CommanderName], [l].[Eradicated], CASE + @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [f].[ServerAddress], [l].[CommanderName], [l].[Eradicated], CASE WHEN [l].[Id] IS NOT NULL THEN N'LocustHorde' END AS [Discriminator], [t0].[Name], [t0].[LocustHordeId], [t0].[ThreatLevel], [t0].[ThreatLevelByte], [t0].[ThreatLevelNullableByte], [t0].[DefeatedByNickname], [t0].[DefeatedBySquadId], [t0].[HighCommandId], [t0].[Discriminator], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOfBirthName], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank], [t0].[Discriminator0] FROM [Factions] AS [f] @@ -4314,7 +4314,7 @@ public override async Task Multiple_derived_included_on_one_method(bool async) await base.Multiple_derived_included_on_one_method(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [l].[CommanderName], [l].[Eradicated], CASE + @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [f].[ServerAddress], [l].[CommanderName], [l].[Eradicated], CASE WHEN [l].[Id] IS NOT NULL THEN N'LocustHorde' END AS [Discriminator], [t].[Name], [t].[LocustHordeId], [t].[ThreatLevel], [t].[ThreatLevelByte], [t].[ThreatLevelNullableByte], [t].[DefeatedByNickname], [t].[DefeatedBySquadId], [t].[HighCommandId], [t0].[Nickname], [t0].[SquadId], [t0].[AssignedCityName], [t0].[CityOfBirthName], [t0].[FullName], [t0].[HasSoulPatch], [t0].[LeaderNickname], [t0].[LeaderSquadId], [t0].[Rank], [t0].[Discriminator], [t1].[Nickname], [t1].[SquadId], [t1].[AssignedCityName], [t1].[CityOfBirthName], [t1].[FullName], [t1].[HasSoulPatch], [t1].[LeaderNickname], [t1].[LeaderSquadId], [t1].[Rank], [t1].[Discriminator] FROM [Factions] AS [f] @@ -5349,10 +5349,10 @@ public override async Task Null_semantics_on_nullable_bool_from_inner_join_subqu await base.Null_semantics_on_nullable_bool_from_inner_join_subquery_is_fully_applied(async); AssertSql( - @"SELECT [t].[Id], [t].[CapitalName], [t].[Name], [t].[CommanderName], [t].[Eradicated], [t].[Discriminator] + @"SELECT [t].[Id], [t].[CapitalName], [t].[Name], [t].[ServerAddress], [t].[CommanderName], [t].[Eradicated], [t].[Discriminator] FROM [LocustLeaders] AS [l] INNER JOIN ( - SELECT [f].[Id], [f].[CapitalName], [f].[Name], [l1].[CommanderName], [l1].[Eradicated], CASE + SELECT [f].[Id], [f].[CapitalName], [f].[Name], [f].[ServerAddress], [l1].[CommanderName], [l1].[Eradicated], CASE WHEN [l1].[Id] IS NOT NULL THEN N'LocustHorde' END AS [Discriminator] FROM [Factions] AS [f] @@ -5367,10 +5367,10 @@ public override async Task Null_semantics_on_nullable_bool_from_left_join_subque await base.Null_semantics_on_nullable_bool_from_left_join_subquery_is_fully_applied(async); AssertSql( - @"SELECT [t].[Id], [t].[CapitalName], [t].[Name], [t].[CommanderName], [t].[Eradicated], [t].[Discriminator] + @"SELECT [t].[Id], [t].[CapitalName], [t].[Name], [t].[ServerAddress], [t].[CommanderName], [t].[Eradicated], [t].[Discriminator] FROM [LocustLeaders] AS [l] LEFT JOIN ( - SELECT [f].[Id], [f].[CapitalName], [f].[Name], [l1].[CommanderName], [l1].[Eradicated], CASE + SELECT [f].[Id], [f].[CapitalName], [f].[Name], [f].[ServerAddress], [l1].[CommanderName], [l1].[Eradicated], CASE WHEN [l1].[Id] IS NOT NULL THEN N'LocustHorde' END AS [Discriminator] FROM [Factions] AS [f] @@ -6881,7 +6881,7 @@ public override async Task Nav_rewrite_with_convert2(bool async) await base.Nav_rewrite_with_convert2(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [l].[CommanderName], [l].[Eradicated], CASE + @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [f].[ServerAddress], [l].[CommanderName], [l].[Eradicated], CASE WHEN [l].[Id] IS NOT NULL THEN N'LocustHorde' END AS [Discriminator] FROM [Factions] AS [f] @@ -6900,7 +6900,7 @@ public override async Task Nav_rewrite_with_convert3(bool async) await base.Nav_rewrite_with_convert3(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [l].[CommanderName], [l].[Eradicated], CASE + @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [f].[ServerAddress], [l].[CommanderName], [l].[Eradicated], CASE WHEN [l].[Id] IS NOT NULL THEN N'LocustHorde' END AS [Discriminator] FROM [Factions] AS [f] @@ -7171,7 +7171,7 @@ public override async Task Navigation_based_on_complex_expression2(bool async) await base.Navigation_based_on_complex_expression2(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [l].[CommanderName], [l].[Eradicated], CASE + @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [f].[ServerAddress], [l].[CommanderName], [l].[Eradicated], CASE WHEN [l].[Id] IS NOT NULL THEN N'LocustHorde' END AS [Discriminator] FROM [Factions] AS [f] @@ -7669,7 +7669,7 @@ public override async Task FirstOrDefault_navigation_access_entity_equality_in_w await base.FirstOrDefault_navigation_access_entity_equality_in_where_predicate_apply_peneding_selector(async); AssertSql( - @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [l].[CommanderName], [l].[Eradicated], CASE + @"SELECT [f].[Id], [f].[CapitalName], [f].[Name], [f].[ServerAddress], [l].[CommanderName], [l].[Eradicated], CASE WHEN [l].[Id] IS NOT NULL THEN N'LocustHorde' END AS [Discriminator] FROM [Factions] AS [f] diff --git a/test/EFCore.Tests/Storage/ValueConverterSelectorTest.cs b/test/EFCore.Tests/Storage/ValueConverterSelectorTest.cs index 9ecf1f6c87d..055ee6e187c 100644 --- a/test/EFCore.Tests/Storage/ValueConverterSelectorTest.cs +++ b/test/EFCore.Tests/Storage/ValueConverterSelectorTest.cs @@ -704,6 +704,10 @@ public void Can_get_converters_for_IPAddress_to_string() AssertConverters( _selector.Select(typeof(IPAddress), typeof(string)).ToList(), (typeof(IPAddressToStringConverter), new ConverterMappingHints(size: 45))); + + AssertConverters( + _selector.Select(IPAddress.Loopback.GetType(), typeof(string)).ToList(), + (typeof(IPAddressToStringConverter), new ConverterMappingHints(size: 45))); } [ConditionalFact] @@ -712,6 +716,10 @@ public void Can_get_converters_for_IPAddress_to_bytes() AssertConverters( _selector.Select(typeof(IPAddress), typeof(byte[])).ToList(), (typeof(IPAddressToBytesConverter), new ConverterMappingHints(size: 16))); + + AssertConverters( + _selector.Select(IPAddress.Loopback.GetType(), typeof(byte[])).ToList(), + (typeof(IPAddressToBytesConverter), new ConverterMappingHints(size: 16))); } private static void AssertConverters(