Re: DataSet.GetChanges() in RowChanged(DataRowAction.Add)
- From: "Sorin Dolha" <sdolha@xxxxxxxxxxxxxxxx>
- Date: Sun, 18 Sep 2005 13:27:03 -0700
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...)
--
Sorin Dolha, DlhSoft
MCAD, MCSD .NET
"William (Bill) Vaughn" wrote:
> 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" <sdolha@xxxxxxxxxxxxxxxx> wrote in message
> news:FBEFD1D2-485E-496A-9DAD-B0FE557BD6E3@xxxxxxxxxxxxxxxx
> > 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" wrote:
> >
> >> 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
> >>
> >>
> >>
> >>
> >>
> >> "Sorin Dolha" <sdolha@xxxxxxxxxxxxxxxx> wrote in message
> >> news:162C393C-A419-4FA2-B38B-5EC57D06CA82@xxxxxxxxxxxxxxxx
> >> > 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.
> >> >
> >> > --
.
- Follow-Ups:
- Re: DataSet.GetChanges() in RowChanged(DataRowAction.Add)
- From: William \(Bill\) Vaughn
- Re: DataSet.GetChanges() in RowChanged(DataRowAction.Add)
- References:
- Re: DataSet.GetChanges() in RowChanged(DataRowAction.Add)
- From: W.G. Ryan MVP
- Re: DataSet.GetChanges() in RowChanged(DataRowAction.Add)
- From: Sorin Dolha
- Re: DataSet.GetChanges() in RowChanged(DataRowAction.Add)
- From: William \(Bill\) Vaughn
- Re: DataSet.GetChanges() in RowChanged(DataRowAction.Add)
- Prev by Date: Re: How can I sort a datetime column in a dataset.
- Next by Date: Re: DataSet.GetChanges() in RowChanged(DataRowAction.Add)
- Previous by thread: Re: DataSet.GetChanges() in RowChanged(DataRowAction.Add)
- Next by thread: Re: DataSet.GetChanges() in RowChanged(DataRowAction.Add)
- Index(es):