zoukankan      html  css  js  c++  java
  • C# 调用数据库函数 转摘

    之前一段时间对存储过程(store proceduce
    简称sp)在EF中的使用非常感兴趣,所以看了一些相关的资料,也断断续续的做 了一些练习。最近2个月下班后就不愿意再写代码了,所以也只能在周末睡眠足够之后做些感兴趣的事.关于sp在EF的使用,最基本资料就是msdn了,不过中午睡醒起来看到Ado.team
    blog上出现了一篇文章关于EF的msdn添加了新
    内容,其中有关于如何自定义function,DefineQuery。

         使用EF也有一段时间了,不过对于entity
    client的了解却知之甚少,因为通过设计EDM,访问ObjectContext,可以说在某种程度上甩掉了那一层层所谓的包装。不过之前学习存储过程sp在EF中的使用时,我发现在某些时候EDM并不能完全解决.如果对于sp在EDM的映射有一些了解的话,可以很清楚的明白,在EDM中映射一个sp返回的类型包括:Entity
    Type,Scalars
    Type,None;这三中类型分别对应的sp返回内容对应到数据库,表的层面就是:(Entity)一张表的所有字段或若干字段(必须包括主键);(Scalars)返回一个常量(int,
    varchar)可以是数据库的一个字段,可以是sum,count,left...等函数操作的结果;(none)自然是什么都不返回.这里自然就有一个严重的问题,对于返回(multiple
    result sets)多张表的结果集怎么办?似乎entity
    client能做到,于是我做了一些尝试:


        //execute stored proceduce with entityclient
            public static IList<OrderDetails> entityClientCommand(NorthWind.NorthwindEFEntities context, int OrderID)
            {
                EntityConnection conn
    = context.Connection as
    EntityConnection;
                IList
    <OrderDetails> list = new List<OrderDetails>
    ();
               
    //EntityConnection expose a StoreConnection

                DbConnection dbconn = conn.StoreConnection;
                DbCommand dbcmd
    =
    dbconn.CreateCommand();
                dbcmd.CommandText
    = "GetOrderDetails"
    ;
                dbcmd.CommandType
    =
    CommandType.StoredProcedure;
                dbcmd.Parameters.Add(
    new SqlParameter("OrderID"
    , OrderID));
               
    if ((dbcmd.Connection.State ==
    ConnectionState.Closed))
                    dbcmd.Connection.Open();
               
    try

                {
                   
    using (DbDataReader reader = dbcmd.ExecuteReader())
                    {
                       
    while
    (reader.Read())
                        {
                           
    // Gets the column ordinal given the name of the column,

                            int IDOrdinal = reader.GetOrdinal("OrderID");
                           
    int UnitPriceOrdinal = reader.GetOrdinal("UnitPrice"
    );
                           
    int QuantityDOrdinal = reader.GetOrdinal("Quantity"
    );
                            OrderDetails od
    = new
    OrderDetails
                            {
                                OrderID
    =
    reader.GetInt32(IDOrdinal),
                                UnitPrice
    = reader.IsDBNull(UnitPriceOrdinal) ? decimal
    .Zero : reader.GetDecimal(UnitPriceOrdinal),
                                Quantity
    =
    reader.GetInt16(QuantityDOrdinal)
                            };
                            list.Add(od);
                        }
                    }
                }
               
    finally

                {
                   
    if (dbcmd.Connection.State == ConnectionState.Open)
                    {
                        dbcmd.Connection.Close();
                    }
                }
               
    return
    list;
            }


        
    从上面的这段代码可以看出我们可以使用EntityClient通过EntityConnection.StoreConnection来执行存储过程,因为StoreConnection是一个Dbconnection,所以的操作都和SqlClient很类似。通过DbDataReader将sp执行的结果具体为某一个实体或多个结果(上面的示例是返回一个实体,返回多个实体也肯定可以,不过需要更麻烦一些).尽管上面的做法可以处理返回内容为multiple
    result sets,但毕竟不能直接返回。不过后来看到了ms发布的EF Extension,在那个扩展包里就添加了对于sp返回multiple result
    sets的扩展。下面是我是我添加EF
    Extension之后在EntityClient调用sp的代码:


            //exec stored proceduce with EF Extension
            public static IEnumerable<OrderDetails> ExtensionCommand(NorthwindEFEntities context, int OrderID)
            {
                DbCommand cmd
    = context.CreateStoreCommand("GetOrderDetails", CommandType.StoredProcedure, new SqlParameter("@OrderID"
    , OrderID));
                var result
    = cmd.Materialize<OrderDetails>
    ().Bind(context);
               
    return
    result;
            }


     
    可以看出entityClientCommand与ExtensionCommand在代码量上的差距(entityClientCommand返回的OrderDetails实体的属性不是所有都有值,因为在DbDataReader里面我没有取出所有的column,否则会更多,再看看执行的效果


    using (NorthwindEFEntities context = new NorthwindEFEntities())
                {
                    IList
    <OrderDetails> list = StoredProduceExtension.entityClientCommand(context, 10248
    );
                   
    foreach (var item in
    list)
                    {
                        Console.WriteLine(
    "entityClientCommand:{0},{1},{2},{3}"
    , item.OrderID, item.UnitPrice, item.Quantity, item.EntityState);
                    }
                    IEnumerable
    <OrderDetails> enumerable = StoredProduceExtension.ExtensionCommand(context, 10248
    );
                   
    foreach (var item in
    enumerable)
                    {
                        Console.WriteLine(
    "ExtensionCommand:{0},{1},{2},{3}"
    , item.OrderID, item.UnitPrice, item.Quantity, item.EntityState);

                    }
                   
    //
    DisplayResults<OrderDetails>(enumerable);
                  
    // IEnumerable<OrderDetails> enumerable1 = StoredProduceExtension.ExtensionCommand1(context, 10248);


                }

          

      
    输出结果并不是完全一样,OrderDetails实体的内容是一样的,但是EntityState的值不一样,在EF中object
    services 的实体跟踪服务Tracking
    Service是一种很重要的行为,entityClientCommand返回的实体OrderDetails状态值是Detached表明实体存在,但是不在当前objectcontext对象的object
    Services
    跟踪之内。Unchanged表明已经被Tracking.具体关于查看EntityState值的说明。


        没想到已经是12.21了, 不过好像我还没有说明EF Extension是怎样处理mulplite
    result set,就已经很困了。对于EF Extension还有很多值得令人兴奋的地方。最后再介绍2篇学习sp&EF的文章Stored Procedure Mapping,Migrating from LINQ to SQL to the Entity

  • 相关阅读:
    使用javap分析Java的字符串操作
    使用javap深入理解Java整型常量和整型变量的区别
    分享一个WebGL开发的网站-用JavaScript + WebGL开发3D模型
    Java动态代理之InvocationHandler最简单的入门教程
    Java实现 LeetCode 542 01 矩阵(暴力大法,正反便利)
    Java实现 LeetCode 542 01 矩阵(暴力大法,正反便利)
    Java实现 LeetCode 542 01 矩阵(暴力大法,正反便利)
    Java实现 LeetCode 541 反转字符串 II(暴力大法)
    Java实现 LeetCode 541 反转字符串 II(暴力大法)
    Java实现 LeetCode 541 反转字符串 II(暴力大法)
  • 原文地址:https://www.cnblogs.com/FredTang/p/2423724.html
Copyright © 2011-2022 走看看