Как использовать DbContext.Database.SqlQuery <TElement>(sql, params) с хранимой процедурой? EF Code First CTP5 - PullRequest
232 голосов
/ 02 февраля 2011

У меня есть хранимая процедура с тремя параметрами, и я пытаюсь использовать следующее для возврата результатов:

context.Database.SqlQuery<myEntityType>("mySpName", param1, param2, param3);

Сначала я попытался использовать SqlParameter объекты в качестве параметров, но этоне работал и выдал SqlException со следующим сообщением:

Процедура или функция 'mySpName' ожидает параметр '@ param1', который не был предоставлен.

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

Спасибо.

Ответы [ 9 ]

365 голосов
/ 02 февраля 2011

Вы должны предоставить экземпляры SqlParameter следующим образом:

context.Database.SqlQuery<myEntityType>(
    "mySpName @param1, @param2, @param3",
    new SqlParameter("param1", param1),
    new SqlParameter("param2", param2),
    new SqlParameter("param3", param3)
);
123 голосов
/ 19 июня 2011

Также вы можете использовать параметр "sql" в качестве спецификатора формата:

context.Database.SqlQuery<MyEntityType>("mySpName @param1 = {0}", param1)
70 голосов
/ 22 сентября 2011

Это решение (только) для SQL Server 2005

Вы, ребята, спасатели, но, как сказал @Dan Mork, вам нужно добавить EXEC в смесь. То, что меня сбило с толку, было:

  • «EXEC» перед именем процесса
  • Запятые между параметрами
  • Отрезать '@' в параметре Определения (хотя не уверен, что бит требуется).

context.Database.SqlQuery<EntityType>(
    "EXEC ProcName @param1, @param2", 
    new SqlParameter("param1", param1), 
    new SqlParameter("param2", param2)
);
13 голосов
/ 18 октября 2012
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();
}
4 голосов
/ 08 сентября 2017

Большинство ответов являются хрупкими, поскольку они зависят от порядка параметров SP. Лучше назвать параметры хранимой процедуры и дать им параметризованные значения.

Чтобы использовать именованные параметры при вызове вашего 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)
3 голосов
/ 15 октября 2017
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();
2 голосов
/ 27 февраля 2012

Я использую этот метод:

var results = this.Database.SqlQuery<yourEntity>("EXEC [ent].[GetNextExportJob] {0}", ProcessorID);

Мне это нравится, потому что я просто добавляю Guids и Datetimes, а SqlQuery выполняет для меня все форматирование.

1 голос
/ 10 мая 2017

@ Ответ Тома Халладея верен, с упоминанием о том, что вы также проверяете наличие нулевых значений и отправляете DbNullable, если параметры равны нулю, как если бы вы получили исключение типа

Параметризованный запрос '...' ожидает параметр '@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)
0 голосов
/ 20 марта 2014

У меня было то же сообщение об ошибке, когда я работал с вызовом хранимой процедуры, которая принимает два входных параметра и возвращает 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();
...