目前,EF对存储过程的支持并不完善。存在以下问题:

l         EF不支持存储过程返回多表联合查询的结果集。

l         EF仅支持返回返回某个表的全部字段,以便转换成对应的实体。无法支持返回部分字段的情况。

l         虽然可以正常导入返回标量值的存储过程,但是却没有为我们自动生成相应的实体.cs代码,我们还是无法在代码中直接调用或使用标量存储过程

l         EF不能直接支持存储过程中Output类型的参数。

l         其他一些问题。

本节,我们将学习如何手动添加/修改存储过程,如何使EF能够支持Output类型的参数。

l         添加/修改存储过程

有时候,某个SQL语句比较复杂,但是数据库中又没有定义相应的存储过程。这个时候,我们又想使上层代码比较简单、方便的方式来完成此项任务。那么,此时,我们便可以手工在实体模型(.edmx文件)中添加自己需要的存储过程了。这样既方便上层调用又方便后期的修改。

以手动修改实体模型edmx文件,添加名为CustomerByCommandText的存储过程为例。具体步骤如下:

修改实体模型文件,找到ssdl部分,添加如下代码:

<Function Name="CustomerByCommandText" Aggregate="false" BuiltIn="false"NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion"Schema="dbo" >

<CommandText>

select c.* from Customers c,Orders o where c.CustomerID=o.CustomerID

</CommandText>

</Function>

然后,再找到csdl部分,添加如下代码:

<FunctionImport Name="CustomerByCommandText" EntitySet="Customers"ReturnType="Collection(NorthwindModel.Customers)"></FunctionImport>

接着,找到msl部分,添加如下代码:

<FunctionImportMapping FunctionImportName="CustomerByCommandText"FunctionName="NorthwindModel.Store.CustomerByCommandText"/>

最后,在实体模型的.cs文件里面,添加一个执行此存储过程的方法,代码如下:

public global::System.Data.Objects.ObjectResult<Customers> GetCustomerByCommandText()

{

return base.ExecuteFunction<Customers>("CustomerByCommandText");

}

至此,修改完毕。

现在,我们就可以在代码使用刚才手工定义的存储过程了。如下代码所示:

[Test]

public void GetCustomerByCmdText()

{

using (var db = new NorthwindEntities())

{

var csts = db.GetCustomerByCommandText().Take(10).Skip(0);

foreach (var c in csts)

Console.WriteLine(c.CustomerID);

}

}

其实,关键的地方就是CommandText这个部分的内容,它里面就是要执行的SQL语句。另外,我们可以在修改实体模型emdx文件的同时,我们可以看到所有的实体类查询的SQL语句命令都可以在edmx文件里找到,我们都可以进行相应的修改。

l         Output类型参数

在实际应用当中,很多时候,我们需要使用output类型的存储过程参数,以便返回我们需要的值。但是,目前,EF不能直接支持output类型的存储过程参数。为此,我们需要对实体模型进行修改,以便使其支持output类型的输出参数。具体过程如下:

在数据库中建立一个为名的GetNameByCustomerId存储过程,代码如下:

CREATE PROCEDURE GetNameByCustomerId

@CustomerId varchar(5),

@ContactName varchar(30) output

AS

BEGIN

SET NOCOUNT ON;

SELECT @ContactName=ContactName

FROM Customers

WHERE CustomerID=@CustomerId;

END

然后,开始修改实体模型edmx文件。

先找到ssdl定义的部分,添加如下代码:

<Function Name="GetNameByCustomerId" Aggregate="false" BuiltIn="false"NiladicFunction="false" IsComposable="false" ParameterTypeSemantics="AllowImplicitConversion"Schema="dbo">

<Parameter Name="CustomerId" Type="varchar" Mode="In" MaxLength="5"></Parameter>

<Parameter Name="ContactName" Type="varchar" Mode="Out" MaxLength="30"></Parameter>

</Function>

接着,在找到csdl定义的部分,添加如下代码:

<FunctionImport Name="GetNameByCustomerId">

<Parameter Name="CustomerId" Mode="In" Type="String" MaxLength="5"></Parameter>

<Parameter Name="ContactName" Mode="Out" Type="String" MaxLength="30"></Parameter>

</FunctionImport>

最后,找到msl定义的部分,添加如下代码:

<FunctionImportMapping FunctionImportName="GetNameByCustomerId"FunctionName="NorthwindModel.Store.GetNameByCustomerId"></FunctionImportMapping>

至此,实体模型emdx文件修改完毕。

接下来,我们需要在实体模型的.cs文件中,增加相应的调用方法。代码如下:

public partial class NorthwindEntities1

{

//执行GetNameByCustomerId的方法

public void GetNameByCustomerId(string CustomerId, out string ContactName)

{

ContactName = string.Empty;

var Pars = new System.Data.EntityClient.EntityParameter[]

{

new System.Data.EntityClient.EntityParameter{ ParameterName="CustomerId", DbType=System.Data.DbType.String,Value=CustomerId},

new System.Data.EntityClient.EntityParameter{ParameterName="ContactName", DbType=System.Data.DbType.String, Direction=System.Data.ParameterDirection.Output}

};

this.ExecuteNonQuery("GetNameByCustomerId", Pars);

ContactName = Pars[1].Value.ToString();

}

//辅助方法,执行SQL命令

private void ExecuteNonQuery(string functionName, System.Data.EntityClient.EntityParameter[] parameters)

{

System.Data.EntityClient.EntityCommand cmd = ((System.Data.EntityClient.EntityConnection)this.Connection).CreateCommand();

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

cmd.Parameters.AddRange(parameters);

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

try

{

if (cmd.Connection.State != System.Data.ConnectionState.Open)

cmd.Connection.Open();

cmd.ExecuteNonQuery();

}

catch (System.Exception)

{

throw;

}

finally

{

cmd.Connection.Close();

}

}

}

现在,所有的修改工作都做完了。接下来,我们就可以在代码中直接调用此存储过程了。示例代码如下:

[Test]

public void OutputTest()

{

using (var db = new NorthwindModel.NorthwindEntities1())

{

string contactname = string.Empty;

db.GetNameByCustomerId("ALFKI", out contactname);

Assert.IsTrue(!string.IsNullOrEmpty(contactname));

Console.WriteLine(contactname);

}

}

至此,我们便可以使用Output类型的输出参数了。

Entity Framework 学习中级篇3—存储过程(中)的更多相关文章

  1. Entity Framework 学习中级篇2—存储过程(上)

    目前,EF对存储过程的支持并不完善.存在以下问题: l         EF不支持存储过程返回多表联合查询的结果集. l         EF仅支持返回返回某个表的全部字段,以便转换成对应的实体.无法 ...

  2. Entity Framework 学习中级篇4—存储过程(下)

    在EF中,各个实体的插入.更新和删除也都通过使用存储过程来完成,以便提高点性能.这个类似于数据集.其步骤是:先定义存储过程,然后在VS的可视化设计器,设置存储过程映射即可. 下面,以为Supplier ...

  3. Entity Framework 学习中级篇1—EF支持复杂类型的实现

    本节,将介绍如何手动构造复杂类型(ComplexType)以及复杂类型的简单操作. 通常,复杂类型是指那些由几个简单的类型组合而成的类型.比如:一张Customer表,其中有FristName和Las ...

  4. Entity Framework学习初级篇2

    Entity Framework 学习初级篇2--ObjectContext.ObjectQuery.ObjectStateEntry.ObjectStateManager类的介绍 本节,简单的介绍E ...

  5. Entity Framework 学习初级篇--基本操作:增加、更新、删除、事务(转)

    摘自:http://www.cnblogs.com/xray2005/archive/2009/05/17/1458568.html 本节,直接写通过代码来学习.这些基本操作都比较简单,与这些基本操作 ...

  6. Entity Framework 学习初级篇1--EF基本概况

    转自:http://www.cnblogs.com/Tally/archive/2012/09/14/2685011.html 最近在学习研究微软的EF,通过这时间的学习研究,感觉这个EF目前来说还不 ...

  7. Entity Framework 学习初级篇7--基本操作:增加、更新、删除、事务

    本节,直接写通过代码来学习.这些基本操作都比较简单,与这些基本操作相关的内容在之前的1至6节基本介绍完毕. l           增加: 方法1:使用AddToXXX(xxx)方法:实例代码如下: ...

  8. Entity Framework学习初级篇1--EF基本概况《转》

    最近在学习研究微软的EF,通过这时间的学习研究,感觉这个EF目前来说还不是很完善,半成品.不过,据说在.Net4.0中,微软将推荐使用此框架,并会有所改善.而且,现在基本上所有数据库均提供了对EF的支 ...

  9. Entity Framework 学习初级篇2--ObjectContext类的介绍

    转自:http://www.cnblogs.com/Tally/archive/2012/09/14/2685014.html 本节,简单的介绍EF中的ObjectContext.ObjectQuer ...

随机推荐

  1. ubuntu 安装python mysql模块

    Installation Starting with a vanilla Lucid install , install pip and upgrade to the latest version: ...

  2. JS实现点击弹出对应的索引

    如果这样写的话 ,弹出来一直是2,原因 这个i ,循环已经结束,i 的值已经是2了,所以需要再前面添加: items[i].index=i;    //添加一个属性  ,技术一下 这个索引值 aler ...

  3. 第七十一,CSS颜色与度量单位

    CSS颜色与度量单位 学习要点: 1.颜色表方案 2.度量单位 本章主要探讨HTML5中CSS颜色和度量单位等问题,包括颜色的选取方式.相对长度和绝对长度等.   一.颜色表方案 1 颜色的表现形式主 ...

  4. Sass与Compress实战:第六章

    概要:介绍Compass如何让你从本地开发原型轻松转移到正产环境的网址或Web应用中. 本章内容: ● CSS精灵的历史和基本原则 ● Compass混合器让精灵自动化 ● 自定义精灵图片和CSS输出 ...

  5. ggplot2 分面相关设置(facet)

    分面设置在ggplot2应该也是要经常用到的一项画图内容,在数据对比以及分类显示上有着极为重要的作用, 下面是两个经常要用到的分面函数. facet_wrap(facets, nrow = NULL, ...

  6. POJ 2039 To and Fro

    To and Fro Description Mo and Larry have devised a way of encrypting messages. They first decide sec ...

  7. HDU 1242 Rescue(BFS),ZOJ 1649

    题目链接 ZOJ链接 Problem Description Angel was caught by the MOLIGPY! He was put in prison by Moligpy. The ...

  8. [ An Ac a Day ^_^ ] hrbust 2291 Help C5 分形

    开博客这么久从来没写过自己学校oj的题解 今天写一篇吧 嘿嘿 原题链接:http://acm.hrbust.edu.cn/index.php?m=ProblemSet&a=showProble ...

  9. jQuery 事件 - bind() 方法

    定义和用法 bind() 方法为被选元素添加一个或多个事件处理程序,并规定事件发生时运行的函数. 实例1(一个事件) 记得把js引用地址换掉 当点击鼠标时,隐藏或显示 p 元素: <html&g ...

  10. 多线程---其他方法 停止线程、守护线程、join方法

    第三方停止线程: 原来是stop(),因为该方法有些问题,所以被interrupt()方法取代,它的用途跟机制是 当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除,强制让线程恢复到 ...