Подтвердить что ты не робот

Почему Entity Framework генерирует исключение при изменении порядка SqlParameter?

Im, использующий сущность Framework 4.3, сначала для вызова хранимой процедуры, как я вызываю хранимую процедуру, выглядит следующим образом:

var parameters = new[]
{
    new SqlParameter("member", 1),
    **new SqlParameter("Code","0165210662660001"),**
    new SqlParameter("PageSize", 1),
    new SqlParameter("PageNumber",1)
};

var result  = context.Database.SqlQuery<resultClass>(
    "mySpName @member, @Code, @PageSize,@PageNumber" parameters).ToList();

Он запускается на SqlServer, и я получаю результат.

Но если я изменю порядок параметров, например:

var result  = context.Database.SqlQuery<resultClass>("mySpName @Code,  @member,@PageSize,@PageNumber" parameters).ToList();

var parameters = new[]
{
    **new SqlParameter("Code","0165210662660001"),**
    new SqlParameter("Member", 1),
    new SqlParameter("PageSize", 1),
    new SqlParameter("PageNumber",1)
};

У меня возникла ошибка:

 Error converting data type nvarchar to int

Хранимая процедура выглядит следующим образом:

ALTER PROCEDURE [c].[mySpName]
    @Member INT ,
    @Code VARCHAR (50) ,
    @PageSize INT ,
    @PageNumber INT
 AS 

Почему я получаю этот заказ? Важно ли сохранять порядок параметров? Что я могу сделать, чтобы я мог вызвать хранимую процедуру, не беспокоясь о порядке параметров?

============ Я нахожу обходной путь, и он отлично работает ============

public class blahContext<T>
{
    int i = 0;
    public  IEnumerable<T> ExecuteStoreQuery(string SPname, SqlParameter[] parameters)
    {

        using (var context = new CADAContext())
        {


            string para = string.Join(", ", (from p in parameters
                                             where !"NULL".Equals(p.Value)
                                             select string.Concat(new object[] { "@", p.ParameterName, "={", this.i++, "}" })).ToList<string>());

            object[] x = (from p in parameters
                          where !"NULL".Equals(p.Value)
                          select p.Value).ToArray<object>();

            return context.Database.SqlQuery<T>(SPname + " " + para, x).ToList();

        }
    }
4b9b3361

Ответ 1

Это не из-за порядка параметров в вашем объекте параметров - потому что во втором фрагменте кода вы явно передаете значение @Code в качестве первого параметра, когда SP ожидает значение Member INT.

var result  = context.Database.SqlQuery<resultClass>("mySpName @Code,  @member,@PageSize,@PageNumber" parameters).ToList();

... вы передаете "0165210662660001" в качестве первого параметра, а преобразование в INT не выполняется.

Порядок ваших параметров в объекте параметров не имеет значения, так как EF (на самом деле ADO.NET) сопоставляет эти параметры со значениями @parametername в строке запроса. Таким образом, new SqlParameter("Code","0165210662660001") будет отображаться в позиции @Code в вашем запросе, - который во втором сокращенном коде фактически является позицией для значения члена, как ожидается SP.

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

db.Database.SqlQuery<resultClass>("mySpName [email protected],[email protected],[email protected],[email protected]", parameters).ToList();

Вы видите, что я не передаю params в SP в том порядке, в котором они были определены [по SP], но поскольку они названы, мне не нужно заботиться.

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