Skip to content

Commit 3d0512a

Browse files
authored
[release/8.0] Do extra processing for init-only fields (#32342) (#32355)
Fixes #32310
1 parent 6980d92 commit 3d0512a

File tree

2 files changed

+72
-2
lines changed

2 files changed

+72
-2
lines changed

src/EFCore.Relational/Query/RelationalShapedQueryCompilingExpressionVisitor.ShaperProcessingExpressionVisitor.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ public partial class RelationalShapedQueryCompilingExpressionVisitor
1616
{
1717
private sealed partial class ShaperProcessingExpressionVisitor : ExpressionVisitor
1818
{
19+
public static readonly bool UseOldBehavior32310 =
20+
AppContext.TryGetSwitch("Microsoft.EntityFrameworkCore.Issue32310", out var enabled32310) && enabled32310;
21+
1922
/// <summary>
2023
/// Reading database values
2124
/// </summary>
@@ -2063,7 +2066,10 @@ protected override Expression VisitBinary(BinaryExpression node)
20632066
OrElse(
20642067
ReferenceEqual(currentVariable, Constant(null)),
20652068
ReferenceEqual(parameter, Constant(null))),
2066-
MakeBinary(node.NodeType, node.Left, parameter),
2069+
!UseOldBehavior32310
2070+
&& node is { NodeType: ExpressionType.Assign, Left: MemberExpression leftMemberExpression }
2071+
? leftMemberExpression.Assign(parameter)
2072+
: MakeBinary(node.NodeType, node.Left, parameter),
20672073
Call(
20682074
PopulateListMethod.MakeGenericMethod(property.ClrType.TryGetElementType(typeof(IEnumerable<>))!),
20692075
parameter,

test/EFCore.Relational.Specification.Tests/Query/JsonQueryAdHocTestBase.cs

Lines changed: 65 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,70 @@ public abstract class JsonQueryAdHocTestBase : NonSharedModelTestBase
88
protected override string StoreName
99
=> "JsonQueryAdHocTest";
1010

11+
#region 32310
12+
13+
[ConditionalTheory]
14+
[MemberData(nameof(IsAsyncData))]
15+
public virtual async Task Contains_on_nested_collection_with_init_only_navigation(bool async)
16+
{
17+
var contextFactory = await InitializeAsync<MyContext32310>(seed: Seed32310);
18+
await using var context = contextFactory.CreateContext();
19+
20+
var query = context.Pubs
21+
.Where(u => u.Visits.DaysVisited.Contains(new DateOnly(2023, 1, 1)));
22+
23+
var result = async
24+
? await query.FirstOrDefaultAsync()!
25+
: query.FirstOrDefault()!;
26+
27+
Assert.Equal("FBI", result.Name);
28+
Assert.Equal(new DateOnly(2023, 1, 1), result.Visits.DaysVisited.Single());
29+
}
30+
31+
protected virtual void Seed32310(MyContext32310 context)
32+
{
33+
var user = new Pub32310
34+
{
35+
Name = "FBI",
36+
Visits = new Visits32310
37+
{
38+
LocationTag = "tag",
39+
DaysVisited = new List<DateOnly> { new(2023, 1, 1) }
40+
}
41+
};
42+
43+
context.Add(user);
44+
context.SaveChanges();
45+
}
46+
47+
protected class MyContext32310 : DbContext
48+
{
49+
public MyContext32310(DbContextOptions options)
50+
: base(options)
51+
{
52+
}
53+
54+
public DbSet<Pub32310> Pubs => Set<Pub32310>();
55+
56+
protected override void OnModelCreating(ModelBuilder modelBuilder)
57+
=> modelBuilder.Entity<Pub32310>(b => { b.OwnsOne(e => e.Visits).ToJson(); });
58+
}
59+
60+
public class Pub32310
61+
{
62+
public int Id { get; set; }
63+
public required string Name { get; set; }
64+
public Visits32310 Visits { get; set; } = null!;
65+
}
66+
67+
public class Visits32310
68+
{
69+
public string LocationTag { get; set; }
70+
public required List<DateOnly> DaysVisited { get; init; }
71+
}
72+
73+
#endregion
74+
1175
#region 29219
1276

1377
[ConditionalTheory]
@@ -893,7 +957,7 @@ public class MyJsonEntityLazyLoadingProxies
893957
}
894958

895959
#endregion
896-
960+
897961
#region NotICollection
898962

899963
[ConditionalTheory]

0 commit comments

Comments
 (0)