CommandBuilder и SqlTransaction для вставки / обновления строки - PullRequest
0 голосов
/ 15 мая 2010

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

При первом запуске он работает как задумано, и вставляется новая строка, в которой «thisField» содержит «doesntExist»

Однако, если я запускаю его в следующий раз, я получаю ошибку во время выполнения, что не могу вставить дубликат ключа, так как он нарушает первичный ключ "thisField".


static void Main(string[] args)
{           
    using(var sqlConn = new SqlConnection(connString) )
    {
        sqlConn.Open();
        var dt = new DataTable();

        var sqlda = new SqlDataAdapter("SELECT * FROM table WHERE thisField ='doesntExist'", sqlConn);
        sqlda.Fill(dt);

        DataRow dr = dt.NewRow();

        dr["thisField"] = "doesntExist"; //Primary key

        dt.Rows.Add(dr);

        //dt.AcceptChanges(); //I thought this may fix the problem. It didn't.

        var sqlTrans = sqlConn.BeginTransaction();

        try
        {
            sqlda.SelectCommand = new SqlCommand("SELECT * FROM table WITH (HOLDLOCK, ROWLOCK) WHERE thisField = 'doesntExist'", sqlConn, sqlTrans);

            SqlCommandBuilder sqlCb = new SqlCommandBuilder(sqlda);

            sqlda.InsertCommand = sqlCb.GetInsertCommand();
            sqlda.InsertCommand.Transaction = sqlTrans;

            sqlda.DeleteCommand = sqlCb.GetDeleteCommand();
            sqlda.DeleteCommand.Transaction = sqlTrans;

            sqlda.UpdateCommand = sqlCb.GetUpdateCommand();
            sqlda.UpdateCommand.Transaction = sqlTrans;

            sqlda.Update(dt);

            sqlTrans.Commit();
        }
        catch (Exception)
        {
            //...
        }
    }
}

Даже когда я могу добиться того, чтобы методом проб и ошибок перемещать AcceptChanges или инкапсулировать изменения в Begin / EndEdit, я начинаю испытывать «нарушение параллелизма», при котором оно не обновляет изменения, а скорее говорит мне не удалось обновить 0 из 1 затронутых строк.

Есть ли что-то безумное очевидное, что мне не хватает?

1 Ответ

1 голос
/ 17 мая 2010

Я смог преодолеть свои проблемы, удалив строки вручную после заполнения таблицы данных. Я не могу использовать dt.Clear(), так как это все еще приводит к исключению из-за попытки вставить запись с повторяющимся первичным ключом.


sqladapter.Fill(dt);

foreach( DataRow d in dt.Rows )
    d.Delete();

DataRow dr = dt.NewRow();

dr.BeginEdit();
//update dr
dr.EndEdit();

dt.Rows.Add(dr);

Вышеприведенное успешно позволит мне вставить новую строку и обновить ранее существующую строку. Удаление foreach сгенерирует «Невозможно вставить дубликат ключа в объект», поэтому я чувствую, что, по крайней мере, нашел решение a ; хотя я чувствую, что это не решение .

Надеюсь, это кому-нибудь поможет.

...