2011-12-09 39 views
15

我创建一个新的应用程序,它需要与遗留代码:(接口。EF ExecuteStoredCommand与返回值参数

存储过程我试图调用使用返回它的结果。我试图执行和消费返回值结果在异常:

InvalidOperationException异常:当执行一个命令,参数必须专门数据库的参数或值

更改存储过程返回VALU另一种方式是不希望的,因为它要么需要更新传统应用程序,要么保持几乎重复的存储过程。

遗留存储过程简介:

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

我的实体框架/的DbContext工作,产生上述InvalidOperationException异常。

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

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

寻找任何和所有的解决方案,不需要存储过程被修改。

回答

-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); 
+2

这里创建了什么? –

2

你不要使用ExecuteSqlCommand

你可以得到从DbContext.Database.Connection底层的连接和使用原始ADO.NET(CreateCommand()ExecuteNonQuery() ...)

25

您可以捕获存储过程的返回值到输出参数,而不是:

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; 
0

创建表用于测试的参数示例或根据您的更改第二个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(); 
       } 
     } 
+0

我可以能够通过让主ID上面的代码。 – Thulasiram

0

该错误消息

InvalidOperationException异常:当执行命令时,参数必须专门数据库的参数或值。

意味着您没有在SQLParameters的params列表中提供正确的类型(或其他代码段中未显示的类型)。

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

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); 
0

extension method现在会为你做所有的肮脏的工作。请参阅SO here的更完整说明。

-1

这将从一个存储过程使用的DbContext返回INT:

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

这是一个可怕的建议。此代码易受SQL注入攻击。 **很少**是这种语句的构建和执行的好主意。始终尝试使用参数化查询。 – NathanAldenSr

+0

@NathanAldenSr - “SqlQuery”方法自动将您提供的参数转换为DbParameters。这是一个参数化查询 - 它必须是为了调用带参数的存储过程。 https://msdn.microsoft.com/en-us/library/system.data.entity.database.sqlquery(v=vs.113).aspx – Colin

+0

@科林啊,我的错,因为没有更好地理解方法。 – NathanAldenSr

1

我知道这是一个有点晚了,但是这对我的作品:

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

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

它不适用于输出参数 –