这工作,没有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 表示p 和per 是同一个引用。没有制作额外的,可以指向其他地方,而p 一直指向约翰
想象一下,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 核心保存更改时,它不会将您传入的实体全部替换为新实体;它修改了实体内部的一些数据。它不需要ref 让您的代码看到它所做的更改
EF 是一个两步过程甚至都没有关系——你将你的实体传递给 Add,EF 将它存储在一个内部列表中,当它 SaveChanges() 时它通过它自己的引用访问数据,但是因为只有一个数据,并且您的变量和 EF 的列表都指向相同的数据,当 EF 更改数据时,您的变量会看到它,因为它是相同内存位置的相同数据