dotnet / efcore

EF Core is a modern object-database mapper for .NET. It supports LINQ queries, change tracking, updates, and schema migrations.
https://docs.microsoft.com/ef/
MIT License
13.79k stars 3.19k forks source link

When I update multiple entities whose navigation properties are the same object, only one of the entities is successfully updated #30281

Closed Angus221 closed 1 year ago

Angus221 commented 1 year ago

When I update multiple entities whose navigation properties are the same object, only one of the entities is successfully updated, and the others are not.

Code

Entities

public class Bank
 {
       public int ID { get; set; }
       public string BankName { get; set; }
        public int BankTypeID { get; set; }
        [ForeignKey("BankTypeID")]
        public virtual BankType BankType { get; set; }
 }

pulic class BankType
{
      public int ID { get; set; }

     public string BankTypeName { get; set; }
}

update code

var bankList=context.DbSet<Bank>().Include(b=>b.BankType).ToList();

//update some properties ;
bankList.ForEach(b=>b.BankName=b.BankName+"test"); //Sample code

//data samples
// [{ID: 1,BankName:"Test1",BankTypeID:1,BankType:{ID:1,BankTypeName:"TestType1"}},
// {ID: 2,BankName:"Test2",BankTypeID:1,BankType:{ID:1,BankTypeName:"TestType1"}}
//{ID: 3,BankName:"Test3",BankTypeID:1,BankType:{ID:1,BankTypeName:"TestType1"}}]
// The navigation property(BankType) for all of the above entities are the same object

context.SaveChanges();

In the above example, only one entity was updated successfully,the remaining two entities did not generate any updated SQL;

If I don't use "include", all entities can be updated successfully, just like:

var bankList=context.DbSet<Bank>().ToList();

//update some properties ;
bankList.ForEach(b=>b.BankName=b.BankName+"test"); //Sample code
context.SaveChanges();

If I set the navigation property to Null, all entities can be updated successfully as well,just like:

var bankList=context.DbSet<Bank>().ToList();

//update some properties ;
bankList.ForEach(b=>b.BankName=b.BankName+"test"); //Sample code

bankList.ForEach(b=>b.BankType=null); //set the navigation property to Null

context.SaveChanges();

If the navigation properties are not the same, all entities can be updated successfully,just like:

var bankList=context.DbSet<Bank>().Include(b=>b.BankType).ToList();

//update some properties ;
bankList.ForEach(b=>b.BankName=b.BankName+"test"); //Sample code

//data samples
// [{ID: 1,BankName:"Test1",BankTypeID:1,BankType:{ID:1,BankTypeName:"TestType1"}},
// {ID: 2,BankName:"Test2",BankTypeID:2,BankType:{ID:2,BankTypeName:"TestType12"}}
//{ID: 3,BankName:"Test3",BankTypeID:3,BankType:{ID:3,BankTypeName:"TestType13"}}]
// The navigation property(BankType) for all of the above entities are not the same object

context.SaveChanges();

So I'm guessing entities with the same navigation properties, only one of them will be updated, but I'm wondering why?

provider and version information

EF Core version: EF Core 5.0.5 Database provider:Microsoft.EntityFrameworkCore.SqlServer Target framework: NET 5.0 Operating system: IDE: Visual Studio 2022 17.1.4

davidroth commented 1 year ago

EFCore 5 is no longer supported. See: https://learn.microsoft.com/en-us/ef/core/what-is-new/#stable-releases Did you also try this on EFCore 6 or EFCore 7? If you can reproduce this on EFCore6 and EfCore7, you should include a fully reproducable sample incl. model building code etc.

Angus221 commented 1 year ago

fix