带有ReturnValue参数的EF ExecuteStoredCommand

时间:2011-12-09 22:21:10

标签: sql-server entity-framework-4.1 ef-code-first

我正在创建一个需要与遗留代码接口的新应用程序:(。

我试图调用的存储过程使用RETURN作为结果。我尝试执行和使用返回值会导致异常:

  

InvalidOperationException:执行命令时,参数必须是数据库参数或值。

不需要更改存储过程以另一种方式返回值,因为它要么需要更新旧应用程序,要么维护几乎重复的存储过程。

遗留存储过程简介:

DECLARE @MyID INT
INSERT INTO MyTable ...
SELECT @MyID = IDENTITY()
RETURN @MyID

My Entity Framework / DbContext工作,产生上述InvalidOperationException。

 SqlParameter parm = new SqlParameter() {
    ParameterName = "@MyID",
    Direction = System.Data.ParameterDirection.ReturnValue
 };

 DbContext.Database.ExecuteSqlCommand("EXEC dbo.MyProc", parm);

寻找任何不需要修改存储过程的解决方案。

9 个答案:

答案 0 :(得分:28)

您可以将存储过程的返回值捕获到输出参数中:

SqlParameter parm = new SqlParameter() {  
    ParameterName = "@MyID",  
    SqlDbType = SqlDbType.Int,
    Direction = System.Data.ParameterDirection.Output  
 };  

Database.ExecuteSqlCommand("exec @MyId = dbo.MyProc", parm);

int id = (int)parm.Value;

答案 1 :(得分:2)

您没有 使用ExecuteSqlCommand

您可以从DbContext.Database.Connection获取基础连接并使用原始ADO.NET(CreateCommand()ExecuteNonQuery(),...)

答案 2 :(得分:2)

我知道这有点晚了,但这对我有用:

var param = new SqlParameter("@Parameter1", txtBoxORsmth.text);

someVariable = ctx.Database.SqlQuery<int>("EXEC dbo.MyProc", param).First();

答案 3 :(得分:0)

为With参数示例创建表,用于测试或根据您的更改第二个sql查询。

CREATE TABLE [dbo].[Test](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NOT NULL,
 CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED 
(
    [Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

// ========================= ==================== ============= //

        public void Test()
        {
                  using (var db = new DbContext())
                  {
                      string sql = "dbo.MyProc";  //With Out Parameter

                  int id1 = (int)db.Database.SqlQuery<decimal>(sql).FirstOrDefault();
                  db.SaveChanges();

                  //Or

                  sql = "INSERT Test(Name) values({0}) SELECT SCOPE_IDENTITY();";  //With Parameter
                  int id2 = (int)db.Database.SqlQuery<decimal>(sql, new object[] { "Thulasi Ram.S" }).FirstOrDefault();
                  db.SaveChanges();
              }
        }

答案 4 :(得分:0)

错误消息

  

InvalidOperationException:执行命令时,参数必须是数据库参数或值。

表示您没有在SQLParameters的参数列表中提供正确的类型(或其他未在您的代码段中显示的内容)。

在我的情况下,我忘记删除MergeOption,因为我改变了SQL命令的执行方式。

答案 5 :(得分:0)

我试过上面的方法,但只有这种方式适合我(必须有'ToList()'功能):

 SqlParameter res = new SqlParameter()
        {
            ParameterName = "Count",
            Value=1,
            Direction = System.Data.ParameterDirection.Output
        };
db.Database.SqlQuery<object>(
         "[dbo].[GetWorkerCountBySearchConditions] @Count ,
         res
         ).ToList();
        return Convert.ToInt32(res.Value);

答案 6 :(得分:0)

extension method现在将为您完成所有肮脏的工作。请参阅有关SO here的更全面的说明。

答案 7 :(得分:0)

这将使用DBContext从存储过程中返回int:

var newId = DbContext.Database.SqlQuery<int>("EXEC dbo.MyProc @MyID = {0}", parm).First();

答案 8 :(得分:-2)

我确信这不是唯一有效的答案,而是我最终使用并且已成功运作的答案。

密钥似乎是命名ReturnValue参数 RetVal

SqlParameter id = create.Parameters.Add("RetVal", System.Data.SqlDbType.Int);
id.Direction = System.Data.ParameterDirection.ReturnValue;

把它们放在一起:

SqlCommand proc = new SqlCommand("dbo.MyProc", new SqlConnection(<connection string>));
proc.CommandType = System.Data.CommandType.StoredProcedure;

SqlParameter id = create.Parameters.Add("RetVal", System.Data.SqlDbType.Int);
id.Direction = System.Data.ParameterDirection.ReturnValue;

proc.ExecuteNonQuery();

int newId = Convert.ToInt32(id.Value);