dotnet / dotnet/efcore

When mapping a property to a string/json column in a group by, EF materializes inconsistent results

Open
#31,675 2 comments 0 reactions 0 assignees View on GitHub
area-query customer-reported
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

I'm finding inconsistent behavior when querying via EF when grouping by an entity that has property(ies) mapped with a string converter. This is breaking our unit tests and the error is hard to detect.

Repro: https://github.com/Westboldyi/XminOrderByRepro/tree/string-converter-group-by-bug

```C#

//Entities
public class Foo
{

public string Id { get; set; } = Guid.NewGuid().ToString();

public List Json { get; set; } = new();
}

public class Bar
{
private Bar()
{

}
public Bar(Foo foo)
{
Foo = foo;
}
public string Id { get; set; } = Guid.NewGuid().ToString();

public Foo Foo { get; set; }

}

//Config
public class ApplicationDbContext :DbContext
{
public ApplicationDbContext(DbContextOptions options)
: base(options)
{
}

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{

base.OnConfiguring(optionsBuilder);
}

protected override void OnModelCreating(ModelBuilder builder)
{
builder.Entity();

//Configuring with a string converter will result in a count of 4 entities materialized (unexpected).

builder.Entity().Property(p=>p.JsonBlob).HasConversion(to => "{}", from => new List());

//Ignoring/not configuring the JsonBlob property will result in a count of 3 entities materialized (expected).
//builder.Entity().Ignore(p => p.JsonBlob);

base.OnModelCreating(builder);
}
}

//Query

public class QueryClass
{
private readonly ApplicationDbContext _dbContext;

public QueryClass(ApplicationDbContext dbContext)
{
_dbContext = dbContext;
}

public async Task Query2()
{
await _dbContext.Set().ExecuteDeleteAsync();
await _dbContext.Set().ExecuteDeleteAsync();

var foo1 = new Foo();
var foo2 = new Foo();
var foo3 = new Foo();
_dbContext.Set().Add(foo1);
_dbContext.Set().Add(foo2);
_dbContext.Set().Add(foo3);

_dbContext.Set().Add(new Bar(foo1));
_dbContext.Set().Add(new Bar(foo1));
_dbContext.Set().Add(new Bar(foo2));
_dbContext.Set().Add(new Bar(foo3));
await _dbContext.SaveChangesAsync();

_dbContext.ChangeTracker.Clear();
var query = (from foo in _dbContext.Set()
join bar in _dbContext.Set() on foo equals bar.Foo
group new
{
bar.Id,
} by foo);

var qs = query.ToQueryString();
var result = await query.ToListAsync();

Debug.Assert(result.Count == 3); //3 Foo's returned if 'JsonBlob' is ignored by EF.
Debug.Assert(result.Count == 4); //4 Foo's returned if string converter is configured for 'JsonBlob' by EF.
}
}

```
### Include provider and version information

EF Core version: 7.0.10
Database provider: NpgSql
Target framework: 7
Operating system: Win 10
IDE: Visual Studio 2022 Preview

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.