EF4在N-Tier下的应用:中间层如何更新实体
转http://www.cnblogs.com/hackee/archive/2009/11/16/1603934.html
在多层应用(N-Tier)环境中,如何更新对象是一个复杂的话题。在这篇文章中,讨论了最新的ADO.NET Entity Framework 4 Beta 2(以下简称EF4)如何实现在多层应用中,中间层如何完成对象的更新操作。下面例子对于Web应用(如ASP.NET MVC)来说尤其具有参考价值,因为在Web环境下,中间层和客户端无法共享实体对象,因而无法利用跟踪实体发生的变化。
新的EF4为多层应用环境提供了许多新的工具和方法,包括:ApplyCurrentValues,ApplyOriginalValues,SetModifiedProperty,GetUpdatableOriginalValues,CurrentValues属性,等等。例如,EF 1中,如果需要将实体标记为”修改“状态,需要在实体本身以及实体的各个属性上均调用SetModified,现在仅需要调用ObjectStateManager的ChangeObjectState,便可以将一个Attached实体的所有属性均标记为”修改“状态。
例子
下面的例子中,Product实例的新旧值均传递给了UpdateProductChanges方法 ,这样可以避免到数据库中查询或在内存中保存待更新对象的旧值。对于ASP.NET MVC,originalProduct对象可以保存在Form的某个Hidden元素中,提交Form时将其一并传递给Action。
下面的例子展示了在没有给出旧的对象的情况下,如何进行对象更新 :
1 private static void ApplyProductUpdates(Product updatedProduct)
2 {
3 // Define an ObjectStateEntry and EntityKey for the current object.
4 EntityKey key;
5 object originalProduct;
6
7 using (NorthwindEntities northwindContext =
8 new NorthwindEntities())
9 {
10 try
11 {
12 // Create the detached object's entity key.
13 key = northwindContext.CreateEntityKey("Products", updatedProduct);
14
15 // Get the original item based on the entity key from the context
16 // or from the database.
17 if (northwindContext.TryGetObjectByKey(key, out originalProduct))
18 {
19 // Call the ApplyCurrentValues method to apply changes
20 // from the updated item to the original version.
21 northwindContext.ApplyCurrentValues(
22 key.EntitySetName, updatedProduct);
23 }
24
25 northwindContext.SaveChanges();
26 }
27 catch (InvalidOperationException ex)
28 {
29 Console.WriteLine(ex.ToString());
30 }
31 }
32 }
[更新]
在上面的第二种方法中,实体的原值是从数据库或当前Context中获取的,在ASP.NET MVC中,往往是在Action中创建一个新的Context,在这种应用环境下,原值基本上都是从数据库中获取。有什么方法能够既不需要提供实体的原值,也能够避免从数据库中检索原值所带来的额外负载呢?
新的EF4为我们提供了一个便捷的方法,
1 private static void ApplyProductUpdates(Product updatedProduct) {
2 using (NorthwindEntities northwindContext = new NorthwindEntities()) {
3 try {
4 northwindContext.Attach(updatedProduct);
5 northwindContext.ObjectStateManager.ChangeObjectState(updatedProduct, EntityState.Modified);
6
7 northwindContext.SaveChanges();
8 }
9 catch (InvalidOperationException ex) {
10 Console.WriteLine(ex.ToString());
11 }
12 }
13 }
而在EF1中,则需要这样:
1 private static void ApplyProductUpdates(Product updatedProduct) {
2 using (NorthwindEntities northwindContext = new NorthwindEntities()) {
3 try {
4 northwindContext.Attach(updatedProduct);
5 var stateEntry = context.ObjectStateManager.GetObjectStateEntry(updatedProduct);
6 foreach (var propertyName in from fm in stateEntry.CurrentValues.DataRecordInfo.FieldMetadata select fm.FieldType.Name) {
7 stateEntry.SetModifiedProperty(propertyName);
8 }
9
10 northwindContext.SaveChanges();
11 }
12 catch (InvalidOperationException ex) {
13 Console.WriteLine(ex.ToString());
14 }
15 }
16 }
1 private static void ApplyProductUpdates(Product originalProduct,
2 Product updatedProduct)
3 {
4 using (NorthwindEntities northwindContext =
5 new NorthwindEntities())
6 {
7 try
8 {
9 // Attach the original item to the object context.
10 northwindContext.Attach(originalProduct);
11
12 // Call the ApplyCurrentValues method to apply changes
13 // from the updated item to the original version.
14 northwindContext.ApplyCurrentValues("Products",
15 updatedProduct);
16
17 northwindContext.SaveChanges();
18 }
19 catch (InvalidOperationException ex)
20 {
21 Console.WriteLine(ex.ToString());
22 }
23 }
24 }