EF ExecuteStoredCommand с параметром ReturnValue

Я создаю новое приложение, которое должно взаимодействовать с устаревшим кодом : (.

хранимая процедура, которую я пытаюсь вызвать, использует RETURN для своего результата. Мои попытки выполнить и использовать возвращаемое значение приводят к исключению:

InvalidOperationException: при выполнении команды параметры должны быть исключительно параметрами или значениями базы данных.

изменение сохраненного proc для возврата значения другим способом не требуется, поскольку это либо требует обновления устаревшего приложения, либо поддержания почти дублирующего сохраненного proc.

наследие хранится proc синопсис:

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

моя Entity Framework / DbContext работа, которая дает вышеуказанное исключение InvalidOperationException.

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

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

поиск любых решений, которые не требуют изменения сохраненного proc.

9 ответов


вместо этого можно записать возвращаемое значение хранимой процедуры в выходной параметр:

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;

не есть использовать ExecuteSqlCommand.

вы можете просто получить базовое соединение от DbContext.Database.Connection и использовать raw ADO.NET (CreateCommand(), ExecuteNonQuery(), ...)


Я знаю, это немного поздно, но это работает для меня:

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

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

создайте таблицу для примера с параметром для тестирования или измените второй 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();
              }
        }

сообщение об ошибке

InvalidOperationException: при выполнении команды параметры должны быть исключительно параметрами или значениями базы данных.

означает, что вы не предоставляете правильный тип (или что-то еще, что не показано в фрагменте кода) в списке параметров SQLParameters.

в моем случае я забыл удалить MergeOption, потому что я изменил способ выполнения команды SQL.


Я пробовал пути выше, но только этот способ работает для меня(должен иметь функцию' 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);

этой метод расширения сделает всю грязную работу для вас теперь. Смотрите более полное описание на SO здесь.


это вернет int из сохраненного proc с помощью DBContext:

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

Я уверен, что это не единственный правильный ответ, но тот, который я в конечном счете используется и успешно работает.

ключ, казалось, называл параметр ReturnValue код.

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