Saving updated binding source

  • Thread starter Thread starter alee
  • Start date Start date
A

alee

I created an object using BindingList<T> for GetObjects() and assigned that
to a objectBindingSource in a WinForm application. The ObjectBindingSource
then
assigned to a DataGridView. There was a objectBindingNavigation also on the
form. Everything worked as expected when I run the application. However,
after inserting
some new rows, deleting a few rows, and updating yet couple rows, the program
could not save the resulting datasource. I had a hard time converting the
result of the objectBindingSource to a typed DataSet Object table. Everytime
I tried to save, the system returned a message stating that the operation
created duplicated keys in the table and stopped. It appeared that after
converting the ObjectBindingSource to a typed dataset, all unchaged rows were
updated to the dataset as new rows.

I tried to solve the problem with a typed dataset table, it worked fine. But,
I can't rewrite all our business objects to use datatables and datarows
instead of BindingList<object> and objects.

Any suggestions or comments will be greatly appreciated.
 
You will need to elaborate on the problems encountered in saving as I never
have an issue with this. How do you objects get saved and what was the
problem doing this after they have been edited through a binding source.

Provide more error information and we may be able to help
 
alee said:
I created an object using BindingList<T> for GetObjects() and assigned
that
to a objectBindingSource in a WinForm application. The
ObjectBindingSource
then
assigned to a DataGridView. There was a objectBindingNavigation also on
the
form. Everything worked as expected when I run the application.
However,
after inserting
some new rows, deleting a few rows, and updating yet couple rows, the
program
could not save the resulting datasource. I had a hard time converting
the
result of the objectBindingSource to a typed DataSet Object table.
Everytime
I tried to save, the system returned a message stating that the operation
created duplicated keys in the table and stopped. It appeared that after
converting the ObjectBindingSource to a typed dataset, all unchaged rows
were
updated to the dataset as new rows.

I tried to solve the problem with a typed dataset table, it worked fine.
But,
I can't rewrite all our business objects to use datatables and datarows
instead of BindingList<object> and objects.

Any suggestions or comments will be greatly appreciated.

How are you trying to save the datasource? I am doing the same thing. I am
not using DataSets, though. I am handling the updates myself, in the class
for the object. I have a property in my class telling if the row was added
or modified. When they delete entries from my grid, I am saving those in
another list. When they hit save, I go through the list and perform the
inserts and updates, and then do the deletes of the deleted entries. So I
cache them and do them all at the end.

To set the rowstate, I'm capturing events on the list. My list is defined
as a BindingList(Of Company).

I figured this out using examples in Brian Noyes' data binding book, and
Chris Sells' Windows Forms 2.0 book. You don't have either of those, do
you?

Robin S.
 
Ciaran,

In the WinForm, I used:

private void dockBindingNavigatorSaveItem_Click(object sender, EventArgs e)
{

Dock dock = new Dock();
dockBS.EndEdit();
dock.UpdateDocks(dockBS.DataSource as BindingList<Dock>);
}

and in the Dock class, I used:

public void UpdateDocks(BindingList<Dock> docks)
{
DockandSlipDS.DockTableDataTable table = new
DockandSlipDS.DockTableDataTable();
foreach( Dock dock in docks)
{
DockandSlipDS.DockTableRow row = table.NewDockTableRow();
row.DockId = dock.DockID;
row.Location = dock.Location;
row.Electricity = dock.Electricity;
row.Water = dock.Water;
table.AddDockTableRow( row );
}
_dockTA.Update( table );
}

I guess I need a way to scan through each dock in the docks BindingList and
determine the rowstate. But I can't find a way to get the rowstate of the
returned
BindingList.

Cheers,

Alan L.
Ciaran said:
You will need to elaborate on the problems encountered in saving as I never
have an issue with this. How do you objects get saved and what was the
problem doing this after they have been edited through a binding source.

Provide more error information and we may be able to help
I created an object using BindingList<T> for GetObjects() and assigned that
to a objectBindingSource in a WinForm application. The ObjectBindingSource
[quoted text clipped - 15 lines]
Any suggestions or comments will be greatly appreciated.
 
Robin,

In the WinForm, I used:

private void dockBindingNavigatorSaveItem_Click(object sender, EventArgs e)
{
Dock dock = new Dock();
dockBS.EndEdit();
dock.UpdateDocks(dockBS.DataSource as BindingList<Dock>);
}

