简体   繁体   English

实体框架附加/更新混淆(EF Core)

[英]Entity Framework Attach/Update confusion (EF Core)

As I understand, when "Update" is called, every property within a specific entity is modified.据我了解,当“更新”被调用时,特定实体中的每个属性都会被修改。

The "Attach" method, on the other hand, starts the entity off in the "Unmodified" state.另一方面,“附加”方法以“未修改”状态启动实体。 Then, when an operation takes place on a particular property, that specific property only is modified.然后,当对特定属性进行操作时,只会修改该特定属性。 So "Attach" is more useful for individual property changes, and "Update" is more useful when you want to update every property in the entity (I may be wrong in this understanding).因此,“Attach”对于单个属性更改更有用,而当您想要更新实体中的每个属性时,“Update”更有用(我的理解可能是错误的)。

However, what I don't understand is what happens when neither of these two methods are called during a property change.但是,我不明白的是,在属性更改期间这两种方法都没有被调用时会发生什么。 For instance, consider an example with a table called "students":例如,考虑一个名为“students”的表的示例:

student.City = "Calgary";
student.Name = "John Smith";
database.SaveChanges();

As we are not marking any property in the entity as modified, how will the generated query from the above code differ?由于我们没有将实体中的任何属性标记为已修改,因此上述代码生成的查询有何不同?

Consider the following code:考虑以下代码:

students entity = new students() {
    Id = 1,
    City = "New York",
    Name = "Sam"
};
using(SomeContext ctx = new SomeContext())
{
    ctx.Entry(entity).State = EntityState.Modified;
    ctx.SaveChanges();
}

Assuming we have a record with id = 1 in the database, the above code will update that entity in the database.假设我们在数据库中有一个 id = 1 的记录,上面的代码将更新数据库中的实体。

Attach is used when you know that an entity already exists in the database but want to make some changes while change state to modified when you have already made the changes.当您知道数据库中已经存在一个实体但想要在将状态更改为已修改时进行一些更改时使用Attach

In the following example, the entity is obtained by the context, so the context begins tracking it immediately.在下面的示例中,实体是由上下文获取的,因此上下文立即开始跟踪它。 When you alter property values on a tracked entity, the context changes the EntityState for the entity to Modified and the ChangeTracker records the old property values and the new property values.当您更改跟踪实体的属性值时,上下文会将实体的 EntityState 更改为 Modified,ChangeTracker 会记录旧属性值和新属性值。 When SaveChanges is called, an UPDATE statement is generated and executed by the database.调用 SaveChanges 时,数据库会生成并执行 UPDATE 语句。

var author = context.Authors.First(a => a.AuthorId == 1);
author.FirstName = "Bill";
context.SaveChanges();

Since the ChangeTracker tracks which properties have been modified, the context will issue a SQL statement that updates only those properties that were changed:由于 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数据库上下文更新

The DbContext class provides Update and UpdateRange methods for working with individual or multiple entities. DbContext 类提供用于处理单个或多个实体的 Update 和 UpdateRange 方法。

public void Save(Author author)
{
    context.Update(author);
    context.SaveChanges();
}

As with setting the entity's State, this method results in the entity being tracked by the context as Modified.与设置实体的状态一样,此方法导致实体被上下文跟踪为已修改。 Once again, the context doesn't have any way of identifying which property values have been changed, and will generate SQL to update all properties.同样,上下文没有任何方法可以识别哪些属性值已更改,并且会生成 SQL 来更新所有属性。 Where this method differs from explicitly setting the State property, is in the fact that the context will begin tracking any related entities (such as a collection of books in this example) in the Modified state, resulting in UPDATE statements being generated for each of them.此方法与显式设置 State 属性的不同之处在于,上下文将开始跟踪处于 Modified 状态的任何相关实体(例如本示例中的书籍集合),从而为每个实体生成 UPDATE 语句. If the related entity doesn't have a key value assigned, it will be marked as Added, and an INSERT statement will be generated.如果相关实体没有分配键值,则会将其标记为已添加,并会生成一条 INSERT 语句。

DBContext Attach数据库上下文附加

When you use the Attach method on an entity, it's state will be set to Unchanged, which will result in no database commands being generated at all.当您在实体上使用 Attach 方法时,它的状态将设置为 Unchanged,这将导致根本不会生成任何数据库命令。 All other reachable entities with key values defined will also be set to Unchanged.定义了键值的所有其他可访问实体也将设置为未更改。 Those without key values will be marked as Added.那些没有键值的将被标记为已添加。 However, now that the entity is being tracked by the context, you can inform the context which properties were modified so that the correct SQL to update just those values is generated:但是,现在实体正在被上下文跟踪,您可以通知上下文哪些属性被修改,以便生成正确的 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();

The code above will result in the author entity being marked as Modified, and SQL being generated to update just the FirstName property:上面的代码将导致作者实体被标记为已修改,并生成 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'

Reference: Read more参考: 阅读更多

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM