EF SaveChanges 方法背后的逻辑是什么?

What is the logic behind EF SaveChanges Method?

当我在 DBSet 中插入一个新项目时,例如:

var newItemAdded = MyDBSet.Add(itemToAdd);

然后我将更改保存在数据库中,如:

MyContext.SaveChanges();

我的变量 newItemAdded 已使用数据库自​​动生成的新 ID 更新。

我去EF Core Github看了逻辑,但是仓库里的文件很多,我不确定背后的逻辑。

我更关心的是插入后执行的 SaveChanges 如何更新 newItemAdded。 EF 似乎没有使用 ref.

也许有人已经知道它是如何工作的?

谢谢

这有效,没有 ref:

class Person{
  int Id {get;set;} = -1; 
  string Name {get;set;}
}

...

void SaveChanges(Person per){     //no ref here
  //simulate saving to DB
  per.Id = new Random().Next();
}

...

var p = new Person{ Name = "John"; }
Console.WriteLine(p.Id); //prints -1;
SaveChanges(p);
Console.WriteLine(p.Id); //prints some random number

我们从来不需要 ref 来确保在 SaveChanges 中设置的人的 ID 仍然存在,并且在 SaveChanges 完成后被 p 看到。

从概念上讲,这是调用上面的 SaveChanges 代码时内存中发生的情况:

p --> [ John, -1 ]                 //var p = new Person{Name = "John"}
p --> [ John, -1 ] <-- per         //SaveChanges(p), establishes another variable per, pointing at the same in memory data
p --> [ John, 23 ] <-- per       //per.Id = random number
p --> [ John, 23 ]               //method exits, variable per goes away. p survives and sees changed data

ref 是一种允许 SaveChanges 将传入的 Person 换出整个 new Person 的机制。如果你有一个像这样的 SaveChanges:

void SaveChanges(Person per){
  per = new Person{ Name = "Jane", Id = 234 }
}

然后内存步骤中的对象将如下所示:

p --> [ John, -1 ]                             //var p = new Person{Name = "John"}
p --> [ John, -1 ] <-- per                     //SaveChanges(p), establishes another reference called per, pointing at the same in-memory data
p --> [ John, -1 ]     per --> [Sarah, 23]     //per is reassigned to a new Person created elsewhere in memory
p --> [ John, -1 ]                             //method exits, variable per goes away. Sarah is vaporized. John was never changed

假设我们使用 ref:

void SaveChanges(ref Person per){
  per = new ...
}

ref 表示 pper 是同一个引用。没有另外制作一个,可以指向其他地方,而 p 一直指向 John

假设 ref 暂时将 p 重命名为 per,因此执行 per = new Person 的 SaveChanges 方法也会影响 p。它可以被认为是这样的:

p ---------> [ John, -1 ]                    //var p = new Person{Name = "John"}
per was p -> [ John, -1 ]                    //SaveChanges(p), establishes another variable per, pointing at the same in memory data
per was p -> [ Sarah, 23]                    //per = new Person..., John is lost here
p ---------> [ Sarah, 23]                    //method exits, variable per goes away. p is the only remaining reference, 

当 EF core 保存更改时,它不会将您传入的实体全部替换为新实体;它修改了实体内部的一些数据。您的代码不需要 ref 就能看到它所做的更改

EF 是一个两步过程甚至无关紧要 - 您将实体传递给 Add,EF 将其存储在内部列表中,当它 SaveChanges() 时,它通过自己的引用访问数据,但是因为只有一个数据并且您的变量和 EF 的列表都指向相同的数据,所以当 EF 更改数据时您的变量会看到它,因为它是相同内存位置的相同数据