Как использовать DbContext.База данных.SQL-запрос (в SQL, параметры) с помощью хранимой процедуры? Эф код первого CTP5
у меня есть хранимая процедура, которая имеет три параметра, и я пытался использовать следующее, чтобы вернуть результаты:
context.Database.SqlQuery<myEntityType>("mySpName", param1, param2, param3);
сначала я попробовал использовать SqlParameter
объекты в качестве параметров, но это не сработало и бросил SqlException
появляется следующее сообщение:
процедура или функция 'mySpName' ожидает параметр '@param1', который не был указан.
поэтому мой вопрос заключается в том, как вы можете использовать этот метод с хранимой процедурой, которая ожидает параметры?
спасибо.
10 ответов:
вы должны предоставить экземпляры SqlParameter следующим образом:
context.Database.SqlQuery<myEntityType>( "mySpName @param1, @param2, @param3", new SqlParameter("param1", param1), new SqlParameter("param2", param2), new SqlParameter("param3", param3) );
кроме того, вы можете использовать параметр "SQL" в качестве спецификатора формата:
context.Database.SqlQuery<MyEntityType>("mySpName @param1 = {0}", param1)
это решение (только) для 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) );
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(); }
большинство ответов хрупкие, потому что они зависят от порядка параметров SP. Лучше назвать сохраненные параметры Proc и дать им параметризованные значения.
чтобы использовать именованные параметры при вызове вашего SP, не беспокоясь о порядке параметров
использование именованных параметров SQL Server с ExecuteStoreQuery и ExecuteStoreCommand
описывает наилучший подход. Лучше, чем ответ Дэна Морка здесь.
- не полагается на конкатенацию строк и не зависит от порядка параметров, определенных в SP.
например:
var cmdText = "[DoStuff] @Name = @name_param, @Age = @age_param"; var params = new[]{ new SqlParameter("name_param", "Josh"), new SqlParameter("age_param", 45) }; context.Database.SqlQuery<myEntityType>(cmdText, params)
Я использую этот метод:
var results = this.Database.SqlQuery<yourEntity>("EXEC [ent].[GetNextExportJob] {0}", ProcessorID);
мне это нравится, потому что я просто забрасываю GUID и даты, а SqlQuery выполняет все форматирование для меня.
ответ@Tom Halladay верен с упоминанием о том, что вы shopuld также проверяете значения null и отправляете DbNullable, если параметры 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)
db.Database.SqlQuery<myEntityType>("exec GetNewSeqOfFoodServing @p0,@p1,@p2 ", foods_WEIGHT.NDB_No, HLP.CuntryID, HLP.ClientID).Single()
@p0,@p1,@p2......
или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();
у меня было такое же сообщение об ошибке, когда я работал с вызовом хранимой процедуры, которая принимает два входных параметра и возвращает 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", parameters).ToList();