Abh*_*eet 5 c# entity-framework-core ef-core-2.2
在更改之后或更改之前,我们将实体状态置为=修改是否重要?
using (var db = new LakshyaContext())
{
foreach (var category in db.Categories)
{
db.Entry(category).State = EntityState.Modified; // before
category.Count = 25; //Making Changes
db.Entry(category).State = EntityState.Modified; //After
}
db.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
jpg*_*ssi 16
所以首先,让我们摆脱最重要的事情:
你是对的。在您的示例中,您无需手动调用db.Entry(category).State = EntityState.Modified
。这是因为您要从上面的上下文中加载条目(类别)。这就是所谓的“连接方案”,其中DbContext
知道实体,并在跟踪它们。这是相同的,例如在ASP.NET Core应用程序中,该上下文在HTTP请求之间共享。
using (var db = new LakshyaContext())
调用时,上下文将知道您在范围之间进行的任何修改SaveChanges
。
现在,在处理断开连接的场景(如您所说的“未跟踪的实体”)时,我们必须更深入地研究。
要了解这一点,首先您需要知道如何DbContext
更改。请看以下示例:
using (var context = new MyContext())
{
// loads the book by it's ISBN
var book = context.Books
.Single(p => p.ISBN == "123456");
// Do changes
book.Price = 30;
// Save changes
context.SaveChanges();
}
Run Code Online (Sandbox Code Playgroud)
它如何知道已Price
更改?因为这只是类的普通自动属性Book
?该DetectChanges
方法背后的魔力。
在某些特定情况下,DbContext
调用DetectChanges
方法。最明显的一个是何时SaveChanges
被调用。在顶层,它的工作方式是:
DbContext
使每个实体IT负载的快照SaveChanges
被调用时,它将继续进行调用DetectChanges
,这将很神奇地找出更改或未更改的内容。DbContext
然后负责将正确的命令发送到数据库。至此,我们知道的责任DetectChanges
。现在重要的部分是知道何时DetectChanges
调用(除了我们已经知道的SaveChanges)。这对于最终回答您的“订单”问题至关重要。摘自Arthur Vickers的链接文章
调用DetectChanges的方法:
- 数据库设置
- DbSet.Local
- DbSet。删除
- DbSet.Add
- DbSet。附加
- DbContext.SaveChanges
- DbContext.GetValidationErrors
- DbContext.Entry
- DbChangeTracker.Entries
让我们研究一下演示“断开连接”方案的代码。
public Task UpdateBook()
{
Book book = null;
// Just loads the book from this context
using (var context = new MyContext())
{
book = context.Books
.Single(p => p.ISBN == "123456");
}
// Starts a new context where the book is going to be updated
using (var anotherContext = new MyContext())
{
// Changed the price - remember this is not loaded from this context!
book.Price = 40;
// THIS IS KEY: This will call `DetectChanges`
// This entity will be tracked by the context now
db.Entry(book).State = EntityState.Modified
// Update will occur normally
db.SaveChanges();
}
}
Run Code Online (Sandbox Code Playgroud)
当我们进入第二阶段时,DbContext,
它并不知道我们的book
实体。我们更改价格,然后致电db.Entry(book).State = EntityState.Modified
。此时,DbContext
将会开始跟踪它并被DetectChanges
调用。进行呼叫SaveChanges
将按预期进行。
如果我们做相反db.Entry(book).State = EntityState.Modified
的事情,那么在实际更改价格之前打电话就可以了。
为什么?好吧,用手动更改实体的状态db.Entry(book).State
会将实体添加到上下文中,这意味着它将开始跟踪其更改。因此,即使我们先调用db.Entry(book).State
然后对实体应用更改,也没关系,因为最后调用SaveChanges
会再次 触发DetectChanges
,并且由于之前已被调用,因此该实体已经存在一个快照。
您可以自己验证此行为的一种方式是运行上面的代码,并为启用日志记录DbContext
:
// Calling db.Entry.. produces this log:
DetectChanges starting for 'MyContext'.
Microsoft.EntityFrameworkCore.ChangeTracking:Debug: DetectChanges completed for 'MyContext'.
Context 'MyContext' started tracking 'Book' entity.
// Calling SaveChanges produces this log:
SaveChanges starting for 'MyContext'
DetectChanges starting for 'MyContext'.
DetectChanges completed for 'MyContext'.
Opening connection to database 'BooksDB'
Beginning transaction with isolation
...
Run Code Online (Sandbox Code Playgroud)
现在一些说明:
在断开连接的情况下,以上更新将在表中的“ 所有列”上发布更新。这可能不是您所期望的。有防止这种情况的方法。在这里阅读更多
DetectChanges
在内部做很多事情,不仅对变更应用合并。它负责处理外键,更新导航属性的引用等,并进行“修复”。
有更多资源需要阅读:(尤其是亚瑟·维克斯的著作!)
DetectChanges的秘密第1部分:DetectChanges有什么作用?
DetectChanges的秘密第2部分:什么时候自动调用DetectChanges?
变更跟踪器缓存实体状态EF Core 2.0.2可能存在的问题
归档时间: |
|
查看次数: |
911 次 |
最近记录: |