如何使用Entity Framework 4访问存储过程的"结果","消息"和"返回值"?

new*_*ton 7 .net c# entity-framework entity-framework-4 c#-4.0

如何使用Entity Framework 4.4和C#4.0访问存储过程的"结果","消息"和"返回值"?

以下是带有三个参数的存储过程.当我运行存储过程时,我希望能够以这样或那样的方式访问"结果","消息"和"返回值"的所有三个值.

有人可以帮我弄清楚如何用EF做到这一点吗?使用EF生成的代码,我似乎能够访问的是查询的"结果"(返回的行)

存储过程

USE [THIS_DB]  
GO  

SET ANSI_NULLS ON  
GO  
SET QUOTED_IDENTIFIER ON  
GO  

ALTER PROCEDURE [dbo].[THIS_PROCEDURE]  
    @FIRST_PARAM CHAR(17) = NULL,  
    @SECOND_PARAM CHAR(2) = NULL,  
    @THIRD_PARAM CHAR(5) = NULL  
AS  
BEGIN  
    SET NOCOUNT ON;  
    DECLARE @ReturnValue INT = 0;  
    IF COALESCE(@SECOND_PARAM, 'XX') NOT IN ('XX', 'YY')  
    BEGIN  
        RAISERROR('Invalid @SECOND_PARAM value: %s; @SECOND_PARAM mXXt be XX or YY.', 2, 1, @SECOND_PARAM ) WITH SETERROR;  
        SET @ReturnValue = -50100;  
    END  
    IF COALESCE(@SECOND_PARAM, 'XX') = 'YY'  
    BEGIN  
        RAISERROR('@SECOND_PARAM value: %s; YY is valid, but currently is not supported, returning XX results.', 2, 1, @SECOND_PARAM) WITH SETERROR;  
        SET @ReturnValue = -50105;  
    END  
    IF COALESCE(@THIRD_PARAM, 'XX-EN') NOT IN ('XX-EN')  
    BEGIN  
        RAISERROR('Invalid @THIRD_PARAM value: %s; @THIRD_PARAM mXXt be XX-EN.', 2, 1, @THIRD_PARAM) WITH SETERROR;  
        SET @ReturnValue = -50101;  
    END  
    SELECT DISTINCT  
        THESE.VALUES  
        FROM dbo.THIS_TABLE  
        WHERE THESE.CONDITIONS;  

    IF @@ROWCOUNT = 0  
    BEGIN  
        DECLARE @SP_MATCHCOUNT INT  

        EXEC @SP_MATCHCOUNT = [dbo].[MATCHTABLE] @PATTERNH = @PATTERN  
        IF @SP_MATCHCOUNT > 0  
        BEGIN  
            RAISERROR('Mapping from HERE to HERE not found for PATTERN: %s.', 2, 1, @PATTERN) WITH SETERROR  
            SET @ReturnValue = -50103;  
        END  
        ELSE  
        BEGIN  
            RAISERROR('PATTERN Pattern not found for PATTERN: %s.', 2, 1, @PATTERN) WITH SETERROR  
            SET @ReturnValue = -50104;  
        END  
    END  
    RETURN @ReturnValue  
END  
Run Code Online (Sandbox Code Playgroud)

public virtual ObjectResult<THIS_PROCEDURE_RESULT> THIS_PROCEDURE_METHOD(string FIRST, string SECOND, string THIRD)  
{  
    var FIRST_PARAM = FIRST != null ?  
        new ObjectParameter("FIRST", FIRST) :  
        new ObjectParameter("FIRST", typeof(string));  

    var SECOND_PARAM = SECOND != null ?  
        new ObjectParameter("SECOND", SECOND) :  
        new ObjectParameter("SECOND", typeof(string));  

    var THIRD_PARAM = THIRD != null ?  
        new ObjectParameter("THIRD", THIRD) :  
        new ObjectParameter("THIRD", typeof(string));  

    return ((IObjectContextAdapter)this).ObjectContext.ExecuteFunction<THIS_PROCEDURE_RESULT>("THIS_PROCEDURE", FIRST_PARAM, SECOND_PARAM, THIRD_PARAM);  
}  
Run Code Online (Sandbox Code Playgroud)

Dev*_*ime 13

所以,首先要做的事情是:-)只是想在回答问题的3个部分之前确保我们在同一页面上.EF被设计为ORM(对象关系映射器).这意味着它的目的是将关系数据转换为代码对象(反之亦然).它用于此的机制是结果集(不是返回值).因此,EF中的大部分管道都是专门设计用于对结果集进行操作,也是为了获取这些结果集而自动生成SQL.但是,由于人们要求它,EF现在具有执行存储过程的能力,但是这种能力并不全面,并且对产品的主要功能有一定的副作用.话虽如此,EF确实使用了ADO.NET,这就是你要获得答案的地方,因为ADO.NET确实可以处理你的所有场景.

第一个问题 - 如何获得结果.在这种情况下,EF将执行SP,并且可能会将其映射到具有与结果列匹配的属性的某个对象.这意味着EF将创建一个对象的集合(可枚举的查询结果集更精确),每个对象代表结果中的一行数据.在您的情况下,您的方法的返回是ObjectResult.ObjectResult是一个对象集合,每个项目的类型为THIS_PROCEDURE_RESULT,而后者又为结果的每个映射列都有一个属性.

第二个问题 - 如何获取消息.如果使用Raiserror具有一定范围的严重性,将导致ADO.NET抛出异常(类型为SqlException).EF只是表面(通过)该错误.该SQLException实例将包含所有错误和消息信息.要查看它,您只需捕获错误:

try
{
    // call EF SP method here...
}
catch(SqlException se)
{
    Debug.WriteLine(se.Message);
}
catch(Exception e)
{
    // all non-DB errors will be seen here...
}
Run Code Online (Sandbox Code Playgroud)

但是,如果Raiserror语句具有警告或信息严重性,则ADO.NET不会抛出异常.在这种情况下,您必须使用连接对象的事件来查看数据库中的信息和警告消息.要在EF中执行此操作,您必须从EF对象上下文获取EntityConnection,然后从EntityConnection获取存储连接.如果您使用的是SQL Server(SqlClient ADO.NET提供程序),那么这将是一个SqlConnection实例.该实例包含一个名为InfoMessage的事件.您可以将事件处理程序连接到该事件以捕获消息.有关详细信息,请访问:http://support.microsoft.com/kb/321903

最后一个问题 - 如何获得回报值.这个会很糟糕.根据我的第一段,EF并不是真正设计为任意处理SP调用.虽然它会将结果集映射到对象集合,但它不处理来自SP的返回值.您必须使用不带EF层的ADO.NET才能访问SqlCommand对象的Parameters集合.其中一个参数是参数类型ReturnValue,它将包含返回值本身.