Как использовать DbContext.Database.SqlQuery <TElement> (sql, params) с хранимой процедурой? EF Code First CTP5
У меня есть хранимая процедура с тремя параметрами, и я пытаюсь использовать следующее для возврата результатов:
context.Database.SqlQuery<myEntityType>("mySpName", param1, param2, param3);
Сначала я попытался использовать объекты SqlParameter
в качестве параметров, но это не сработало и бросило SqlException
со следующим сообщением:
Процедура или функция 'mySpName' ожидает параметр '@param1', который не был указан.
Итак, мой вопрос заключается в том, как вы можете использовать этот метод с хранимой процедурой, которая ожидает параметров?
Спасибо.
Ответы
Ответ 1
Вы должны предоставить экземпляры SqlParameter следующим образом:
context.Database.SqlQuery<myEntityType>(
"mySpName @param1, @param2, @param3",
new SqlParameter("param1", param1),
new SqlParameter("param2", param2),
new SqlParameter("param3", param3)
);
Ответ 2
Кроме того, вы можете использовать параметр "sql" в качестве спецификатора формата:
context.Database.SqlQuery<MyEntityType>("mySpName @param1 = {0}", param1)
Ответ 3
Это решение (только) для SQL Server 2005
Вы, ребята, спасатели, но, как сказал @Dan Mork, вам нужно добавить EXEC в микс. Что меня сбило с толку:
- 'EXEC' перед именем Proc
- Запятые между Парамами
- Отключение "@" на Param
Определения (не уверен, что бит необходим, хотя).
:
context.Database.SqlQuery<EntityType>(
"EXEC ProcName @param1, @param2",
new SqlParameter("param1", param1),
new SqlParameter("param2", param2)
);
Ответ 4
return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
new object[] { param1, param2, param3 });
//Или
using(var context = new MyDataContext())
{
return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
new object[] { param1, param2, param3 }).ToList();
}
//Или
using(var context = new MyDataContext())
{
object[] parameters = { param1, param2, param3 };
return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
parameters).ToList();
}
//Или
using(var context = new MyDataContext())
{
return context.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
param1, param2, param3).ToList();
}
Ответ 5
Большинство ответов являются хрупкими, потому что они зависят от порядка параметров SP. Лучше назвать параметры Stored Proc и дать им параметризованные значения.
Для того, чтобы использовать именованные параметры при вызове вашего SP, не беспокоясь о порядке параметров
Использование именованных параметров SQL Server с ExecuteStoreQuery и ExecuteStoreCommand
Описывает лучший подход. Лучше, чем Дэн Морк, ответь здесь.
- Не зависит от объединения строк и не зависит от порядка параметров, определенных в SP.
Например:
var cmdText = "[DoStuff] @Name = @name_param, @Age = @age_param";
var sqlParams = new[]{
new SqlParameter("name_param", "Josh"),
new SqlParameter("age_param", 45)
};
context.Database.SqlQuery<myEntityType>(cmdText, sqlParams)
Ответ 6
db.Database.SqlQuery<myEntityType>("exec GetNewSeqOfFoodServing @p0,@p1,@p2 ", foods_WEIGHT.NDB_No, HLP.CuntryID, HLP.ClientID).Single()
или же
db.Database.SqlQuery<myEntityType>(
"exec GetNewSeqOfFoodServing @param1, @param2",
new SqlParameter("param1", param1),
new SqlParameter("param2", param2)
);
или же
var cmdText = "exec [DoStuff] @Name = @name_param, @Age = @age_param";
var @params = new[]{
new SqlParameter("name_param", "Josh"),
new SqlParameter("age_param", 45)
};
db.Database.SqlQuery<myEntityType>(cmdText, @params)
или же
db.Database.SqlQuery<myEntityType>("mySpName {0}, {1}, {2}",
new object[] { param1, param2, param3 }).ToList();
Ответ 7
Я использую этот метод:
var results = this.Database.SqlQuery<yourEntity>("EXEC [ent].[GetNextExportJob] {0}", ProcessorID);
Мне это нравится, потому что я просто бросаю гиды и Datetimes, а SqlQuery выполняет все форматирование для меня.
Ответ 8
@Tom Halladay ответ верен с упоминанием о том, что вы также проверяете нулевые значения и отправляете DbNullable, если params равны null, поскольку вы получите исключение, например
Параметрированный запрос "..." ожидает параметр "@parameterName", который не был предоставлен.
Что-то вроде этого помогло мне
public static object GetDBNullOrValue<T>(this T val)
{
bool isDbNull = true;
Type t = typeof(T);
if (Nullable.GetUnderlyingType(t) != null)
isDbNull = EqualityComparer<T>.Default.Equals(default(T), val);
else if (t.IsValueType)
isDbNull = false;
else
isDbNull = val == null;
return isDbNull ? DBNull.Value : (object) val;
}
(кредит для метода переходит на https://stackoverflow.com/users/284240/tim-schmelter)
Затем используйте его как:
new SqlParameter("@parameterName", parameter.GetValueOrDbNull())
или другое решение, более простое, но не общее:
new SqlParameter("@parameterName", parameter??(object)DBNull.Value)
Ответ 9
У меня было то же сообщение об ошибке, когда я работал с вызовом хранимой процедуры, которая принимает два входных параметра и возвращает 3 значения, используя инструкцию SELECT, и я решил проблему, как показано ниже в EF Code First Approach
SqlParameter @TableName = new SqlParameter()
{
ParameterName = "@TableName",
DbType = DbType.String,
Value = "Trans"
};
SqlParameter @FieldName = new SqlParameter()
{
ParameterName = "@FieldName",
DbType = DbType.String,
Value = "HLTransNbr"
};
object[] parameters = new object[] { @TableName, @FieldName };
List<Sample> x = this.Database.SqlQuery<Sample>("EXEC usp_NextNumberBOGetMulti @TableName, @FieldName", parameters).ToList();
public class Sample
{
public string TableName { get; set; }
public string FieldName { get; set; }
public int NextNum { get; set; }
}
ОБНОВЛЕНИЕ. Похоже, в SQL SERVER 2005 отсутствует ключевое слово EXEC, что создает проблему. Поэтому, чтобы позволить ему работать со всеми версиями SQL SERVER, я обновил свой ответ и добавил EXEC в строке ниже
List<Sample> x = this.Database.SqlQuery<Sample>(" EXEC usp_NextNumberBOGetMulti @TableName, @FieldName", param).ToList();
Ответ 10
Я сделал мой с EF 6.x так:
using(var db = new ProFormDbContext())
{
var Action = 1;
var xNTID = "A239333";
var userPlan = db.Database.SqlQuery<UserPlan>(
"AD.usp_UserPlanInfo @Action, @NTID", //, @HPID",
new SqlParameter("Action", Action),
new SqlParameter("NTID", xNTID)).ToList();
}
Не делайте удвоения по параметру sqlparameter - некоторые люди обжигаются, делая это со своей переменной
var Action = new SqlParameter("@Action", 1); // Don't do this, as it is set below already.