程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> 關於.NET >> ADO.NET Entity Framework深入分析, Part 7 – Change Tracking

ADO.NET Entity Framework深入分析, Part 7 – Change Tracking

編輯:關於.NET

ObjectStateManager – 對象狀態管理器

我們已經知道如何增加、更新和刪除實體記錄,並將更改數據庫記錄。Entity Framework 通過Object Context 控制的ObjectStateManager 對象來跟蹤變更,ObjectStateManager 將跟蹤所有對實體對象的變更,在調用SaveChanges() 方法時,執行相應的T-SQL腳本。

ObjectStateManager比LINQ to SQL中DataContext 的變更跟蹤功能更先進。下面,我們詳細了解如何顯示有用的變更跟蹤信息。

ObjectStateManager 有2個有趣的方法:

GetObjectStateEntries() – 返回給定狀態下ObjectStateEntry 集合對象。

GetObjectStateEntry() – 返回給定實體的ObjectStateEntry 對象。

一個ObjectStateEntry 對象包含了一些有用的數據,根據狀態不同(Added, Modified, Deleted)有不同的變化。

在下面的示例中,首先檢索特定的Product記錄,修改其中3個屬性,並調用GetObjectStateEntries(EntityState.Modified) 方法,返回所有更新實體的列表,並進一步遍歷ObjectStateEntry集合,顯示實體名稱,Key/Value,初始值和當前值。

示例代碼如下:

Product product1 = context.Product.FirstOrDefault(p => p.ProductID == 1004);

            if (product1 != null)

            {

                product1.Color = "Black";

                product1.StandardCost = 20;

                product1.ListPrice = 25;

            }

            var objectStateEntries = context.ObjectStateManager.GetObjectStateEntries(EntityState.Modified);

            foreach (var entry in objectStateEntries)

            {

                Console.WriteLine("{0} - {1} - {2}",

                    entry.EntityKey.EntityContainerName,

                    entry.EntityKey.EntitySetName.ToString(),

                    entry.EntityKey.EntityKeyValues.First().Key + " = " +

                    entry.EntityKey.EntityKeyValues.First().Value);

                for (int i = 0; i < entry.OriginalValues.FieldCount; i++)

                {

                    Console.WriteLine("\t {0} -> {1}", entry.OriginalValues[i], entry.CurrentValues[i]);

                }

            }

輸出結果如下:

AdventureWorksLTEntities - Product - ProductID = 1004

1004 -> 1004

def -> def

abc -> abc

Black -> Black

20.0000 -> 20

25.0000 -> 25

->

->

2008-11-3 11:33:30 -> 2008-11-3 11:33:30

->

->

->

->

5b2cfc8c-8344-4431-8c2c-651358cce331 -> 5b2cfc8c-8344-4431-8c2c-651358cce331

2008-11-3 11:33:30 -> 2008-11-3 11:33:30

MergeOption.NoTracking 選項

如果僅僅檢索數據,並不需要更新數據,則可以通過使用MergeOption.NoTracking 取消變更跟蹤。這樣,就不會使用ObjectStateManager,減少執行查詢的時間,所有返回的實體將是分離的狀態(detached state)。在ASP.NET web application 或在WinForms / WPF Grids 控件中以只讀方式顯示數據時,NoTracking 是一個比較好的選擇。

在使用對象服務(Object Services)和Entity SQL時,需要調用ObjectQuery 的一個重載構造函數,其中第三個參數是MergeOption 枚舉。默認的行為是 AppendOnly,可以改變為 NoTracking。

示例代碼如下:

var sql = "SELECT VALUE model FROM AdventureWorksLTEntities.Model AS model";

var query = new ObjectQuery<Model>(sql, context, MergeOption.NoTracking);

foreach (var mod in query)

Console.WriteLine("{0} {1} {2}", mod.ModelID, mod.Name, mod.ModifiedDate);

輸出結果如下:

1 Classic Vest 2003-6-1 0:00:00

2 Cycling Cap 2001-6-1 0:00:00

3 Full-Finger Gloves 2002-6-1 0:00:00

4 Half-Finger Gloves 2002-6-1 0:00:00

5 HL Mountain Frame 2001-6-1 0:00:00

6 HL Road Frame 1998-5-2 0:00:00

在使用LINQ to Entities 或者與Entity SQL 一起使用的CreateQuery<T> 工廠方法時,不能直接傳入NoTracking 選項,你需要對整個EntitySet 設置MergeOption 選項。

示例代碼如下:

var categories = from c in this.context.Category

where c.ParentCategory.Name != null

orderby c.Name

select c;

context.Category.MergeOption = MergeOption.NoTracking;

return categories.ToList();

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved