EF ExecuteStoredCommand с параметром ReturnValue
Я создаю новое приложение, которое должно взаимодействовать с устаревшим кодом: (.
Хранимая процедура, которую я пытаюсь вызвать, использует RETURN для ее результата. Мои попытки выполнить и использовать возвращаемое значение приводят к исключению:
InvalidOperationException: при выполнении команды параметры должны быть исключительно параметрами или значениями базы данных.
Изменение сохраненного proc для возврата значения другим способом нежелательно, поскольку оно требует либо обновления устаревшего приложения, либо сохранения почти дублированного сохраненного 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);
Поиск любых решений, которые не требуют изменения хранимой процедуры.
Ответы
Ответ 1
Я уверен, что это не единственный правильный ответ, но тот, который я в конечном счете использовал и успешно работал.
Ключ, казалось, назвал параметр 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
Вместо этого вы можете вернуть возвращаемое значение хранимой процедуры в выходной параметр:
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;
Ответ 3
У вас < есть, чтобы использовать ExecuteSqlCommand
.
Вы можете просто получить базовое соединение из DbContext.Database.Connection
и использовать raw ADO.NET(CreateCommand()
, ExecuteNonQuery()
,...)
Ответ 4
Я знаю это немного позже, но это работает для меня:
var param = new SqlParameter("@Parameter1", txtBoxORsmth.text);
someVariable = ctx.Database.SqlQuery<int>("EXEC dbo.MyProc", param).First();
Ответ 5
Создать таблицу для параметра Параметр для тестирования или изменения второго 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();
}
}
Ответ 6
Сообщение об ошибке
InvalidOperationException: при выполнении команды параметры должны быть исключительно параметрами или значениями базы данных.
означает, что вы не предоставляете правильный тип (или что-то еще, что не показано в фрагменте кода) в списке параметров SQLParameters.
В моем случае я забыл удалить MergeOption, потому что изменил способ выполнения команды SQL.
Ответ 7
Я пробовал способы выше, но только для меня это работает (должна быть функция 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);
Ответ 8
Этот метод расширения теперь сделает всю грязную работу для вас. Более подробное описание SO здесь.
Ответ 9
Это вернет int из сохраненного процесса, используя DBContext:
var newId = DbContext.Database.SqlQuery<int>("EXEC dbo.MyProc @MyID = {0}", parm).First();