前面的Part 1-3的文章,介绍了Entity Data Model、Entity 
                                          SQL、ObjectQuery、EntityCommand、LINQ to 
                                          Entities等等及其代码演示。Part 4主要演示如何通过相关技术或Debug工具,如SQL 
                                          Server Profiler、ToTraceString 方法、eSqlBlast 
                                          工具、LINQPad工具等等,来查看生成的T-SQL脚本。Part 5 
                                          演示如何新增、更新和删除数据实体,并相应更新数据库。Part 6 演示如何处理并发更新。本篇文章Part 
                                          7 介绍对象状态管理器 ObjectStateManager 及MergeOption.NoTracking 
                                          选项的用法。
                                        
                                        
                                         
                                          我们已经知道如何增加、更新和删除实体记录,并将更改数据库记录。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();