10

问题

如何使用 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  

代码

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);  
}  
4

1 回答 1

16

所以,首先要做的事情是 :-) 在我回答问题的 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...
}

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

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

于 2013-05-06T20:37:26.700 回答