Я использую EF 6 с MVC5/С#.
Я пытаюсь запустить оператор вставки, используя объекты 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);
Я получаю сообщение об ошибке:
Must declare the scalar variable "@Value". Statement(s) could not be prepared.
Я заметил, что он всегда жалуется на первый столбец в операторе Insert независимо от типа. Итак, если бы я поменял его местами, я бы получил:
Must declare the scalar variable "@FkId". Statement(s) could not be prepared.
Мысли ?
Обновлено:
Только что заметил, что запись вставляется и сохраняется в БД, но я все еще получаю эту ошибку. Озадачен...
Если вы очень внимательно посмотрите на тип, выведенный компилятором для переменной:
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[]
согласно документам:
The parameters value can be an array of DbParameter objects or an array of parameter values
Чтобы решить эту проблему, вы можете использовать один из конструкторов SqlParameter
, которые принимают значение напрямую, например.
var paramList = new[]
{
new SqlParameter("@Value", "SomeValue"),
new SqlParameter("@FkId", 123)
};
Или создайте параметры, назначьте их, а затем добавьте в массив.
Ради интереса, ExecuteStoreCommand
— это метод ObjectContext
, а не DbContext.
Существует эквивалентный метод DbContext.Database.ExecuteSqlCommand
, который должен делать то же самое.
Только что попробовал ваше первое предложение, и оно сработало. Очень люблю ваш очень исчерпывающий ответ. Теперь я вижу тип объекта! Так благодарен.