Попытка запустить Insert с SqlParameters с EF, получение ошибки скалярной переменной, Как исправить? - PullRequest
1 голос
/ 07 апреля 2019

Я использую EF 6 с MVC5 / C #

Я пытаюсь выполнить оператор вставки, используя SqlParameter объекты, через ExecuteStoreCommand через EF. Я делаю это таким образом, так как у меня есть некоторые проблемы с производительностью AddObject.

Мой код:

string insertCmd = "INSERT INTO TABLE (Value,FkId) VALUES (@Value,@FkId)";

var paramList = new[]{
    new SqlParameter("@Value", SqlDbType.VarChar).Value = value,
    new SqlParameter("@FkId", SqlDbType.Int).Value = fkId
};

db.ExecuteStoreCommand(insertCmd, paramList);

Я получаю ошибку:

Должен объявлять скалярную переменную "@Value". Заявление (я) не может быть подготовлено.

Я заметил, что он всегда жалуется на первый столбец в операторе вставки независимо от типа. Так что, если бы я поменял его, я бы получил:

Должен объявлять скалярную переменную "@FkId". Заявление (я) не может быть подготовлено.

Мысли?

EDIT:

Только что заметил, что запись вставляется и сохраняется в БД, но я все еще получаю эту ошибку. Озадаченный ...

1 Ответ

2 голосов
/ 07 апреля 2019

Если вы внимательно посмотрите на тип, выведенный компилятором для переменной:

var paramList = new[]
{
    new SqlParameter("@Value", SqlDbType.VarChar).Value = "SomeValue",
    new SqlParameter("@FkId", SqlDbType.Int).Value = 123
};

Вы увидите, что paramList - это Object[2] с двумя скалярными значениями Value(string) и 123(int), а SqlParameters полностью потеряны, потому что результатом присваивания является присвоенное значение! Object выводится компилятором как наименьший общий знаменатель из string и int.

К сожалению, вызов ExecuteStoreCommand не даст вам никакого предупреждения о том, что вы не передаете SqlParameter[], поскольку он принимает очень слабый тип params object[] согласно документам:

Значением параметров может быть массив объектов DbParameter или массив значений параметров

Чтобы решить эту проблему, вы можете использовать один из конструкторов SqlParameter, которые непосредственно принимают значение, например,

var paramList = new[]
{
    new SqlParameter("@Value", "SomeValue"),
    new SqlParameter("@FkId", 123)
};

Или создайте параметры, назначьте их и добавьте в массив.

Из интереса, ExecuteStoreCommand - это метод для ObjectContext, а не DbContext.

Существует эквивалентный метод DbContext.Database.ExecuteSqlCommand, который должен делать то же самое.

...