Для обновления требуется допустимая команда UpdateCommand при передаче коллекции DataRow с измененными строками

Так что на прошлой неделе у меня была эта работа. По крайней мере, я так думал! Обновление DataGridView

Затем я снова начинаю работать над проектом сегодня и получаю

Для обновления требуется допустимая команда UpdateCommand при передаче коллекции DataRow с измененными строками.

На

scDB.SSIS_Configurations_StagingDataTable table = (scDB.SSIS_Configurations_StagingDataTable)stagingGrid.DataSource;
myStagingTableAdapter.Update(table);

У StagingTableAdapter него есть дополнительный запрос, который принимает в качестве параметра «фильтр». Это использовалось для заполнения DataGridView . В мастере создания этого запроса я вижу «обновление было сгенерировано». Я вижу, что для большинства сообщений с этой ошибкой требуется, чтобы оператор обновления создавался с помощью построителя команд. Что мне делать?

Ответов (11)

Решение

Ошибка очевидна: адаптеру требуется действующий оператор SQL Update. Дизайнеры наборов данных и CommandBuilders сгенерируют их для вас, но нет ничего плохого в том, чтобы вручную создать немного SQL.

В любом случае вам нужно будет проверить (отладчик), что оператор Update все еще настроен и что он на самом деле представляет. Это может быть скорее проблема SQL, чем проблема C#.

Изменить: инструменты Command Builder будут обрабатывать только прямые, одиночные таблицы, операторы Select. Используйте Join или что-нибудь необычное, и вы сами по себе.

У меня возникла та же проблема, и ответ Джейсона сработал для меня: я забыл назначить первичный ключ для своей таблицы.

Еще одно напоминание, которое следует добавить: после исправления проблемы в таблице при возвращении в Visual Studio в файле .xsd, содержащем набор данных, обязательно удалите исходную таблицу и снова добавьте ее из обозревателя серверов или базы данных. Исследователь. В противном случае ошибка все равно будет существовать.

Я тоже столкнулся с той же проблемой и получил следующее решение. Попытайся.

private void btnSave_Click(object sender, EventArgs e)
{
    ConnStr = "Data Source=FIN03;Initial Catalog=CmsTest;Integrated Security=True";
    cn = new SqlConnection(ConnStr);
    cn.Open();
    SqlCommand cmd = new SqlCommand();
    cmd.Connection = cn;
    mytran = cn.BeginTransaction(IsolationLevel.Serializable );

    cmd.Transaction = mytran;
    try
    {

        scb = new SqlCommandBuilder(da);
        da.Update(ds, "tblworker");
        mytran.Commit ();
        MessageBox.Show("Data update successfully"); 

    }
    catch (Exception err)
    {

           mytran.Rollback();

            MessageBox.Show(err.Message.ToString());           
    }
}

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

В моем простом примере это может быть столбец имени - хотя более реалистично я бы добавил столбец идентификатора с автоматической нумерацией, который обеспечит уникальность всех значений в этом столбце.

Восстановите все, воссоздайте новый DataSet, замените DataGridView, используя перетаскивание, как раньше, и все готово .

Как обычно, ответ прост, когда вы его знаете, и невероятно неприятно, когда вы этого не знаете.

Источник .

У вас всегда должно быть поле столбца, определяемое первичным ключом. Иначе проблема будет всегда. SqlCommandBuilder не поможет, если у вас нет поля первичного ключа.

вы можете использовать следующий код для любой таблицы, он автоматически сгенерирует для вас команды Insert, Update и Delete.

private void savechanges(String tbl, SqlDataAdapter sqldap, DataSet dset)
    {

        try
        {
            SqlCommandBuilder scb = new SqlCommandBuilder(sqldap);
            scb.ConflictOption = ConflictOption.CompareRowVersion;
            sqldap.Update(dset, tbl);
            dset.AcceptChanges();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message.ToString());
        }
    }

Как говорили другие, вам нужно убедиться, что у вас есть первичный ключ, установленный в таблице для создания автоматически сгенерированного кода обновления. Я сделал это, но все еще видел то же сообщение

Для обновления требуется допустимая команда UpdateCommand при передаче коллекции DataRow с измененными строками.

Затем я обнаружил, что вам также нужно обновить адаптер таблицы (это имеет смысл, если подумать!).

Пока вы делаете это, также может быть полезно дважды проверить, что у вас был выбран параметр « Создать операторы вставки, обновления и удаления» (как показано ниже).

введите описание изображения здесь

Затем просто щелкните мастер, последний экран должен подтвердить, что он создаст требуемый код повтора (теперь с первичным ключом):

введите описание изображения здесь

Со страницы:

Примечание. Если в основном запросе достаточно информации, команды InsertCommand, UpdateCommand и DeleteCommand создаются по умолчанию при создании TableAdapter. Если основной запрос TableAdapter представляет собой более одного оператора SELECT для таблицы, возможно, разработчик не сможет сгенерировать InsertCommand, UpdateCommand и DeleteCommand. Если эти команды не генерируются, вы можете получить сообщение об ошибке при выполнении метода TableAdapter.Update.

Итак, насколько я могу судить, эти утверждения должны были быть созданы. Я использую одну таблицу.

Я столкнулся с той же проблемой, что и Сэм. У меня был рабочий код, который внезапно перестал работать. Я не знал, когда я это написал, но, должно быть, он автоматически выводил команду обновления, а затем прекратил это делать. Возможно, сервисный пакет от MS между версиями, который мы так и не заметили. В любом случае, решение, с которым я столкнулся, использует (в моем случае для oracle) OracleCommandBuilder, который принимает DataAdapter (после вызова fill) в качестве параметра конструктора, а затем вызывает GetUpdateCommand () и присваивает его UpdateCommand в DataAdapter.

pseudocode:

DataAdapter da = new DataAdapter(...)
...
da.Fill();
da.UpdateCommand = new OracleCommandBuilder(da).GetUpdateCommand();
...
da.Update();

У меня работает обходной путь Дэна, но вместо OracleCommandBuilder я могу просто использовать SqlCommandBuilder:

DataAdapter da = new DataAdapter(...)
...
da.Fill();
da.UpdateCommand = new SqlCommandBuilder(da).GetUpdateCommand();
...
da.Update();

Это сообщение также будет отображаться, если у вас нет первичного ключа, определенного для обновляемой таблицы.