[英]Entity Framework Attach/Update confusion (EF Core)
据我了解,当“更新”被调用时,特定实体中的每个属性都会被修改。
另一方面,“附加”方法以“未修改”状态启动实体。 然后,当对特定属性进行操作时,只会修改该特定属性。 因此,“Attach”对于单个属性更改更有用,而当您想要更新实体中的每个属性时,“Update”更有用(我的理解可能是错误的)。
但是,我不明白的是,在属性更改期间这两种方法都没有被调用时会发生什么。 例如,考虑一个名为“students”的表的示例:
student.City = "Calgary";
student.Name = "John Smith";
database.SaveChanges();
由于我们没有将实体中的任何属性标记为已修改,因此上述代码生成的查询有何不同?
考虑以下代码:
students entity = new students() {
Id = 1,
City = "New York",
Name = "Sam"
};
using(SomeContext ctx = new SomeContext())
{
ctx.Entry(entity).State = EntityState.Modified;
ctx.SaveChanges();
}
假设我们在数据库中有一个 id = 1 的记录,上面的代码将更新数据库中的实体。
当您知道数据库中已经存在一个实体但想要在将状态更改为已修改时进行一些更改时使用Attach
。
在下面的示例中,实体是由上下文获取的,因此上下文立即开始跟踪它。 当您更改跟踪实体的属性值时,上下文会将实体的 EntityState 更改为 Modified,ChangeTracker 会记录旧属性值和新属性值。 调用 SaveChanges 时,数据库会生成并执行 UPDATE 语句。
var author = context.Authors.First(a => a.AuthorId == 1);
author.FirstName = "Bill";
context.SaveChanges();
由于 ChangeTracker 跟踪哪些属性已被修改,上下文将发出一条 SQL 语句,该语句仅更新那些已更改的属性:
exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Authors] SET [FirstName] = @p0
WHERE [AuthorId] = @p1;
SELECT @@ROWCOUNT;
',N'@p1 int,@p0 nvarchar(4000)',@p1=1,@p0=N'Bill'
数据库上下文更新
DbContext 类提供用于处理单个或多个实体的 Update 和 UpdateRange 方法。
public void Save(Author author)
{
context.Update(author);
context.SaveChanges();
}
与设置实体的状态一样,此方法导致实体被上下文跟踪为已修改。 同样,上下文没有任何方法可以识别哪些属性值已更改,并且会生成 SQL 来更新所有属性。 此方法与显式设置 State 属性的不同之处在于,上下文将开始跟踪处于 Modified 状态的任何相关实体(例如本示例中的书籍集合),从而为每个实体生成 UPDATE 语句. 如果相关实体没有分配键值,则会将其标记为已添加,并会生成一条 INSERT 语句。
数据库上下文附加
当您在实体上使用 Attach 方法时,它的状态将设置为 Unchanged,这将导致根本不会生成任何数据库命令。 定义了键值的所有其他可访问实体也将设置为未更改。 那些没有键值的将被标记为已添加。 但是,现在实体正在被上下文跟踪,您可以通知上下文哪些属性被修改,以便生成正确的 SQL 来更新这些值:
var context = new TestContext();
var author = new Author {
AuthorId = 1,
FirstName = "William",
LastName = "Shakespeare"
};
author.Books.Add(new Book {BookId = 1, Title = "Othello" });
context.Attach(author);
context.Entry(author).Property("FirstName").IsModified = true;
context.SaveChanges();
上面的代码将导致作者实体被标记为已修改,并生成 SQL 以仅更新 FirstName 属性:
exec sp_executesql N'SET NOCOUNT ON;
UPDATE [Authors] SET [FirstName] = @p0
WHERE [AuthorId] = @p1;
SELECT @@ROWCOUNT;
',N'@p1 int,@p0 nvarchar(4000)',@p1=1,@p0=N'William'
参考: 阅读更多
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.