8
votes

Violation de la concurrence: l'UpdatEcommand a affecté 0 des enregistrements prévus 1

Je suis nouveau à C # et essayez de lier une base de données DataGridView à une base de données MSSQL dans Visual Studio 2010. Les annonces de données sont correctes et tout semble fonctionner. Sauf quelques erreurs étranges:

Je reçois l'erreur dans le sujet après: Mise à jour de la même ligne 2 fois, Suppression d'une nouvelle ligne insérée, Après avoir mis à jour une ligne lorsqu'une autre ligne a été supprimée (changements de mots à Supprimer) P>

Aucune des solutions que j'ai trouvées sur Google Workes pour moi. J'espère que quelqu'un peut me aider. Voici le code TE: P>

    private void fillDatagrid()
        {
            //fill datagrid ADO.NET
            conn = new SqlConnection(TestApp.Properties.Settings.Default.TestdatabaseConnectionString);
            cmd = conn.CreateCommand();
            conn.Open();
            cmd.CommandText = "SelectFrom";
            cmd.CommandType = CommandType.StoredProcedure;
            cmd.Parameters.Add("@table", SqlDbType.NVarChar, 50).Value = "Countries";
            cmd.Parameters.Add("@filters", SqlDbType.NVarChar, 300).Value = "";

            adapt = new SqlDataAdapter(cmd);
            dt = new DataTable();
            adapt.Fill(dt);
            dt.TableName = "Countries";

            conn.Close();

            BindingSource src = new BindingSource();
            src.DataSource = dt;
            dt.RowChanged += new DataRowChangeEventHandler(dt_RowChanged);

            dgDatabaseGrid.DataSource = src;
            dgDatabaseGrid.AutoResizeColumns(DataGridViewAutoSizeColumnsMode.AllCells);
            //dgDatabaseGrid.RowValidating += new DataGridViewCellCancelEventHandler(dgDatabaseGrid_RowValidating);

            //disable columns:
            dgDatabaseGrid.Columns[0].Visible = false;
            dgDatabaseGrid.Columns["date_insert"].Visible = false;
            dgDatabaseGrid.Columns["user_insert"].Visible = false;
            dgDatabaseGrid.Columns["date_change"].Visible = false;
            dgDatabaseGrid.Columns["user_change"].Visible = false;
            dgDatabaseGrid.Columns["deleted"].Visible = false;

            //auto size last column
            dgDatabaseGrid.Columns["remarks"].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;


            SqlCommandBuilder cb = new SqlCommandBuilder(adapt);
        }

        void dt_RowChanged(object sender, DataRowChangeEventArgs e)
        {
            try
            {
                adapt.Update(dt);
            }
            catch (SqlException ex)
            {
                Debug.WriteLine(ex.Message);
            }
        }

private void dgDatabaseGrid_UserDeletingRow(object sender, DataGridViewRowCancelEventArgs e)
        {
            if (!e.Row.IsNewRow)
            {


                DialogResult response = MessageBox.Show("Are you sure?", "Delete row?",
                                     MessageBoxButtons.YesNo,
                                     MessageBoxIcon.Question,
                                     MessageBoxDefaultButton.Button2);

                if (response == DialogResult.Yes)
                {

                    //ipv delete --> deleted=1
                    conn.Open();
                    cmd = conn.CreateCommand();
                    cmd.CommandType = CommandType.StoredProcedure;
                    cmd.CommandText = "DeleteFrom";
                    cmd.Parameters.Add("@table", SqlDbType.NVarChar, 50).Value = "Countries";
                    cmd.Parameters.Add("@id", SqlDbType.Int).Value = e.Row.Cells[0].Value;
                    cmd.ExecuteNonQuery();
                    conn.Close();


                    //delete from datagrid:
                    dt.Rows[dgDatabaseGrid.SelectedCells[0].RowIndex].Delete();

                }

                //always cancel!
                e.Cancel = true;

            }
        }


2 commentaires

Lorsque vous utilisez la mise à jour, les lignes de table doivent être terminées. En autre mot, l'instruction «SELECT» FILL doit avoir - toutes les colonnes.


@fcm pas vrai. Les commandes de mise à jour sont basées sur la commande SELECT et si la commande SELECT manque 2 colonnes à partir de la table, alors la commande de mise à jour "ne sait pas" à leur sujet et ne les mettra tout simplement pas à la mettre à jour


6 Réponses :


3
votes

Après avoir mis à jour la même ligne 2 fois

Y a-t-il une colonne d'horodatage (ou une autre colonne modifiée / remplie sur le serveur DB)?

