Skip to content

Commit

Permalink
Support value conversion for ReadOnlyIPAddress (#25587)
Browse files Browse the repository at this point in the history
Fixes #21159
  • Loading branch information
roji authored Aug 23, 2021
1 parent a42a71f commit cda096e
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 29 deletions.
4 changes: 3 additions & 1 deletion src/EFCore/Storage/ValueConversion/ValueConverterSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ public class ValueConverterSelector : IValueConverterSelector
typeof(float)
};

private static readonly Type? _readOnlyIPAddressType = IPAddress.Loopback.GetType();

/// <summary>
/// Initializes a new instance of the <see cref="ValueConverterSelector" /> class.
/// </summary>
Expand Down Expand Up @@ -291,7 +293,7 @@ public virtual IEnumerable<ValueConverterInfo> Select(
NumberToBytesConverter<long>.DefaultInfo.MappingHints));
}
}
else if (modelClrType == typeof(IPAddress))
else if (modelClrType == typeof(IPAddress) || modelClrType == _readOnlyIPAddressType)
{
if (providerClrType == null
|| providerClrType == typeof(string))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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<InvalidOperationException>(
Expand Down
10 changes: 10 additions & 0 deletions test/EFCore.Specification.Tests/Query/GearsOfWarQueryTestBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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<Faction>().Where(f => f.ServerAddress == IPAddress.Loopback));
}

protected GearsOfWarContext CreateContext()
=> Fixture.CreateContext();

Expand Down
Original file line number Diff line number Diff line change
@@ -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; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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]");
}
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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]
Expand All @@ -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]
Expand Down Expand Up @@ -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]
Expand All @@ -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]
Expand Down Expand Up @@ -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 (
Expand All @@ -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 (
Expand Down Expand Up @@ -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]
Expand Down Expand Up @@ -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] = (
Expand Down Expand Up @@ -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);
}
Expand Down
Loading

0 comments on commit cda096e

Please sign in to comment.