Skip to content

Commit

Permalink
Partial fix to type mapping inference for primitive collections (#31110)
Browse files Browse the repository at this point in the history
Closes #31030
  • Loading branch information
roji authored Jun 21, 2023
1 parent da6e296 commit 532482d
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 2 deletions.
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

0 comments on commit 532482d

Please sign in to comment.