Votre problème pourrait se produire lorsque la ligne en mémoire est différente de celle de la DB. Et parce que vous utilisez un SP pour le SelectCMD (probablement) n'est pas une actualisation après une mise à jour.

Après avoir supprimé une nouvelle ligne insérée

similaire, causé ne pas récupérer le nouvel identifiant après un insert

Après avoir mis à jour une ligne lorsqu'une autre ligne a été supprimée (changements de mots à DeleTecommand)

totalement incertain.
Mais pourquoi supprimez-vous des rangées "manuellement" au lieu de la laisser à l'Adaptation.Unupdate ()? Et êtes-vous sûr que les deux méthodes ne sont pas exécutées?


1 commentaires

Votre réponse est exactement ce que je devrais savoir, me donnant assez d'indice pour résoudre mon problème. Merci henk.



11
votes

Je sais que c'est très tard mais peut-être que cela aidera quelqu'un.

a apporté les modifications suivantes à votre code: xxx

mettez ces lignes ici et utilisez Votre variable xxx

Cela a fonctionné comme un charme pour moi espérons que cela fonctionnera pour vous. xxx


3 commentaires

Joli! Cela m'a aidé à résoudre mon problème, cependant, édité pour un meilleur résultat. Remplissez une carte de données.table qui contient déjà des données affichera des lignes dupliquées.


Me.yourtableadapter.update (moi.yourdataset.yourdble) - J'ai déjà une exception à cette ligne, donc pas sûr que la réponse ci-dessus fonctionne


Mais il y a un problème dans cette situation, si vous liez un DataGridView au jeu de données, les valeurs seront dupliquées jusqu'à ce que vous rechargez le formulaire.



-2
votes

réponse simple:

Cela signifie simplement que si vous essayez de mettre à jour une ligne qui n'existe plus dans la base de données.

Plus de détails pourrait être trouvé ici: http://blogs.msdn.com/b/spike/archive/2010/04/07/concurrency-violation-the-updatecommand-Affecte-0-0 -Of-the-attendu-1-Records.aspx


0 commentaires

2
votes

Je poursuis cette erreur dans ma demande pendant des semaines! J'ai finalement trouvé mon problème.

Ce que j'ai trouvé dans ma demande ...

J'ai beaucoup textboxes , comboBoxes , etc. lié à la base de données. Certains de ces champs sont mis à jour à partir des combinaisons d'autres domaines. Tout cela fonctionne très bien avec une exception

Si l'un des champs calculés est ré-calculé après que vous endisse et avant votre update , cela provoquera une infraction dbconcurrency .

Cette erreur ne signifie pas que la ligne n'existe plus; Cela signifie simplement que cela n'a pas mis à jour une ligne pour une raison quelconque. Ma raison était que les données avaient trois états différents, donc il pensait que quelqu'un d'autre avait changé les données avant d'appeler la mise à jour.

BTW, il s'agit d'un seul MDF situé sur l'ordinateur des utilisateurs, donc personne d'autre n'a accès à celui-ci pour la modifier pendant la mise à jour. Un utilisateur, une mise à jour. Mon code était l'utilisateur "autre" utilisateur.

J'espère que cela peut aider à pointer quelqu'un d'autre dans la bonne direction pour leur application.


1 commentaires

Après toutes les modifications appellent simplement des fichiers de données.Acceptchanges ();



2
votes

Si je peux ajouter mes deux cents valeurs.

J'ai lutté avec cela pendant un moment. Dans notre application, nous avons calculé des colonnes sur lesquelles la colonne est le résultat d'un certain calcul de deux autres colonnes ou plus.

Ce recalc a jeté l'adaptateur.

Je devais définir sqlcommandbuilder.conflictoption = conflitoption.overitechanges pour contourner ce problème.

Je ne sais pas s'il y a une option pour dire à l'adaptateur d'ignorer les colonnes en lecture seule à la vérification.


0 commentaires

1
votes

Pour résoudre ce problème, j'ai simplement transformé une concurrence optimiste sur l'adaptateur de table:
- Ouvrez le jeu de données
- Cliquez avec le bouton droit sur l'adaptateur de table, choisissez Configurer ...
- Cliquez sur le bouton Avancé Options

- désélectionnez «Utiliser une simultané optimiste», cliquez sur OK
- Cliquez sur le reste de l'assistant.


1 commentaires

Après avoir poursuivi cette erreur pendant des jours, c'était la seule solution qui a fonctionné. Merci pour votre commentaire! Cela devrait être beaucoup plus élevé que ce qu'il est vraiment.