EF ExecuteStoredCommand с параметром ReturnValue - PullRequest
16 голосов
/ 10 декабря 2011

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

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

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

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

Устаревший хранимый протокол proc:

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 ]

28 голосов
/ 10 декабря 2011

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

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;
2 голосов
/ 08 апреля 2016

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

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

someVariable = ctx.Database.SqlQuery<int>("EXEC dbo.MyProc", param).First();
2 голосов
/ 10 декабря 2011

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

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

0 голосов
/ 30 апреля 2015

Это вернет int из сохраненного процесса, используя DBContext:

var newId = DbContext.Database.SqlQuery<int>("EXEC dbo.MyProc @MyID = {0}", parm).First();
0 голосов
/ 18 октября 2013

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

0 голосов
/ 22 марта 2013

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

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

Ключ, похоже, называл параметр 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);
0 голосов
/ 31 октября 2012

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

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

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

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

0 голосов
/ 24 сентября 2012

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