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

  • 相关阅读:
    JAVA中数据类型转换
    PADS故障解决
    KEIL4.12中添加ULINK2的支持
    身份证号码规则
    用19种编程语言写Hello World
    30年的Hello world
    Java Annotation手册
    线控耳机原理图
    破解EXCEL2007的密码
    [野狐行][内存辅助][二重门更新中][2016/6/1]
  • 原文地址:https://www.cnblogs.com/FredTang/p/2423724.html
Copyright © 2011-2022 走看看