Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Partial fix to type mapping inference for primitive collections #31110

Merged
merged 1 commit into from
Jun 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions All.sln.DotSettings
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ The .NET Foundation licenses this file to you under the MIT license.
<s:Boolean x:Key="/Default/UserDictionary/Words/=unignore/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=fixup/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=attacher/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=uninferrable/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=uniqueidentifier/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Uniquification/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Uniquified/@EntryIndexedValue">True</s:Boolean>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2656,6 +2656,7 @@ when _currentSelectExpression is not null
&& _currentProjectionExpression is not null
&& _inferredColumns.TryGetValue(
(_currentSelectExpression, _currentProjectionExpression.Alias), out var inferredTypeMapping)
&& inferredTypeMapping is not null
&& WasMaybeOriginallyUntyped(columnExpression):
{
RegisterInferredTypeMapping(columnExpression, inferredTypeMapping);
Expand Down Expand Up @@ -2704,14 +2705,15 @@ SqlExpression UnwrapConvert(SqlExpression expression)
: expression;
}

private void RegisterInferredTypeMapping(ColumnExpression columnExpression, RelationalTypeMapping? inferredTypeMapping)
private void RegisterInferredTypeMapping(ColumnExpression columnExpression, RelationalTypeMapping inferredTypeMapping)
{
var underlyingTable = columnExpression.Table is JoinExpressionBase joinExpression
? joinExpression.Table
: columnExpression.Table;

if (_inferredColumns.TryGetValue((underlyingTable, columnExpression.Name), out var knownTypeMapping)
&& inferredTypeMapping != knownTypeMapping)
&& knownTypeMapping is not null
&& inferredTypeMapping.StoreType != knownTypeMapping.StoreType)
{
// A different type mapping was already inferred for this column - we have a conflict.
// Null out the value for the inferred type mapping as an indication of the conflict. If it turns out that we need the
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,52 @@ FROM OPENJSON(@__dateTimes_0_1) WITH ([value] datetime2 '$') AS [d0]
""");
}

[ConditionalFact]
public virtual async Task Same_collection_with_default_type_mapping_and_uninferrable_context()
{
var contextFactory = await InitializeAsync<TestContext>(
onModelCreating: mb => mb.Entity<TestEntity>(b => b.Property(typeof(DateTime), "DateTime")));

await using var context = contextFactory.CreateContext();

var dateTimes = new DateTime?[] { new DateTime(2020, 1, 1, 12, 30, 00), new DateTime(2020, 1, 2, 12, 30, 00), null };

_ = await context.Set<TestEntity>()
.Where(m => dateTimes.Any(d => d == EF.Property<DateTime>(m, "DateTime") && d != null))
.ToArrayAsync();

AssertSql(
"""
@__dateTimes_0='["2020-01-01T12:30:00","2020-01-02T12:30:00",null]' (Size = 4000)

SELECT [t].[Id], [t].[DateTime], [t].[Ints]
FROM [TestEntity] AS [t]
WHERE EXISTS (
SELECT 1
FROM OPENJSON(@__dateTimes_0) WITH ([value] datetime2 '$') AS [d]
WHERE [d].[value] = [t].[DateTime] AND [d].[value] IS NOT NULL)
""");
}

[ConditionalFact]
public virtual async Task Same_collection_with_non_default_type_mapping_and_uninferrable_context()
{
var contextFactory = await InitializeAsync<TestContext>(
onModelCreating: mb => mb.Entity<TestEntity>(
b => b.Property(typeof(DateTime), "DateTime").HasColumnType("datetime")));

await using var context = contextFactory.CreateContext();

var dateTimes = new DateTime?[] { new DateTime(2020, 1, 1, 12, 30, 00), new DateTime(2020, 1, 2, 12, 30, 00), null };

var exception = await Assert.ThrowsAsync<InvalidOperationException>(
() => context.Set<TestEntity>()
.Where(
m => dateTimes.Any(d => d == EF.Property<DateTime>(m, "DateTime") && d != null))
.ToArrayAsync());
Assert.Equal(RelationalStrings.ConflictingTypeMappingsInferredForColumn("value"), exception.Message);
}

[ConditionalFact]
public virtual async Task Same_collection_with_conflicting_type_mappings_not_supported()
{
Expand Down