and in the Dock class located in a separate DLL, I used:

public void UpdateDocks(BindingList<Dock> docks)
{
DockandSlipDS.DockTableDataTable table = new
DockandSlipDS.DockTableDataTable();
foreach( Dock dock in docks)
{
DockandSlipDS.DockTableRow row = table.NewDockTableRow();
row.DockId = dock.DockID;
row.Location = dock.Location;
row.Electricity = dock.Electricity;
row.Water = dock.Water;
table.AddDockTableRow( row );
}
_dockTA.Update( table );
}

I guess I need a way to scan through each dock in the docks BindingList and
determine the rowstate. But I can't find a way to get the rowstate of the
returned. I don't have the two books you mentioned. Would it be possible
for you to give me some sample code for adding a rowstate detection event
inside
the Dock class to capture any change of rowstate.

Also, can you show me how you keep track of changes using another list while
we are using a BindingSource. A small example will be greatly appreciated.

Cheers,

Alan L.

I created an object using BindingList<T> for GetObjects() and assigned
that
[quoted text clipped - 24 lines]
Any suggestions or comments will be greatly appreciated.

How are you trying to save the datasource? I am doing the same thing. I am
not using DataSets, though. I am handling the updates myself, in the class
for the object. I have a property in my class telling if the row was added
or modified. When they delete entries from my grid, I am saving those in
another list. When they hit save, I go through the list and perform the
inserts and updates, and then do the deletes of the deleted entries. So I
cache them and do them all at the end.

To set the rowstate, I'm capturing events on the list. My list is defined
as a BindingList(Of Company).

I figured this out using examples in Brian Noyes' data binding book, and
Chris Sells' Windows Forms 2.0 book. You don't have either of those, do
you?

Robin S.
 
alee via DotNetMonster.com said:
Robin,

In the WinForm, I used:

private void dockBindingNavigatorSaveItem_Click(object sender, EventArgs
e)
{
Dock dock = new Dock();
dockBS.EndEdit();
dock.UpdateDocks(dockBS.DataSource as BindingList<Dock>);
}

and in the Dock class located in a separate DLL, I used:

public void UpdateDocks(BindingList<Dock> docks)
{
DockandSlipDS.DockTableDataTable table = new
DockandSlipDS.DockTableDataTable();
foreach( Dock dock in docks)
{
DockandSlipDS.DockTableRow row = table.NewDockTableRow();
row.DockId = dock.DockID;
row.Location = dock.Location;
row.Electricity = dock.Electricity;
row.Water = dock.Water;
table.AddDockTableRow( row );
}
_dockTA.Update( table );
}

I guess I need a way to scan through each dock in the docks BindingList
and
determine the rowstate. But I can't find a way to get the rowstate of
the
returned. I don't have the two books you mentioned. Would it be
possible
for you to give me some sample code for adding a rowstate detection event
inside
the Dock class to capture any change of rowstate.

Also, can you show me how you keep track of changes using another list
while
we are using a BindingSource. A small example will be greatly
appreciated.

Cheers,

Alan L.

There's no such thing as a small example for this stuff. ;-)

When I first tried to figure out how to make a list of my objects, show
them in a DataGridView, and support updating, it took me a few days, and
the help of those two books that I listed. I'm not using table adapters or
data adapters or datasets to do my updates, I'm handling them myself
through my business class.

The RowState stuff and methodology for updating, I got from Deborah
Kurata's "Doing Objects in VB2005". This is the book that taught me how to
segment my application into 3 layers. I call a Stored Procedure in my
DataAccess layer to do the updates one object at a time, and have the SP
check the rowstate to determine which SQL statement in the SP to run, just
like the data adapters work.

I have a base class from which I derive all of my business layer objects.
In that class, I have a rowstate enumerator defined with the items
Unchanged, Added, Deleted, and Modified.

When I load each object, I set it to unchanged, because it hasn't been
changed yet.
me.DataStateChanged(EntityStateEnum.Unchanged)

In my class, in the Set for each property, if the value is changed, I have
a call:
DataStateChanged(EntityStateEnum.Modified)

When they add a new row:
DataStateChanged(EntityStateEnum.Added)

When they delete a row, I check and make sure it's not one they have added
that hasn't been committed yet. If it is, I just remove it. If it's not, I
save it to a different list (so it doesn't show up in the grid) and do:
DataStateChanged(EntityStateEnum.Deleted)
I process these separately from the add/change list that is displayed to
the user.

This is the method used to change the state of my object. You have to be
careful; you can't just arbitrarily change it. For example, if they add a
row, and then before committing the changes, they change a field in the
row, you don't want it marked as Modified, you want it to still be marked
as Added because it hasn't been added yet.

Protected Sub DataStateChanged(ByVal dataState As EntityStateEnum)
'if the state is deleted, mark it as deleted
'if they are adding a new one, mark it as an add so
' the stored procedure knows to insert it
If dataState = EntityStateEnum.Deleted _
Or dataState = EntityStateEnum.Added Then
Me.EntityState = dataState
End If
If Me.EntityState = EntityStateEnum.Unchanged _
OrElse dataState = EntityStateEnum.Unchanged Then
'they are changing it from add or change or delete back to
unchanged
'or from unchanged to something else
Me.EntityState = dataState
End If
End Sub

A rowstate to expose this property (which is private):
Public ReadOnly Property RowState() as EntityStateEnum
Get
Return Me.EntityState
End Get
End Property

I hope this helps. If you want to know how to bind a list of objects to a
DataGridView, and handle the updates w/o casting to a dataset, post your
e-mail address in some format I can recognize and I'll send you an example.
It is not trivial the first time you do it. There may also be a way to do
it better, but I haven't had time to revisit it. It works, and works well,
and that's all I need.

Robin S.
 
Hello Robins,

I already solved the problem. I literally followed the similar steps you
took with one exception. That is I found a good VB.NET article from the
following URL:

http://blogs.msdn.com/vbteam/archive/2005/04/14/TableAdaptersAndObjects.aspx

Other than that I created one base class to hand entitystate (unchanged,
modified, added,
deleted) for all my entity classes to inherit from, and
one extended BaseList class which extends the BindingList<T> to support all
the
entity state updates with a built in property DeletedRows, which is updated
by
the entitystate management code in the base class.

By doing this, the Winform application simply uses the entity class object
without any
modifications.

Thanks for your suggestions and comments.

Cheers and Best regards,

Alan L.

[quoted text clipped - 44 lines]

There's no such thing as a small example for this stuff. ;-)

When I first tried to figure out how to make a list of my objects, show
them in a DataGridView, and support updating, it took me a few days, and
the help of those two books that I listed. I'm not using table adapters or
data adapters or datasets to do my updates, I'm handling them myself
through my business class.

The RowState stuff and methodology for updating, I got from Deborah
Kurata's "Doing Objects in VB2005". This is the book that taught me how to
segment my application into 3 layers. I call a Stored Procedure in my
DataAccess layer to do the updates one object at a time, and have the SP
check the rowstate to determine which SQL statement in the SP to run, just
like the data adapters work.

I have a base class from which I derive all of my business layer objects.
In that class, I have a rowstate enumerator defined with the items
Unchanged, Added, Deleted, and Modified.

When I load each object, I set it to unchanged, because it hasn't been
changed yet.
me.DataStateChanged(EntityStateEnum.Unchanged)

In my class, in the Set for each property, if the value is changed, I have
a call:
DataStateChanged(EntityStateEnum.Modified)

When they add a new row:
DataStateChanged(EntityStateEnum.Added)

When they delete a row, I check and make sure it's not one they have added
that hasn't been committed yet. If it is, I just remove it. If it's not, I
save it to a different list (so it doesn't show up in the grid) and do:
DataStateChanged(EntityStateEnum.Deleted)
I process these separately from the add/change list that is displayed to
the user.

This is the method used to change the state of my object. You have to be
careful; you can't just arbitrarily change it. For example, if they add a
row, and then before committing the changes, they change a field in the
row, you don't want it marked as Modified, you want it to still be marked
as Added because it hasn't been added yet.

Protected Sub DataStateChanged(ByVal dataState As EntityStateEnum)
'if the state is deleted, mark it as deleted
'if they are adding a new one, mark it as an add so
' the stored procedure knows to insert it
If dataState = EntityStateEnum.Deleted _
Or dataState = EntityStateEnum.Added Then
Me.EntityState = dataState
End If
If Me.EntityState = EntityStateEnum.Unchanged _
OrElse dataState = EntityStateEnum.Unchanged Then
'they are changing it from add or change or delete back to
unchanged
'or from unchanged to something else
Me.EntityState = dataState
End If
End Sub

A rowstate to expose this property (which is private):
Public ReadOnly Property RowState() as EntityStateEnum
Get
Return Me.EntityState
End Get
End Property

I hope this helps. If you want to know how to bind a list of objects to a
DataGridView, and handle the updates w/o casting to a dataset, post your
e-mail address in some format I can recognize and I'll send you an example.
It is not trivial the first time you do it. There may also be a way to do
it better, but I haven't had time to revisit it. It works, and works well,
and that's all I need.

Robin S.
 
That's cool, and thanks for the link. I'll check it out. Maybe it'll be
easier than what I'm doing!

Robin S.
------------------------------
alee via DotNetMonster.com said:
Hello Robins,

I already solved the problem. I literally followed the similar steps you
took with one exception. That is I found a good VB.NET article from the
following URL:

http://blogs.msdn.com/vbteam/archive/2005/04/14/TableAdaptersAndObjects.aspx

Other than that I created one base class to hand entitystate (unchanged,
modified, added,
deleted) for all my entity classes to inherit from, and
one extended BaseList class which extends the BindingList<T> to support
all
the
entity state updates with a built in property DeletedRows, which is
updated
by
the entitystate management code in the base class.

By doing this, the Winform application simply uses the entity class
object
without any
modifications.

Thanks for your suggestions and comments.

Cheers and Best regards,

Alan L.

[quoted text clipped - 44 lines]

There's no such thing as a small example for this stuff. ;-)

When I first tried to figure out how to make a list of my objects, show
them in a DataGridView, and support updating, it took me a few days, and
the help of those two books that I listed. I'm not using table adapters
or
data adapters or datasets to do my updates, I'm handling them myself
through my business class.

The RowState stuff and methodology for updating, I got from Deborah
Kurata's "Doing Objects in VB2005". This is the book that taught me how
to
segment my application into 3 layers. I call a Stored Procedure in my
DataAccess layer to do the updates one object at a time, and have the SP
check the rowstate to determine which SQL statement in the SP to run,
just
like the data adapters work.

I have a base class from which I derive all of my business layer objects.
In that class, I have a rowstate enumerator defined with the items
Unchanged, Added, Deleted, and Modified.

When I load each object, I set it to unchanged, because it hasn't been
changed yet.
me.DataStateChanged(EntityStateEnum.Unchanged)

In my class, in the Set for each property, if the value is changed, I
have
a call:
DataStateChanged(EntityStateEnum.Modified)

When they add a new row:
DataStateChanged(EntityStateEnum.Added)

When they delete a row, I check and make sure it's not one they have
added
that hasn't been committed yet. If it is, I just remove it. If it's not,
I
save it to a different list (so it doesn't show up in the grid) and do:
DataStateChanged(EntityStateEnum.Deleted)
I process these separately from the add/change list that is displayed to
the user.

This is the method used to change the state of my object. You have to be
careful; you can't just arbitrarily change it. For example, if they add a
row, and then before committing the changes, they change a field in the
row, you don't want it marked as Modified, you want it to still be marked
as Added because it hasn't been added yet.

Protected Sub DataStateChanged(ByVal dataState As EntityStateEnum)
'if the state is deleted, mark it as deleted
'if they are adding a new one, mark it as an add so
' the stored procedure knows to insert it
If dataState = EntityStateEnum.Deleted _
Or dataState = EntityStateEnum.Added Then
Me.EntityState = dataState
End If
If Me.EntityState = EntityStateEnum.Unchanged _
OrElse dataState = EntityStateEnum.Unchanged Then
'they are changing it from add or change or delete back to
unchanged
'or from unchanged to something else
Me.EntityState = dataState
End If
End Sub

A rowstate to expose this property (which is private):
Public ReadOnly Property RowState() as EntityStateEnum
Get
Return Me.EntityState
End Get
End Property

I hope this helps. If you want to know how to bind a list of objects to a
DataGridView, and handle the updates w/o casting to a dataset, post your
e-mail address in some format I can recognize and I'll send you an
example.
It is not trivial the first time you do it. There may also be a way to do
it better, but I haven't had time to revisit it. It works, and works
well,
and that's all I need.

Robin S.
 
Back
Top