-
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
[Bug]: Attach with ValueGenerator
composite key not working in case of Relations (FK)
#26448
Comments
I test Code Sample (Console App) >> |
Note for triage: the fundamental question here is whether the generation of a stable value should be enough to consider the entity as new or not. For example, in the following code, the state of the attached entity is public class Book
{
public Guid Id { get; set; }
}
public class SomeDbContext : DbContext
{
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.UseSqlServer(Your.ConnectionString);
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Book>().Property(e => e.Id).HasValueGenerator<TenantIdGenerator>();
}
}
public class TenantIdGenerator : ValueGenerator<Guid>
{
public override Guid Next(EntityEntry entry) => Guid.Parse("98D06A82-C691-4988-EA39-08D98E2C8D8F");
public override bool GeneratesTemporaryValues => false;
public override bool GeneratesStableValues => true;
}
public class Program
{
public static void Main()
{
using (var context = new SomeDbContext())
{
var book = new Book();
context.Attach(book);
Console.WriteLine($"State = {context.Entry(book).State}");
}
}
} |
I consider it a bug, as EF core 5 has different behaviour for two similar situations. When I test it in EF Core 6 and both the entities had If it was intented, is there any way to attach the existing entities with a value generated key? |
@mohamed-seada-1994 If the key value is not set, then the entity is considered new and will get the Added state. |
@ajcvickers The use case I want to cover involves a shadow property and updating an entity using
The problem I have with For non-shadow property, the entity is considered |
@ajcvickers @mohamed-seada-1994 InternalEntityEntry.cs#L1513-L1542 This HasDefaultValue method return true in final, but not everything has a default value. InternalEntityEntry.cs#L198-L218 And this will return false when newState is Modified. It's false, so on this InternalEntityEntry.cs#L134-L137, it was not generated any value. ValueGenerationManager.cs#L91-L117 On line 97, not everything has a default value, so it will be skip some ValueGenerator property, skip generated value. |
@eation All of that seems by-design, except possibly changing the handling of stable generated values. @mohamed-seada-1994 If you have a shadow property that is part of a primary key, then it needs to be set explicitly to the correct value before attaching. This is one reason (of many) not to put PKs into shadow state. If you're seeing some behavior that involves a FK that is not also part of a PK, then please attach a small, runnable project or post a small, runnable code listing that reproduces what you are seeing so that we can investigate. |
Note from triage: generation of a stable value should not be enough to treat an entity as new. |
@ajcvickers EfCore 5: EFCore 6: |
@ajcvickers Is there any workaround I could use to set/generate shadow property explicitly before update/attach? |
@mohamed-seada-1994 I was make a simple fix for #6999 on this fork, it work for this test ConcurrencyValueGeneratorTest current in efcore5,but need more test in efcore6, maybe u can test it. |
@mohamed-seada-1994 I should point out again that using value generators to generate primary key values that are not new (i.e. are already stored in the database) is not something EF Core was designed for. It's not something I have ever seen anyone do before this issue. Stable keys potentially allows for this, again as discussed above. The best workaround is to not used a value generator to set values that already exist in the database. |
@eation I think you solution is related to generate values on update before saving the changes, It's not going to work in case of autogenerated PK before attach, update. @ajcvickers
I found this workaround to set the value of the shadow property before var generatedTenantId = Guid.Parse("98D06A82-C691-4988-EA39-08D98E2C8D8F");
var entry = context.Entry(book);
entry.Property("TenantId").OriginalValue = generatedTenantId;
entry.Property("TenantId").CurrentValue = generatedTenantId;
entry.Property("TenantId").IsModified = false;
book.Title = "Modified!";
var attachedEntry = context.Books.Update(book); // attachedEntry.Status >> "Modified"
context.SaveChanges(); With this workaround I have to set the shadow property on before calling |
Setup
ValueGenerator<Guid>
. (TenantId
)Error and notes
book
entity with theTenantId
property unset, The value will be generated correctly but the entity will be attached as a new Added entity.Student
entity in this sampleTenantId
property unset, The value will be generated correctly and the entity will be attached as Unchanged entity.Code Sample (Console App) >>
attach-demo branch
https://github.com/mohamed-seada-1994/EFCore-ValueGenerator-Bug-Sample/tree/attach-demo
EF Core version:
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: NET 5.0
Operating system: Win10
IDE: Visual Studio 2019 16.11.5
The text was updated successfully, but these errors were encountered: