无法使用Entity Framework 6获取存储过程结果

时间:2016-09-09 15:57:18

标签: c# sql-server entity-framework stored-procedures entity-framework-6

我有一个存储过程,它会返回01,具体取决于我的数据库中是否存在指定的电子邮件地址:

CREATE PROCEDURE [DatabaseSchema].[EmailAddressIsDuplicate] (@emailAddress nvarchar(255))
AS
BEGIN
    SET NOCOUNT ON;

    IF EXISTS(
        SELECT *
        FROM [DatabaseSchema].[EmailUpdatesRegistrant]
        WHERE EmailAddress = @emailAddress
    )
        RETURN 1
    ELSE
        RETURN 0

    RETURN 0
END

GO

我正在尝试从Entity Framework 6数据库上下文中获取此存储过程的结果:

using (DatabaseContext dbContext = new DatabaseContext())
{
    ObjectParameter param = new ObjectParameter("emailAddress", typeof(bool));
    var result = dbContext.EmailAddressIsDuplicate(emailAddress); 
}

我遇到了很多错误。

错误#1:使用上面的代码,var result始终设置为-1。

错误#2:我尝试导航到Edit Function Import并将Returns a Collection Of设置为Boolean标量值。这会引发以下错误:

  

商店数据提供程序返回的数据读取器没有足够的列用于请求的查询。

错误#3:我回去并将Edit Function Import返回值设置为None。然后我尝试了以下代码:

using (DatabaseContext dbContext = new DatabaseContext())
{
    var p = new SqlParameter("@emailAddress", emailAddress);
    var result = dbContext.Database.SqlQuery<bool>("DatabaseSchema.EmailAddressIsDuplicate", p);
}

没有立即出现错误,但我不知道我是否可以从var result派生有用的数据。尝试将result强制转换为bool会引发以下错误:

  

无法将类型'System.Data.Entity.Infrastructure.DbRawSqlQuery'转换为'bool'

有关如何查看此存储过程结果的任何想法(01)?

4 个答案:

答案 0 :(得分:1)

您可以尝试在存储过程签名中添加输出参数(@result):

CREATE PROCEDURE [DatabaseSchema].[EmailAddressIsDuplicate]
    (@emailAddress nvarchar(255), @result bit out)
AS
BEGIN
    SET NOCOUNT ON;

    IF EXISTS(SELECT *
              FROM [DatabaseSchema].[EmailUpdatesRegistrant]
              WHERE EmailAddress = @emailAddress)
       SET @result = 1
    ELSE
       SET @result = 0

    RETURN @result
END
GO

(您必须相应地重新定义您的EF模型函数定义)

using (DatabaseContext dbContext = new DatabaseContext())
{
    ObjectParameter isDuplicate = new ObjectParameter("isDuplicate", typeof(bool)); 
    var result = dbContext.EmailAddressIsDuplicate(emailAddress, isDuplicate);

    bool emailIsDuplicate = (bool)isDuplicate.Value;.    
}

如果要使用out参数直接调用存储过程,可以遵循以下建议: Database.SqlQuery calling stored procedure that has multiple output parameters

答案 1 :(得分:1)

原因 - EF的模板构建器(包括v6)错误地将SP设置为返回包含行计数而不是返回值的INT,因为它错误地调用了错误的ObjectContext.ExecuteFunction(找到在模板生成的类YourDatabaseEntities中,它是DBContext的子项。

为什么错误的ExecuteFunction? - 结果集错误地表示更改行的行数而不是返回值或输出参数,因为它调用了丢弃结果的不同ExecuteFunction。 ObjectContext.ExecuteFunction的flyover intellisense提示说&#34;执行存储过程.... 丢弃从该函数返回的任何结果;并返回受执行影响的行数&#34;而不是通常&#34;执行存储过程....带有指定参数的 &#34;。

为什么-1:我认为SET NOCOUNT ON导致SP没有返回计数结果,并且Microsoft的ExecuteFunction将其作为错误代码返回。

SP FIXES - 1)您必须注释掉SET NOCOUNT ON。 2)您必须更改存储过程以将SELECT命令作为最后一个语句而不是RETURN命令。

SOLUTION FIX - 1)修复SP后,从Function Imports文件夹和Data Store的SP文件夹中删除SP。 2)使用数据库中的&#34;更新模型将SP重新加载到EDMX中。 3)重建EDMX所在的所有数据项目。 4)退出Visual Studio并返回。 5)重建整体解决方案。

请参阅:Entity Framework (Database first) has incorrect return result from stored procedure

答案 2 :(得分:0)

使用参数将C#中的存储过程实现为一个值。

资源:https://msdn.microsoft.com/en-us/library/yy6y35y8(v=vs.110).aspx

这样,值可以存储到ExecuteReader的变量中。

将值添加到模型,类似于向属性添加值。可以从ActionResult调用存储过程。虽然这可能需要将存储过程添加到单独的层,但这只是运行存储过程并在之后将值添加到模型中。

答案 3 :(得分:-1)

试试这个

CREATE PROCEDURE [DatabaseSchema].[EmailAddressIsDuplicate] (@emailAddress nvarchar(255))
AS
BEGIN

        SELECT *
        FROM [DatabaseSchema].[EmailUpdatesRegistrant]
        WHERE EmailAddress = @emailAddress

    SELECT @@ROWCOUNT

END

GO


using (DatabaseContext dbContext = new DatabaseContext())
{ 
    var result = dbContext.Database.SqlQuery<int32>("exec  DatabaseSchema.EmailAddressIsDuplicate {0}", emailAddress).FirstOrDefault();
}

返回值中的任何其他0表示匹配,数字表示匹配数