-
Notifications
You must be signed in to change notification settings - Fork 3.2k
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
SaveChanges circular dependency in unique filtered index #28065
Comments
Just adding on that I can also reproduce this with a filtered unique index which does not allow nulls: // Same code for TestEntity
public class TestDependentEntity
{
public int Id { get; set; }
public int TestEntityId { get; set; }
public string UniqueOn { get; set; } = null!;
public int? ToChange { get; set; }
public class Config : IEntityTypeConfiguration<TestDependentEntity>
{
public void Configure(EntityTypeBuilder<TestDependentEntity> builder)
{
builder.HasIndex(e => new { e.TestEntityId, e.UniqueOn })
.HasFilter("unique_on != 'a'")
.IsUnique();
}
}
} Reproduce with: var t1 = new TestEntity();
db.Tests.Add(t1);
await db.SaveChangesAsync();
var dependent = new TestDependentEntity() {
TestEntityId = t1.Id,
UniqueOn = "a",
ToChange = 1,
};
var dependent2 = new TestDependentEntity() {
TestEntityId = t1.Id,
UniqueOn = "a",
ToChange = 2,
};
var dependent3 = new TestDependentEntity() {
TestEntityId = t1.Id,
UniqueOn = "b",
ToChange = 3,
};
db.TestDependents.Add(dependent);
db.TestDependents.Add(dependent2);
db.TestDependents.Add(dependent3);
await db.SaveChangesAsync();
dependent.ToChange = null;
dependent2.ToChange = null;
dependent3.ToChange = null;
// Errors
await db.SaveChangesAsync(); Stacktrace:
Similarly, it looks like the filter is not being taken into account so the two entries in the index |
Thanks for the code - confirmed that I can repro this. I've indeed done some changes in this area, will investigate. Repro codeusing System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
await using var ctx = new BlogContext();
await ctx.Database.EnsureDeletedAsync();
await ctx.Database.EnsureCreatedAsync();
var t1 = new TestEntity();
ctx.Tests.Add(t1);
await ctx.SaveChangesAsync();
var dependent = new TestDependentEntity() {
TestEntityId = t1.Id,
UniqueOn = null,
ToChange = 1,
};
var dependent2 = new TestDependentEntity() {
TestEntityId = t1.Id,
UniqueOn = null,
ToChange = 2,
};
ctx.TestDependents.Add(dependent);
ctx.TestDependents.Add(dependent2);
await ctx.SaveChangesAsync();
dependent.ToChange = null;
dependent2.ToChange = null;
await ctx.SaveChangesAsync();
public class BlogContext : DbContext
{
public DbSet<TestEntity> Tests { get; set; }
public DbSet<TestDependentEntity> TestDependents { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlite(@"Data Source=/tmp/foo.sqlite")
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TestDependentEntity>().HasIndex(e => new { e.TestEntityId, e.UniqueOn })
.IsUnique();
}
}
public class TestEntity
{
public int Id { get; set; }
}
public class TestDependentEntity
{
public int Id { get; set; }
public int TestEntityId { get; set; }
public bool? UniqueOn { get; set; }
public int? ToChange { get; set; }
} |
@AndriySvyryd this is caused by 246cc8692915c72d77e393952c1c6797dea92fc9g. I didn't dig too deep, CommandBatchPreparer.IsModified - called from AddUniqueValueEdges - returns true, as if the commands modify columns covered by the index (which they don't). The cause seems to be the new ProviderValueComparer check. |
This happens because the index has a filter. We shouldn't try to sort filtered index values as we can't evaluate it |
Just for the avoidance of doubt, is this also the cause for the first reproducer I posted which contains a unique index rather than an index with a filter? |
No, the two repros have different causes |
Thanks for confirming, and thanks for taking a look 👍 |
…oken if there's a cycle, since they might not be enforced in the database. Fixes #28065
Hi Guys Is the first scenario without filter fixed as well? I have an issue where I attach entity and mark property as modified to force ef to send update for just this column. But instead I get the same exception regarding unique index. This approach was working fine in ef core 6. It fails now after update to ef core 7. |
The first example still fails for me. using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
var db = new TestDbContext();
await db.Database.EnsureDeletedAsync();
await db.Database.EnsureCreatedAsync();
var t1 = new TestEntity();
db.Tests.Add(t1);
await db.SaveChangesAsync();
var dependent = new TestDependentEntity()
{
TestEntityId = t1.Id,
UniqueOn = null,
ToChange = 1,
};
var dependent2 = new TestDependentEntity()
{
TestEntityId = t1.Id,
UniqueOn = null,
ToChange = 2,
};
db.TestDependents.Add(dependent);
db.TestDependents.Add(dependent2);
await db.SaveChangesAsync();
dependent.ToChange = null;
dependent2.ToChange = null;
await db.SaveChangesAsync();
public class TestDbContext : DbContext
{
public DbSet<TestEntity> Tests { get; set; }
public DbSet<TestDependentEntity> TestDependents { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.UseSqlite(@"Data Source=foo.sqlite")
.LogTo(Console.WriteLine, LogLevel.Information)
.EnableSensitiveDataLogging();
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<TestDependentEntity>().HasIndex(e => new { e.TestEntityId, e.UniqueOn })
.IsUnique();
}
}
public class TestEntity
{
public int Id { get; set; }
}
public class TestDependentEntity
{
public int Id { get; set; }
public int TestEntityId { get; set; }
public bool? UniqueOn { get; set; }
public int? ToChange { get; set; }
} |
@roji can we reopen this, since it doesn't seem to be fixed? |
BatchingTopologicalSort
in latest preview
While testing out the newest preview, I'm running into an issue with a previously working bit of code -
BatchingTopologicalSort
is throwing errors for a case that was working in EFCore 6.It's reproducible for me with the following cut-down code:
Entities:
To reproduce:
The final
SaveChangesAsync()
will throw the following error:It appears that this is due to the unique index, and indeed removing the index makes this work. Although I can't tell for sure, my hunch is that the code working with the index is not considering the fact that the two rows are considered unique by the index even though they both have
null
inUniqueOn
becauseNULL != NULL
?Happy to provide any more info if needed.
Info
EF Core version:
7.0.0-preview.4.22229.2
Database provider:
Npgsql.EntityFrameworkCore.PostgreSQL
Target framework:
.NET 6
Operating system: macOS
IDE: Rider 2022.1
The text was updated successfully, but these errors were encountered: