• 热门专题

DbContext API中使用SqlQuery和ExecuteSqlCommand获取存储过程的输入输出参数

作者:cesium  发布日期:2014-05-16 21:50:40
Tag标签:参数  过程  
  • 水平有限,欢迎指正。
    原文:http://blogs.msdn.com/b/diego/archive/2012/01/10/how-to-execute-stored-procedures-sqlquery-in-the-dbcontext-api.aspx

    在 Entity Framework 4.1中引入的DbContext API暴露了一些新的方法用于提供透传原生SQL给数据库执行查询和命令,比如 Database.SqlQuery<T>, 以及 Database.ExecuteSqlCommand。

    这些方法很重要不仅仅因为它们允许你执行自己的原生SQL查询,而且因为它们是当前你可以使用DbContext访问存储过程的主要方法,特别当你使用代码优先的开发模式。

    就实现而言,它们是在EF 4.0中加入的ObjectContext.ExecuteStoreQuery<T> 和 ObjectContext.ExecuteStoreCommand 的更简单变种。不管怎么说,关于这些方法可以做什么看上去还是会有一些困惑,尤其是它们支持的查询语法。

    简而言之我觉得以下几点可以说明这些方法是怎么工作的:
    1、传递给方法的查询文本会被设置给来自底层ADO.NET提供程序的DbCommand对象。
    2、DbCommand对象是通过设置CommandType属性值为CommandType.Text来执行的。
    3、此外,如果方法会返回你之前传递的对象类型的结果(例如SqlQuery<T>),这个结果是基于DbDataReader返回的值所提取的。

    你可以使用类似下面的语法,从一个存储过程返回的必要列中提取一个个人实体对象:

    1 var idParam = new SqlParameter { 
    2      ParameterName = "id",  
    3      Value = 1}; 
    4 var person = context.Database.SqlQuery<Person>( 
    5      "GetPerson @id",  
    6      idParam);

    为了方便这些方法同时也接收普通的原始类型参数。你可以使用类似“{0}”的语法在查询语句中使用这些参数。

    var person = context.Database.SqlQuery<Person>(
         "SELECT * FROM dbo.People WHERE Id = {0}", id);

    可是这些语法适用性有局限,而且可能你要做的一些事情需要更好的控制,像调用一个带输入输出参数的存储过程,或者参数不是基本类型,你必须使用数据源所支持的完整的SQL语法。

    我想分享一个关于使用输入输出参数的简单例子,这样可以更好的举例说明。

    在你的SQL Server数据库中创建一个(完整但没什么用)存储过程定义:

     1 CREATE PROCEDURE [dbo].[GetPersonAndVoteCount] 
     2  ( 
     3    @id int, 
     4    @voteCount int OUTPUT 
     5  ) 
     6  AS 
     7  BEGIN 
     8    SELECT @voteCount = COUNT(*) 
     9    FROM dbo.Votes 
    10    WHERE PersonId = @id; 
    11    SELECT * 
    12    FROM dbo.People 
    13    WHERE Id = @id; 
    14  END

    你可以写一段如下所示的代码执行它:

     1 var idParam = new SqlParameter {
     2       ParameterName = "id",
     3       Value = 1};
     4  var votesParam = new SqlParameter {
     5       ParameterName = "voteCount",
     6       Value = 0,
     7       Direction = ParameterDirection.Output };
     8  var results = context.Database.SqlQuery<Person>(
     9      "GetPersonAndVoteCount @id, @voteCount out",
    10       idParam,
    11       votesParam);
    12  var person = results.Single();
    13  var votes = (int)votesParam.Value;

    在上面这段代码中有几个注意事项:
    1、SqlQuery和ExecuteSqlCommand方法所支持的主要语法是被底层ADO.NET提供程序所支持的原生SQL语法。(有人在评论中提到SQL Server 2005必须在存储过程名前面加上EXEC关键字)。
    2、DbCommand是使用CommandType.Text(相对于CommandType.StoredProcedure)来执行的,这意味着它不会自动为存储过程绑定参数,尽管如此你还是可以使用普通的SQL语法来执行存储过程。
    3、你必须使用正确的语法来为存储过程传递一个输入输出参数,比如你需要在SQL语句中参数名称的后面增加一个“OUT”关键字。
    4、输入和输出参数仅仅在使用实际的DbParameters类型的时候起作用(在这个例子中我们使用SqlParameters因为我们使用SQL Server),SqlQuery和ExecuteSqlCommand所支持的普通类型对象是不支持输入输出参数的。(译注:SqlQuery和ExecuteSqlCommand的参数要么全部是DbParameter参数,要么全部是普通类型对象)
    5、在你访问输入输出参数你必须读整个返回结果(这个例子我们通过Single方法获取),但这是存储过程工作原理不是特定于EF的特性。

    一旦你学会了,你可以使用提供程序特定参数和底层数据源的原生SQL语法,你能够获取更多和你使用ADO.NET相同的灵活性,但是使用ADO.NET无法获得重用同一个EF所维护的数据库连接的便利性和直接从查询结果中获取对象的能力。

About IT165 - 广告服务 - 隐私声明 - 版权申明 - 免责条款 - 网站地图 - 网友投稿 - 联系方式
本站内容来自于互联网,仅供用于网络技术学习,学习中请遵循相关法律法规