none
Problems with TableAdapterManager.UpdateAll() with related tables RRS feed

  • Question

  • I have added two related tables (one to one) to a datasource, then dragged a grid for the master table to a form and the fields for the other table to the same form.
    As I scroll through the grid for the master table, the contents of the related table change accordingly.
    When I try saving my changes, all changes get made to the master table, but the only the current (visible) changes get made to the other table.

    The RowState of an altered row that is not visible is "Unchanged", even though the Original and Proposed values of aun updated field differ.

    I have tried various means of saving my changes (including using AcceptChanges()), but the following has been the least bad option.  [I have also tried using xxxTableAdapter.Update(yyy) x2, but this did not improve things.

    What am I doing wrong?

                this.Validate();
                this.peopleBindingSource.EndEdit();  // The Master table.
                this.peopleAddressBindingSource.EndEdit();  // The related table.
                this.tableAdapterManager.UpdateAll(this.support_LogDataSet);
    


    • Moved by VMazurModerator Tuesday, October 13, 2009 10:16 AM (From:ADO.NET Data Providers)
    Monday, October 12, 2009 10:29 AM

All replies

  • I have done a bit more investigation...

    The code in my original entry to do the change works OK if I update the related table in a DataGrid, but not if using individual controls (e.g. a bound TextBox).
    The problem seems to be that the peopleAddressBindingSource.EndEdit() only works for the current record, with the other changes remaining as "Proposed" rather than current. 

    The following code can get round the problem, but I feel it should not be necessary!


                foreach (DataRow checkRow in support_LogDataSet.PeopleAddress)
                {
    
                    if ((checkRow.RowState == DataRowState.Unchanged)
                        && (checkRow.HasVersion(DataRowVersion.Proposed)))
                    {
                        // Need to call EndEdit() for row...
                        checkRow.EndEdit();
                    }
                }
    

    If anyone has any ideas I would still be eager to learn.
    Monday, October 12, 2009 4:28 PM
  • Hi Phil,

     

    I’ve tested it on my computer and it works well.

    I drag the two datagridview to the form as follows,

     

     

    Then the save button’s click event is like this,

     

                parentBindingSource.EndEdit();

                this.tableAdapterManager.UpdateAll(this.sQLServer2005DBDataSet);

     

    The generated code about bindingsource is like this,

     

    this.childBindingSource.DataSource = this.parentBindingSource;

     

     

    Could you give more information about your problem?

    Please update the thread and we will have a further discussion.

     

     

    Best Regards

    Yichun Feng

     


    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Wednesday, October 14, 2009 6:07 AM
  • Yichun,

    When I used 2 DataGridViews (as I think you did) everything worked OK.

    It was when I used Details for the child (Course in your code example) that things went wrong.  [I have a one to one relationship between parent and child, so individual controls are more appropriate for the child.]

    I can confirm that the two BindingSources are linked in the way you describe.

    The code for the save button's click event was the same as yours, but I also included a childBindingSource.EndEdit() as well.
    Regardless of where I include childBindingSource.EndEdit() or not, updates made using the child controls are lost unless they are current when I do the save.

    Thanks for trying things out.

    Phil
    Wednesday, October 14, 2009 4:39 PM
  • Hi Phil,

    I believe that it is by design. Since the child shows textboxs is not common, I'll consult the product team for it.


    Best Regards
    Yichun Feng
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.
    Welcome to the All-In-One Code Framework! If you have any feedback, please tell us.
    Sunday, October 18, 2009 8:42 AM
  • Phil, could you post the code you are using to DataBind the grid and the TextBox?

    Part of the issue may be that you've used different binding syntaxes. Here's an example of what I mean (http://geek-goddess-bonnie.blogspot.com/2009/09/keeping-datagrids-and-other-ui-controls.html) ... I'm not using a BindingSource, instead directly binding to a DataTable in a DataSet, but the concept is the same.
    ~~Bonnie Berent [C# MVP]

    geek-goddess-bonnie.blogspot.com
    Sunday, October 18, 2009 4:45 PM
  • Bonnie,

    The bindings that I am using are those created by my drag and drop.

    In the case of the grid, this has it's DataSource set to the parent's BindingSource, and the BindingSource has the DataSet as its DataSource and the (string) name of the parent table as its DataMember:
    parentBindingSource.DataMember = "Parent";
    parentBindingSource.DataSource = this.xxxDataSet;

    For the Textbox, hovering my mouse over the Text property reveals the child's BindingSource + " - " + the name of the field.
    Looking in the Form's Designer.cs file, the Text Box has the following binding:
    this.uniqueNoTextBox.DataBindings.Add(new System.Windows.Forms.Binding("Text", this.childBindingSource, "UniqueNo", true));
    The child's BindingSource has the DataSource set to the parent's BindingSource, and its DataMember to the (string) name of the relation between the two tables:


    Look at the example from your blog "Keeping DataGrids And Other UI Controls In Sync", your example involves just one example not two.
    I can see that I have the grid bound using a DataMember, but the text but is not (third parameter in the Binding constructor is "UniqueNo", not child.UniqueNo). 

    I tried changing the parent's BindingSource to the DataTable rather than the DataSet, which I did in the Constructor after InitializeComponent(), but this did not make things any better (or worse):
    parentBindingSource.DataSource = xxxDataSet.Parent;
    parentBindingSource.DataMember =
    null;
    [I could not do this in Form Design as it would not show me the DataTables.]

    If I add a DataGrid for the child table using drag and drop, this has it's DataSource set to the child's BindingSource, which means that effectlively it is bound in the same way as the TextBox.
    Not sure where this gets us...
    Friday, October 23, 2009 11:02 AM
  • >...your example involves just one example not two.<
    No, there are two examples (binding with two different syntaxes). Two things I did NOT include in my blog post, however, was binding using BindingSources and binding using Relations. I'll amend my blog at some point.

    But that doesn't appear to be what your problem is. Sorry to lead you down a wild goose chase. I should have caught this after your second post. You're right that the childBindingSource.EndEdit() is only ending the edit of the current row (that's because that's the only row associated with the relationship that the BindingSource is tied to). The solution you used (DataRow.EndEdit() of rows that have DataRowVersion.Proposed) will work. And I have used that myself.

    But, you can get around that another way ... albeit, it too seems a bit kludgy. And that's by creating one more BindingSource. You don't actually bind it to anything though ... but you still do an EndEdit() on it. Here's what I mean:
    parentBindingSource.DataSource = this.xxxDataSet;
    parentBindingSource.DataMember = "Parent";
     
    childBindingSource.DataSource = parentBindingSource;
    childBindingSource.DataMember = "MyRelation";
     
    childtableBindingSource.DataSource = this.xxxDataSet;
    childtableBindingSource.DataMember = "MyRelatedTable";
    Now, when you set the DataSource to your Grid and add the Binding to your TextBox, you do it the same way you did before:
    this.MyGrid.DataSource = parentBindingSource;
    this.MyTextBox.DataBindings.Add("Text", childBindingSource, "UniqueNumber");
    You do nothing with the childtableBindingSource until you're ready to save. Then, you do an EndEdit() for childtableBindingSource instead of childBindingSource.
    parentBindingSource.EndEdit();
    childtableBindingSource.EndEdit();

    ~~Bonnie Berent [C# MVP]

    geek-goddess-bonnie.blogspot.com
    Friday, October 23, 2009 9:07 PM