簡體   English   中英

實體框架附加/更新混淆(EF Core)

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM