You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The main issue here is that the application is marking an entity as Deleted, and then adding a new instance with the same key as Added. Because of #30705, this gets converted to an update containing this:
UPDATE [Item] SET [CreatedAt] = @p0, [UpdatedAt] = @p1
Before 7.0.3, the behavior was this:
UPDATE [Item] SET [UpdatedAt] = @p1
UpdatedAt is marked as BeforeSaveBehavior ignore. CreatedAt is marked as AfterSaveBehavior ignore.
So, if we treat this as an update, then UpdatedAt should be sent, but CreatedAt should not.
On the other hand, if this remains a deleteinsert, then CreatedAt should be sent in the insert, and UpdatedAt should not.
Repro:
usingvarcontext=new StoreContext();await context.Database.EnsureDeletedAsync();await context.Database.EnsureCreatedAsync();varitem=new Item {Id="abc",CreatedAt= DateTime.Now.ToString()};varstore=new Store {CreatedAt= DateTime.Now.ToString(),Items={ item }};
context.Add(store);await context.SaveChangesAsync();
context.ChangeTracker.Clear();store=await context.Stores.Include(e => e.Items).SingleAsync();
store.CreatedAt ="X";
store.UpdatedAt ="Y";
store.Items =newList<Item>(){new(){Id= item.Id,CreatedAt="A",UpdatedAt="B"}};// Doing the store update like this instead does not result in the issue:// store.Items.First().CreatedAt += "+";// store.Items.First().UpdatedAt += "+";
context.SaveChanges();publicclassItem{publicstringId{get;set;}=null!;publicintStoreId{get;set;}publicstring?CreatedAt{get;set;}publicstring?UpdatedAt{get;set;}}publicclassStore{publicintStoreId{get;set;}publicList<Item> Items {get;set;}=new();publicstring?CreatedAt{get;set;}publicstring?UpdatedAt{get;set;}}publicclassStoreContext:DbContext{publicDbSet<Store> Stores =>Set<Store>();protectedoverridevoidOnConfiguring(DbContextOptionsBuilderoptionsBuilder)=>
optionsBuilder
.LogTo(Console.WriteLine, LogLevel.Information).UseSqlServer("Data Source=localhost;Database=BuildBlogs;Integrated Security=True;Trust Server Certificate=True;ConnectRetryCount=0");protectedoverridevoidOnModelCreating(ModelBuildermodelBuilder){
modelBuilder.Entity<Item>(b =>{ b.Property(x => x.CreatedAt).Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Ignore); b.Property(x => x.UpdatedAt).Metadata.SetBeforeSaveBehavior(PropertySaveBehavior.Ignore);});
modelBuilder.Entity<Store>(b =>{ b.Property(x => x.CreatedAt).Metadata.SetAfterSaveBehavior(PropertySaveBehavior.Ignore); b.Property(x => x.UpdatedAt).Metadata.SetBeforeSaveBehavior(PropertySaveBehavior.Ignore);});}}
The text was updated successfully, but these errors were encountered:
Originally reported here: PomeloFoundation/Pomelo.EntityFrameworkCore.MySql#1908
See #30705
The main issue here is that the application is marking an entity as Deleted, and then adding a new instance with the same key as Added. Because of #30705, this gets converted to an update containing this:
Before 7.0.3, the behavior was this:
UpdatedAt
is marked asBeforeSaveBehavior
ignore.CreatedAt
is marked asAfterSaveBehavior
ignore.So, if we treat this as an update, then
UpdatedAt
should be sent, butCreatedAt
should not.On the other hand, if this remains a
delete
insert
, thenCreatedAt
should be sent in the insert, andUpdatedAt
should not.Repro:
The text was updated successfully, but these errors were encountered: