DataSet.GetChanges() in RowChanged(DataRowAction.Add)

G

Guest

Hello,

I have a pretty difficult question about a hard-to-explain issue (I hope my
English would be good enough to make you understand). The environment beside
the problem itself may also be important, so I'm gonna explain a little the
whole idea and then go back to the issue and my question. Thanks in advance
for your time.

I am developing a .NET 1.1-based application that uses a main central
DataSet instance as a local cache storage for the current user-based slice of
data stored in an SQL Server database. The application consists of several
threads that may access the DataSet either to retreive data or for updating
data.

A special thread in the application is set to listen to all DataSet's
tables' RowChanged and RowDeleted events through a single event handler that
does something like this:

public void RowChanged(object sender, DataRowEventArgs e)
{
lock (myDataSet)
{
DataSet changes = myDataSet.GetChanges();
if (changes != null)
{
myDataSet.AcceptChanges();
//... Store changes in a changes queue, for later use in background
synchronization to the SQL Server database (using multiple
DataAdapter.Update() commands, one for each DataTable in the DataSet)
}
}
}

All the other threads that use the DataSet are using a lock(myDataSet) block
in order to maintain thread safety of the operations.

The idea here is to get all the changes that are done to the local DataSet
in a one-by-one way, so that I can update them back to the SQL Server (like a
"replication" synchronization) in a background thread and do not affect the
user's experience in that process.

Some would argue about the comment above that it won't be necessary to get
the changes one-by-one as I could from time to time execute a
myDataSet.GetChanges() in the background thread itself and update all the
changes back to the database at once -- however, this is not true because I
have circular relationships between the database tables, and the order of the
DataAdapter.Update() would be dependent on the actual changes done in the
DataSet (in order to not get exceptions regarding relationship constraints).
In some cases, for example for self-referring tables, there is no way to
update multiple circular chages using one single DataAdapter.Update() call
(because the data is updated sequentially by the adapter, and the order of
the changes is not the order of change occurence, but in the primary key
order - and in some cases, entities updated first would refer entities that
would be updated later and the database would complain after the first update
that the referencial integrity is lost).

Ok. Now back to my point. The idea above works in theory, and it also works
in practice but only for changes of these DataRowAction type: Change and
Delete. It doesn't work for Add. Specifically, when a new row is added in a
table in the DataSet, the new row is not got by the GetChanges() call in the
RowChanged event handler, although modified rows and deleted rows are. As I
read on other blogs and posts, it seems that this is a bug in the DataSet of
ADO .NET 1.1, and seems to be solved in .NET 2.0 (tested it myself).

However, because I need to stick with 1.1 for this application, what are
your suggestions regarding this issue? Specifically, how to get the Add
changes also? I even tried to add them manually, in case that e.RowAction ==
Add, by creating a new DataSet using myDataSet.clone() and adding the e.Row
in the table with the same name of the DataSet (also needed to set
EnforceConstraints to false for the changes to be able to do that) instead of
GetChanges() call, but I feel that this workaround is not my best choice.

Also, it's out of discussion to create a new thread that would be started by
the RowChanged event hander (to allow .NET add the row in the meantime, and
to be gettable with GetChanges() after that), and to do the GetChanges()
there - because of the problem that I cannot lock the DataSet from the event
hanlder function and release it in another thread... And what if .NET doesn't
add the row until the thread gets to the GetChanges() call...

Waiting for the Commit DataRowAction is also unapropriate because the
threads that add rows to the DataSet's tables do not call AcceptChanges() for
each Add operation they make...

I hope that there is another good and nice workaround for this problem -
maybe somebody else found it before me and can share the knowledge. Or at
least, advise me what other approach to take in order to reach my goals for
this application.

If in the meantime I will find any good workaround myself, I will post it
here.

Thank you again, in advance.
 
G

Guest

Hello, and thank you very much for your time to provide advice.

I realize now that I didn't describe well how the client application is
intended to run and what are our requirements on that part.

Well, the end-user that runs the client will need to run the application
directly from a Web site (under a Security Context) as a hosted Windows Forms
user control that is hosted in a web page (the user is required to have .NET
Framework installed on the client machine, but not any SQL Server). That
being said, I am not able to use a client side edition of SQL Server and do
synchronization that way.

The client uses Isolated Storage to maintain data locally between subsequent
runs of the application on the client, and we use DataSet write and read
operations from XML files stored in Isolated Storage. We like this benefit of
the DataSet.

Also, it is important that DataSets are features directly exposed by .NET
Framework, without needing us to provide any third party components
(libraries) to be downloaded on the client with the Windows User
Control-based application.

And finally, we really need a relational way to store data as we have about
20 tables in different relations with eachother in the database, and we need
to have the same structure on the client side. The client uses the local
cache typed DataSet as if it were a database (with relations defined within
the DataSet), using the generated methods for each table. So we cannot use
collections or other types of objects (or we can use such objects, but we
would need to develop them and it's no need for them because the exact thing
is done by generating the typed DataSet).

Hopefully, I cleared up the ideas about our application. As a review, I will
say that the application must only use .NET Framework (no third-party
components), should leverage all DataSet functions on the client (i.e.
caching data between runs in the local Isolated Storage and getting and
updating relational data using autogenerated methods in the DataTables of the
typed DataSet), and the data needs to be automatically synchronized with a
central server (SQL Server) in background. Of course, depending on the user
who logged in to the client, only some data (a horizontal slice of the
database - so all tables would be represented, but not all data in each of
them) will be synchronized from the server to the client (based on the
permissions of that user).

--
Sorin Dolha, DlhSoft
MCAD, MCSD .NET


W.G. Ryan MVP said:
Sorin:

The following recommendation is based solely on what I understand to be the
nature of your program and not generall what I'd advise. The first thing
that comes to mind is using Sql Server CE or Sql Mobile , or Oracle Lite and
just use it as the back end - then do the synchronization there. There are
some killer benefits in the 2.0 framework to this approach but as you
mentioned, you want to stick with 1.1. What you get by doing this is a
trusted, tested, performant and flexible way to solve your problem.
Moreoever, if the way synchronization needs to be handled changes in the
future, changing the synchronization model is pretty simple and can be done
almost transparently. If you roll your own (which may for reasons I'm not
aware of yet not be feasible) you are essentially re-creating a very very
complex wheel. By using Sql CE or Sql Mobile etc, you also have tremendous
advantages in terms of security and conflict resolution that would be next
to impossible (and definitely something undesirable) to recreate).

I'm not sure if it's possible, but from the sounds of it, you can use other
events, like Button clicks or other UI Cues to do the same thing you are
trying to accomplish with the datatable events. Would I normally suggest
using the UI instead of the objects themselves. NO. But your case is
specific and depending on what you need, it may be a viable solution.

Finally, and remember, I only say this b/c of the specific nature of your
app, if none of the above will work, is it possible that you can not use a
DataSet/DataTable as your primary object for storage? For instance, if you
don't need Sorting, Selecting, Computing etc and you're just using the
objects as data stores, then you could just roll your own collection of
collections and add those events in yourself. Normally (as you can tell
from my first suggestion), I'd not recommend rolling your own object when
there's already something peer reviewed and widely used (like DataSets) that
are already coded. But, in cases where you don't need the specific
functionality of a datatable/dataview/dataset, and you're just using them to
store data, then it may make sense. Remember that you can implement the
same interfaces for instances, so that you can still bind to them or
effectively make your new object have all the features that users would
normally want (I know, this sounds contradictory but what I mean is that you
can implement the thing partially) recreating only the features that the
application needs.

I know i covered vastly different approaches here and I may well have not
understood your requirements correctly - if that's the case, please let me
know and I'll take a stab at it again,

Thanks,

Bill
 
W

William \(Bill\) Vaughn

Given this scenario, have you considered SQL Express (or MSDE) and use
replication to keep the client and server in sync? This would seem to
address several of your issues.

--
____________________________________
William (Bill) Vaughn
Author, Mentor, Consultant
Microsoft MVP
www.betav.com/blog/billva
www.betav.com
Please reply only to the newsgroup so that others can benefit.
This posting is provided "AS IS" with no warranties, and confers no rights.
__________________________________

Sorin Dolha said:
Hello, and thank you very much for your time to provide advice.

I realize now that I didn't describe well how the client application is
intended to run and what are our requirements on that part.

Well, the end-user that runs the client will need to run the application
directly from a Web site (under a Security Context) as a hosted Windows
Forms
user control that is hosted in a web page (the user is required to have
.NET
Framework installed on the client machine, but not any SQL Server). That
being said, I am not able to use a client side edition of SQL Server and
do
synchronization that way.

The client uses Isolated Storage to maintain data locally between
subsequent
runs of the application on the client, and we use DataSet write and read
operations from XML files stored in Isolated Storage. We like this benefit
of
the DataSet.

Also, it is important that DataSets are features directly exposed by .NET
Framework, without needing us to provide any third party components
(libraries) to be downloaded on the client with the Windows User
Control-based application.

And finally, we really need a relational way to store data as we have
about
20 tables in different relations with eachother in the database, and we
need
to have the same structure on the client side. The client uses the local
cache typed DataSet as if it were a database (with relations defined
within
the DataSet), using the generated methods for each table. So we cannot use
collections or other types of objects (or we can use such objects, but we
would need to develop them and it's no need for them because the exact
thing
is done by generating the typed DataSet).

Hopefully, I cleared up the ideas about our application. As a review, I
will
say that the application must only use .NET Framework (no third-party
components), should leverage all DataSet functions on the client (i.e.
caching data between runs in the local Isolated Storage and getting and
updating relational data using autogenerated methods in the DataTables of
the
typed DataSet), and the data needs to be automatically synchronized with a
central server (SQL Server) in background. Of course, depending on the
user
who logged in to the client, only some data (a horizontal slice of the
database - so all tables would be represented, but not all data in each of
them) will be synchronized from the server to the client (based on the
permissions of that user).
 
G

Guest

