Entity Framework:存储过程 in entity client and EF Extension(二)

    接着早晨的写下去,为什么entityClientCommand和ExtensionCommand返回的结果的entity state不一样,原因是这行代码:var result = cmd.Materialize<OrderDetails>().Bind(context);的Bind()方法,在EF Extension 中的Bind()可以将entity加入到state manager.

  EF Extension中有的确许多令人兴奋的地方,为了解决最初的话题解决sp 返回Multiple result set的问题,我对NorthwindEF模型中的Order和OrderDtails实体进行扩展:

   首先添加对EF Extension .dll的引用,添加命名空间using Microsoft.Data.Extensions;由于EDM.Designer.cs是一个partial类,对一个分部(partial)类进行扩展是件容易的事,

1 namespace  NorthWind
2 {
3    public partial class NorthwindEFEntities : ObjectContext
4    {  }
5}

  只需要在上面的类中添加扩展方法即可,下面是实现Entity Set<T>,Materializer<T>的代码,

 1   EntitySet
34
35          Materializer

  至于为什么重新实现Materializer,而不是像ExtensionCommand中那样直接调用,只要的原因是我想使用EntitySet<T>,另外重新实现Materializer可以对sp的返回结果进行处理。通过 Materializer<KeyValuePair<Orders, OrderDetails>>将Mutilple result set中的内容分割为相对应的entity,这里顺便说一下我定义的存储过程getOrderAndOrderDetails是这样的:

select a.OrderID,a.OrderDate,a.ShippedDate,a.ShipName,b.UnitPrice,b.Quantity,b.Discount
from Orders as a left join OrderDetails as b
on a.OrderID=b.OrderID
where a.OrderID=@OrderID

    下面就是对Order,OrderDetails的包装的3个方法:

 1     public  Orders GetOrder( int  OrderID)
 2          {
 3            DbCommand cmd = this.CreateStoreCommand("GetOrder", CommandType.StoredProcedure, new SqlParameter("@OrderID", OrderID));//specify DBCcommand
 4            Orders order = s_orderMaterializer.Materialize(cmd).SingleOrDefault();// return a most single match for this store proceduce
 5            return this.OrderSet.FindOrAttach(order);// //method made order be a tracked entity too
 6        }

 7          public  OrderDetails GetOrderDetail( int  OrderID)
 8          {
 9            DbCommand cmd = this.CreateStoreCommand("GetOrderDetails", CommandType.StoredProcedure, new SqlParameter("@OrderID", OrderID));
10            OrderDetails orderDetails = s_orderDetailMaterializer.Materialize(cmd).FirstOrDefault<OrderDetails>();
11            // return this.OrderDetailSet.FindOrAttach(details);
12            return orderDetails;
13        }

14          /// <summary>
15        ///return Multiple result sets
16        /// </summary>
17        /// <param name="pid">Product id</param>
18        /// <returns>Product</returns>

19          public  Orders GetOrderAndOrderDetails( int  OrderID)
20          {
21            DbCommand command = this.CreateStoreCommand("getOrderAndOrderDetails", CommandType.StoredProcedure, new SqlParameter("@OrderID", OrderID));
22            //this store proceduce return Multiple result sets,contain Order and OrderDetails
23            Orders order = null;
24            var orderAndDetailSet = s_OrderAndOrderDetailsMaterializer.Materialize(command);
25            foreach (var orderAndDetail in orderAndDetailSet)
26            {
27                order = this.OrderSet.FindOrAttach(orderAndDetail.Key);
28                if (null != order)
29                {
30                    order.OrderDetails.Add(orderAndDetail.Value);
31                    // order.OrderDetails = this.OrderDetailSet.FindOrAttach(orderAndDetail.Value);
32                }

33
34            }

35            return order;
36        }

   我用下面的代码来来测试上面的方法

 1 Orders order  =  context.GetOrder( 10248 ); // a single entity order
 2             Console.WriteLine( " GetOrder:{0},OrderDetails Count:{2},Entity State:{1} " , order.OrderID, order.OrderDetails.Count, order.EntityState);
 3              // writer.WriteLine(order);
 4              // DisplayResults<Orders>(order);
 5             OrderDetails orderDetails  =  context.GetOrderDetail( 10248 ); // a silgle entity orderdetail
 6              // writer.WriteLine(orderDetails);
 7             Console.WriteLine( " GetOrderDetail:{0},Entity State:{1} " , orderDetails.OrderID, orderDetails.EntityState);
 8             Orders orderAndDetails  =  context.GetOrderAndOrderDetails( 10248 ); // entity order with orderdetail
 9             Console.WriteLine( " GetOrderAndOrderDetails:{0},OrderDetails Count:{1},Entity State:{2} " , orderAndDetails.OrderID, orderAndDetails.OrderDetails.Count, orderAndDetails.EntityState);
10

运行的结果是:

 

 GetOrder()方法返回的order对象由于没有attach相应的OrderDetails对象,因此 order.OrderDetails.Count 为0,而GetOrderAndOrderDetails()就不同,我们将getOrderAndOrderDetails返回的Mutilple result set中的内容进行分割为Order,OrderDetails,并将OrderDetails 对象添加到Orders,这样的效果等同于

contex.Orders.Include("OrderDetails").Where(q=>q.OrderID=10248).FirstOrDefault();至于为什么GetOrderDetail返回的结果Entity State为Detach,那是因为 我将这行代码this.OrderDetailSet.FindOrAttach(details)注释了.

   EF Extension真的让我太高兴了,可以说让我感受到了sp在EF用应用不再那么局限性。可能后面我还会写一些关于还有一些关于通过设计器的映射sp的随笔.最后说一下还是说一下哪儿可以找到EF Extension.

你可能感兴趣的:(framework)