现在的位置: 首页 > 综合 > 正文

Entity Framework:存储过程 && EDM

2012年12月03日 ⁄ 综合 ⁄ 共 3969字 ⁄ 字号 评论关闭

     存储过程(sp)在EDM中的使用,相比于sp在EDM中的functionImport,似乎我更关心sp在EDMX文件中的表现.

     当我将存储过程sp GetOrder添加到EDM并完成FunctionImport之后,我就可以打开EDMX文件,查看关于GetOrder在ssdl(),csdl,c-s mapping中的实现:

    sdl:  <Function Name="GetOrder" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false"   ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">
          <Parameter Name="OrderID" Type="int" Mode="In" />
        </Function>

    关于function中的参数:对于IsComposable,BuiltIn这2个参数非常重要,用于指定返回结果将由存储过程的查询来返回,不需要生成其它的sql(针对linq,及时不需要被解释),因为均设为false,其它的没什么好说的。

   csdl:   <FunctionImport Name="GetOrders" EntitySet="Orders" ReturnType="Collection(NorthwindEFModel.Orders)">
            <Parameter Name="OrderID" Mode="In" Type="Int32" />
          </FunctionImport>

   ReturnType是一个Collection,我曾尝试将其修改为单一实体(让其返回一个非集合类型),不过在EF v1中并不支持.

    如果sp在edmx文件中就仅仅如此,那真的没什么可写了.不过并不仅仅如此,因为除了Return Type之外还有CommandText,out put 参数.

.CommandText

   在Function的xml节点下面有CommandText这个标签,CommandText可以让我们在ssdl层的function中自定义sql,而非仅仅局限于sp,在某些特定的场景中将sql嵌入ssdl层中要好过sp,毕竟sp是存在数据库上,这使得不仅要管理应用程序还需要管理数据,function中的CommandText属性可以2者达到某种平衡.下面是使用CommandText的例子

  ssdl:<Function Name="CustomerWithHighestSales" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">

          <!-- cannot use command text with functions. allows to execute multiple statement.-->

          <CommandText>

            select *

            from Customers

            where CustomerID = (

            select top 1 o.CustomerID

            from Orders o

            join OrderDetails od

            on o.OrderID = od.OrderID

            group by o.CustomerID

            order by SUM(od.UnitPrice * od.Quantity) desc )

          </CommandText>

        </Function> ssdl中的CommandText内容是找出HighestSales的Customer

   Csdl: <FunctionImport Name="CustomerWithHighestSales" EntitySet="Customers" ReturnType="Collection(NorthwindEFModel.Customers)">

          </FunctionImport>

   msdl: <FunctionImportMapping FunctionImportName="CustomerWithHighestSales" FunctionName="NorthwindEFModel.Store.CustomerWithHighestSales" />

  而使用CustomerWithHighestSales这个方法,和之前的并没有任何不同.

   using (NorthwindEFEntities context = new NorthwindEFEntities())

            {

                var customer = context.CustomerWithHighestSales().First();

                Console.WriteLine("{0}", customer.CustomerID);

            }

  

  .out put 参数,当我一直在调用sp相应的方法是,总是传入参数,所以我很想尝试对于带有out put参数的sp的处理,不过很遗憾的是在EF v1中不直接支持带有out put参数的sp.当我在数据库创建一个带参数的sp getTotolOrdersForCust,在模型浏览器进行FunctionImport后,我查看edmx文件没有看到1任何相关getTotolOrdersForCust的内容,后来在EF社区得到了EF v1不支持带out put参数的sp.当然只是说不直接支持,但 可以通过自定义来解决

  Ssdl: <Function Name="getTotolOrdersForCust" Aggregate="false" BuiltIn="false" NiladicFunction="false" IsComposable="false"  ParameterTypeSemantics="AllowImplicitConversion" Schema="dbo">

          <Parameter Name="CustomerID" Type="nchar" Mode="In" />

          <Parameter Name="Count" Type="int" Mode="Inout" />       

        </Function>

  Csdl: <FunctionImport Name=" getTotolOrdersForCust "> 

       <Parameter Name="CustomerID" Type="nchar" Mode="In" />

       <Parameter Name="Count" Type="int" Mode=="InOut" /></FunctionImport>

 Msdl: <FunctionImportMapping FunctionImportName="getTotolOrdersForCust" FunctionName=" NorthwindEFModel.Store.getTotolOrdersForCust" />

 而剩下的代码则可以写成这样:

 public void CustomerWithHighestSales(string customerID, ref int totalOrders)

        {

            var dbparams = new DbParameter[] {

                new EntityParameter { ParameterName = "CustomerID", DbType = DbType.String, Value = customerID },

                new EntityParameter { ParameterName = "Count", DbType = System.Data.DbType.Int32, Direction = ParameterDirection.Output }

             };

            DbCommand cmd = this.Connection.CreateCommand();

            cmd.CommandType = System.Data.CommandType.StoredProcedure;

            cmd.Parameters.AddRange(dbparams);

            cmd.CommandText = this.DefaultContainerName + "." + "getTotolOrdersForCust";

            if (cmd.Connection.State == System.Data.ConnectionState.Closed)

            { cmd.Connection.Open(); }

            cmd.ExecuteNonQuery();

            totalOrders = Convert.ToInt32(dbparams[1].Value);

 

        }

抱歉!评论已关闭.