I believe that to use MSDE on the client side would request that the end-user
to download and install our application as an installation package and will
lose our ability to deploy the application as a Windows Forms User Control
hosted in the browser (which doesn't require the end-user to manually
download anything - the browser will automatically download the Windows Forms
User Control dlls and run them in a Security Context - in the Security
Context I don't believe that we could access a MSDE, and we could not install
MSDE on the client in the first place, anyway).

However, I believe using MSDE and a full package installation would be a
good-enough choice for us (even if we would lose what I explained above)
because the gain of SQL replication I believe it's better than our "by-hand"
DataSet synchronization... However we will need to discuss this with our
client, which currently specifically requested that the application would
need to be able to run directly from a Web page (supposed that the user has
..NET FW installed...)
 
W

William \(Bill\) Vaughn

I would carefully study the (many) benefits of "one touch" deployment
implemented with VS 2005. I have seen several sites that are implementing
SQL Express rigs using this approach. The client "sees" a web site to start
with and all of the download details are handled for you behind the scenes.
If you app is updated, it's downloaded again or (if not), it's simply run
from the locally installed file(s).

--
____________________________________
William (Bill) Vaughn
Author, Mentor, Consultant
Microsoft MVP
INETA Speaker
www.betav.com/blog/billva
www.betav.com
Please reply only to the newsgroup so that others can benefit.
This posting is provided "AS IS" with no warranties, and confers no rights.
__________________________________
 
G

Guest

We have already reviewed the ClickOnce technology and other technologies that
..NET 2.0 brings on, and I also believe that it would be a nice way to do
things. I wasn't aware however about the ability to use SQL Express
installation in background from ClickOnce -- this would be very nice.

However, again, we will need to convince our customer about using 2.0, which
is currently in Beta (and even after the launch in November as I heard - it
wouln't be a too-mature technology)...

But thank you for all your advice.
 
W

William \(Bill\) Vaughn

Ah, saying that 2.0 is not a mature technology (but implying that 1.1 is)
seems strange. I would say that 2.0 is more "mature" in that it's more
complete, more feature-rich and more bugs have been resolved than 1.1. I
understand that 2.0 has been installed in over 100 large customer sites on
production servers for some time now.

--
____________________________________
William (Bill) Vaughn
Author, Mentor, Consultant
Microsoft MVP
INETA Speaker
www.betav.com/blog/billva
www.betav.com
Please reply only to the newsgroup so that others can benefit.
This posting is provided "AS IS" with no warranties, and confers no rights.
__________________________________
 
G

Guest

I completely agree with you as a developer.

But customers are not developers and hesitate about using beta technologies.
And myself, I wouldn't give more credit to a v2 Beta software component than
for v1 release of the same component (launched a few years ago, for example).
That's because usually beta software contains [more] bugs [than a released,
throughly tested, widely-used for a couple of years technology].

Of course, .NET beta can be tested and is tested in our labs - and I
personally find it very mature and a lot less buggy than I expected (at least
in beta 2 - beta 1 was not this choice). But you know, as a developer, you
cannot expect to convince somebody to use beta technology very easily - even
if you present all the advantages etc. because "maturity" needs time and is
measured from the release...
 
W

William \(Bill\) Vaughn

So don't talk to them as if it's beta software or don't mention that you're
planning to use 2.0 until after October 15th (or so) when it goes to RTM and
is no longer "beta".

--
____________________________________
William (Bill) Vaughn
Author, Mentor, Consultant
Microsoft MVP
INETA Speaker
www.betav.com/blog/billva
www.betav.com
Please reply only to the newsgroup so that others can benefit.
This posting is provided "AS IS" with no warranties, and confers no rights.
__________________________________

Sorin Dolha said:
I completely agree with you as a developer.

But customers are not developers and hesitate about using beta
technologies.
And myself, I wouldn't give more credit to a v2 Beta software component
than
for v1 release of the same component (launched a few years ago, for
example).
That's because usually beta software contains [more] bugs [than a
released,
throughly tested, widely-used for a couple of years technology].

Of course, .NET beta can be tested and is tested in our labs - and I
personally find it very mature and a lot less buggy than I expected (at
least
in beta 2 - beta 1 was not this choice). But you know, as a developer, you
cannot expect to convince somebody to use beta technology very easily -
even
if you present all the advantages etc. because "maturity" needs time and
is
measured from the release...

--
Sorin Dolha, DlhSoft
MCAD, MCSD .NET


William (Bill) Vaughn said:
Ah, saying that 2.0 is not a mature technology (but implying that 1.1 is)
seems strange. I would say that 2.0 is more "mature" in that it's more
complete, more feature-rich and more bugs have been resolved than 1.1. I
understand that 2.0 has been installed in over 100 large customer sites
on
production servers for some time now.

--
____________________________________
William (Bill) Vaughn
Author, Mentor, Consultant
Microsoft MVP
INETA Speaker
www.betav.com/blog/billva
www.betav.com
Please reply only to the newsgroup so that others can benefit.
This posting is provided "AS IS" with no warranties, and confers no
rights.
__________________________________
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top