2014-09-23 49 views
4

我正在使用C#中的实体框架,并且遇到了一个我已经跟踪到正在生成的SQL语句的问题。sp_executesql - 过程或函数期望不提供的参数

存储过程需要一个表值参数,但这似乎不是问题。

在SQL事件探查器,我看到正在执行的情况如下:

declare @p3 dbo.PositiveTypes 
insert into @p3 values(N'1') 
insert into @p3 values(N'4') 
insert into @p3 values(N'6') 

    exec sp_executesql N'dbo.SaveResults', 
         N'@resultID int, @positiveResults [PositiveTypes] READONLY', 
         @resultID=1, 
         @[email protected] 

这导致:

消息201,级别16,状态4,过程SaveResults,行0
程序或者函数'SaveResults'需要参数'@resultID',它没有提供。

这个程序的定义是:

ALTER PROCEDURE [dbo].[SaveResults] 
    @resultID int, 
    @positiveResults AS dbo.PositiveTypes READONLY 

用户定义的类型是:

CREATE TYPE [dbo].[PositiveTypes] AS TABLE(
    [TypeID] [tinyint] NULL 
) 

什么不对这个sp_executesql语法?为什么它认为@resultID在这里没有被正确传递?

+0

你是如何执行这个?有没有办法设置命令类型,以便EF知道它是一个存储过程? – 2014-09-23 20:21:15

+0

它正在EF中使用DbContext上的Database.ExecuteSqlCommand执行。它似乎认识到它是基于来自SQL Server的错误消息(“过程或函数”...期望“参数”)的存储过程。我试图确定sp_executesql语法究竟出了什么问题,然后根据需要后退工作以重新编写代码。 – Patrick 2014-09-23 20:28:36

+0

啊,好的。我认为可能有一些类似的命令类型[但似乎并非如此](http://msdn.microsoft.com/en-us/library/system.data.entity.database_methods(v = vs.113 ).aspx) – 2014-09-23 20:34:51

回答

4

您正在使用sp_executesql来运行SQL文本dbo.SaveResults。此T-SQL运行不带参数的过程dbo.SaveResults。现在你明白这条消息来自哪里。该怎么办?使用EXEC

EXEC dbo.SaveResults @resultID = 1234, @positiveResults = @p3 

或者窝电话:

exec sp_executesql N' 

    EXEC dbo.SaveResults @resultID = @resultID, @positiveResults = @positiveResults 

',N'@resultID int, @positiveResults [PositiveTypes] READONLY',@resultID=1,@[email protected] 

我已经缩进,使之更加清晰。据我所知,第二个变体没有用处。使用第一个。

+0

不幸的是,我正在使用的框架是使用sp_executesql生成语句。我有控制手动执行此操作,但宁愿让它继续生成语句。我试图将EXEC包含到生成的字符串中,但我得到了相同的结果..即exec sp_executesql N'EXEC dbo.SaveResults ...' – Patrick 2014-09-23 20:10:43

+0

发布可执行的repro(您使用SQL Profiler捕获的内容)。我不清楚现在的问题是什么。 – usr 2014-09-23 20:12:29

+0

repro与原始文章(第一个SQL代码块)中所述完全相同。这是通过SQL Profiler传入的内容。将N'dbo.SaveResults'更改为N'EXEC dbo.SaveResults'会导致相同的“期望参数@resultID”错误消息。 – Patrick 2014-09-23 20:18:02

1

我有同样的确切问题。

一旦你声明的命令,你必须指定命令类型

SqlCommand cmd = new SqlCommand(@"sp_name", con); 

cmd.CommandType = CommandType.StoredProcedure; 

如果你不这样做,.NET可以使用sp_executesql...生成命令,这就是问题...您指定命令类型如上和生成的代码使用

execute storedprocedure @param1 = ... 
1

你会在你的SQL字符串指定参数映射为它工作。即,在C#代码替换

db.Database.SqlQuery<T>("EXEC dbo.SaveResults", resultId, positiveResults) 

看来sp_executesql是无法执行存储过程时传递的参数来自动关联到期望的参数,除非在SQL被手动指定的映射字符串通过

相关问题