dotnet / dotnet/EntityFramework.Docs
Document that value comparers must handle nulls
- Dominant language
- Mermaid
- Stars
- 1.7k
- Forks
- 2k
- Avg merge
- 7d 23h
- Merged PRs (30d)
- 16
Description
## File a bug
### Include your code
Consider the following example which worked in EF Core 6 but throws in EF Core 7:
```C#
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
using Microsoft.Extensions.DependencyInjection;
using System.Text.Json;
Console.WriteLine("Hello, World!");
var services = new ServiceCollection()
.AddDbContext(options => options.UseSqlServer(connectionString: "NotImportant"))
.BuildServiceProvider();
var db = services.GetRequiredService();
db.Set().Add(new Model());
class Model
{
public int Id { get; set; }
public List Strings { get; set; } = new List();
}
class AppContext : DbContext
{
public AppContext(DbContextOptions options) : base(options)
{
}
public DbSet Models { get; init; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity().Property(x => x.Strings).HasConversion(JsonValueConverter>.Default, ListValueComparer.Default).IsRequired().HasDefaultValueSql("[]");
}
}
public class JsonValueConverter : ValueConverter
{
public static JsonValueConverter Default { get; } = new JsonValueConverter();
public JsonValueConverter(JsonSerializerOptions? options = null) : base(
convertToProviderExpression: x => JsonSerializer.Serialize(x, options),
convertFromProviderExpression: x => JsonSerializer.Deserialize(x, options))
{
}
}
public class ListValueComparer : ValueComparer>
{
public static readonly ListValueComparer Default = new();
public ListValueComparer() : base(
equalsExpression: (a, b) => EqualsFn(a, b),
hashCodeExpression: x => x.Aggregate(x.Count, (a, v) => HashCode.Combine(a, v.GetHashCode())),
snapshotExpression: x => new List(x))
{
}
static bool EqualsFn(List a, List b)
{
// This line throws in v7 because b is now "null for an empty list" instead of being an empty list.
return Enumerable.SequenceEqual(a, b);
}
}
```
In EF Core 6 the EqualsFn was never called with `b = null` but this is the case now EF Core 7 even when `HasDefaultValueSql("[]")` should have set a default value to an empty list.
### Include provider and version information
EF Core version: 7.0.0
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 7.0
Operating system:
IDE: Visual Studio 2022 17.4
Contributor guide
Assessment
This issue has not been assessed yet.