Re: DataSet and serialization is dangerous

Tech Tip: Click here to run a free scan for Windows Errors and optimize PC performance

From: Mauricio Pires (MauricioPires_at_discussions.microsoft.com)
Date: 02/09/05


Date: Wed, 9 Feb 2005 09:27:03 -0800

Hi ABad,
Excuse I am late. I live in Brazil and here has carnival (4 days). In Rio it
is very famous. Do you like carnival?
Let's go to work.
Imagine a server giving the dataset to a client application. The client
binds this dataset to a datagrid. The client user deletes the father row and,
afterwards, decides to create the same row again. What the client must return
to the server? Isn't the dataset.GetChanges?
I would like to say when a return the dataset.GetChanges to a local method,
it works ok, but if I return to a remote server by remoting, it doesn't work
(the child row vanishes) and I think the serialization doesn't work ok in
this case.
I change your example program again (the code is above) creating a new
column in father table. You will see that the father row was inserted, but
there is no child.
Code:
Sub CreateSchema(ByVal InDS As DataSet)
        Dim FatherTable As New DataTable("FatherTable")
        Dim ChildTable As New DataTable("ChildTable")
        Dim fatherCol1 As New DataColumn("FatherCol1")
        'I create a new column in father table
        Dim fatherCol2 As New DataColumn("FatherCol2")
        Dim childCol1 As New DataColumn("ChildCol1")
        Dim childCol2 As New DataColumn("ChildCol2")
        FatherTable.Columns.Add(fatherCol1)
        FatherTable.Columns.Add(fatherCol2)
        ChildTable.Columns.Add(childCol1)
        ChildTable.Columns.Add(childCol2)
        FatherTable.PrimaryKey = New DataColumn() {fatherCol1}
        InDS.Tables.Add(FatherTable)
        InDS.Tables.Add(ChildTable)
        InDS.Relations.Add("FatherChildRelation", fatherCol1, childCol1)
    End Sub
    Function CreateOriginalDataset() As DataSet
        Dim dsOriginal As New DataSet
        CreateSchema(dsOriginal)
        dsOriginal.Tables("FatherTable").Rows.Add(New Object() {"Father1",
"Col1"})
        dsOriginal.AcceptChanges()
        Return dsOriginal
    End Function

    Sub WorkWithDataset(ByVal WorkingDataSet As DataSet)
        WorkingDataSet.Tables("FatherTable").Rows(0).Delete()
        WorkingDataSet.Tables("FatherTable").Rows.Add(New Object()
{"Father1", "ColChanged"})
        WorkingDataSet.Tables("ChildTable").Rows.Add(New Object()
{"Father1", "Child1"})
    End Sub

    Sub Main()
        'dsOriginal is the server copy
        Dim dsOriginal As DataSet = CreateOriginalDataset()

        'dsWorking is the client copy
        'starts off with original copy
        Dim dsWorking As DataSet = dsOriginal.Copy
        'client copy is modified
        WorkWithDataset(dsWorking)

        'get changes to send to the server<===
        Dim dsChanges As DataSet = dsWorking.GetChanges

        'persist out the changes (remoting process) <===
        dsChanges.WriteXml("myFileName.xml", XmlWriteMode.DiffGram)

        'read back in the changes (remoting processs) <===
        Dim dsRead As New DataSet
        CreateSchema(dsRead)
        dsRead.ReadXml("myFileName.xml", XmlReadMode.DiffGram)

        'merge client side changes to the server copy
        dsOriginal.Merge(dsRead.GetChanges)
        dsOriginal.AcceptChanges()

        Console.WriteLine("")
        Console.WriteLine("****
ORIGINAL*****************************************************")
        Console.WriteLine("")
        dsOriginal.WriteXml(Console.Out)

        Console.WriteLine("")
        Console.WriteLine("**** WORKING
*****************************************************")
        Console.WriteLine("")
        dsWorking.WriteXml(Console.Out)
        Console.ReadLine()
    End Sub

"ABad" wrote:

> In other words change you client side logic From:
> - Delete Father1 from Father Table
> - Add Father1 to Father Table
> - Add Child1 to Child Table with relationship to Father1 in Father
> Table
>
>
> To:
> - Delete Father1 from Father Table
> - Undo Father1 delete or rollback
> - Add Child1 to Child Table with relationship to Father1 in Father
> Table
>
>
>
> "ABad" <anonymous@discussions.microsoft.com> wrote in message
> news:%23UH$$2rCFHA.1836@tk2msftngp13.phx.gbl...
> > I don't think you are getting what I'm trying to show you. Take a step
> back
> > and look at what your example is doing at the *client only* for second.
> >
> > Original state:
> > - Father1 in Father Table
> >
> > Changes done by your example:
> > - Delete Father1 from Father Table
> > - Add Father1 to Father Table
> > - Add Child1 to Child Table with relationship to Father1 in Father
> Table
> >
> > The client side XML changes that are being sent to the server are:
> > Before Snapshot:
> > - Father1 in Father Table
> > Proposed Changes
> > - Insert Father1 to Father Table
> > - Add Child1 to Child Table with relationship to Father1 in Father
> > Table
> >
> > Do you see the problem in the client side XML changes that you sending to
> > the server? Look closely. You are telling the server that Father1 already
> > exists but *insert* another Father1 with a new Child1. The server doesn't
> do
> > the proposed changes of insert Father1 and Child1 because there is a
> unique
> > constraint on the Father table, and you are telling it to insert a
> duplicate
> > record. The result is the server only shows the Before Snapshot. My
> example
> > where the events are attached show this is exactly what is happening.
> >
> > If you look at the XML changes from my final example you will see:
> > Before Snapshot:
> > - Father1 in Father Table
> > Proposed Changes
> > - Modified Father1 to Father Table
> > - Add Child1 to Child Table with relationship to Father1 in Father
> > Table
> >
> > Do you see the difference? These XML changes do not try to insert another
> > Father1 record but modifies it. This is why my example works and this is
> > what your final XML changes should have when sent to the server.
> >
> > - ABad
> >
> >
> >
> > "Mauricio Pires" <MauricioPires@discussions.microsoft.com> wrote in
> message
> > news:5CB5B45B-68F5-40D7-9F77-F3613418EB70@microsoft.com...
> > > Hi ABad,
> > > Excuse me, but I think your code doesn't actually represent the remoting
> > > process (or am I wrong?).
> > > I did some changes in your code (sub Main() only) that I think be more
> > > similar to remoting process. The child row vanished.
> > > Thanks.
> > >
> > > Sub Main()
> > > 'dsOriginal is the server copy
> > > Dim dsOriginal As DataSet = CreateOriginalDataset()
> > >
> > > 'dsWorking is the client copy
> > > 'starts off with original copy
> > > Dim dsWorking As DataSet = dsOriginal.Copy
> > > 'client copy is modified
> > > WorkWithDataset(dsWorking)
> > >
> > > 'get changes to send to the server<===
> > > Dim dsChanges As DataSet = dsWorking.GetChanges
> > >
> > > 'persist out the changes (remoting process) <===
> > > dsChanges.WriteXml("myFileName.xml", XmlWriteMode.DiffGram)
> > >
> > > 'read back in the changes (remoting processs) <===
> > > Dim dsRead As New DataSet
> > > CreateSchema(dsRead)
> > > dsRead.ReadXml("myFileName.xml", XmlReadMode.DiffGram)
> > >
> > > 'merge client side changes to the server copy
> > > dsOriginal.Merge(dsRead.GetChanges)
> > > dsOriginal.AcceptChanges()
> > >
> > > Console.WriteLine("")
> > > Console.WriteLine("****
> > > ORIGINAL*****************************************************")
> > > Console.WriteLine("")
> > > dsOriginal.WriteXml(Console.Out)
> > >
> > > Console.WriteLine("")
> > > Console.WriteLine("**** WORKING
> > > *****************************************************")
> > > Console.WriteLine("")
> > > dsWorking.WriteXml(Console.Out)
> > > Console.ReadLine()
> > > End Sub
> > >
> > >
> >
> >
>
>
>



Relevant Pages

  • Chat client/server print failed
    ... This is a chat client wrote in perl Gtk2. ... is the print statement in the send_msg_all sub. ... leave the server running for testing purposes. ... # just read means there is a complete request waiting ...
    (comp.lang.perl.misc)
  • Re: Chat client/server print failed
    ... is the print statement in the send_msg_all sub. ... leave the server running for testing purposes. ... # This would be the end of file, so close the client ... # just read means there is a complete request waiting ...
    (comp.lang.perl.misc)
  • Re: client close the socket. how the server knows?
    ... the server know that the socket is closed from the client side. ... > Private Delegate Sub UpdateListBoxDel(ByVal Data As String) ... > Private Sub Button1_Click(ByVal sender As System.Object, ...
    (microsoft.public.dotnet.languages.vb)
  • Re: Event doesnt work in late binding?
    ... fAddObjectReference = False ... ObjClient.eInitialized ' late bound the client must have a sub ... i have a COM project server wich is capable of sending events to both ...
    (microsoft.public.vb.enterprise)
  • Re: Event doesnt work in late binding?
    ... caller must be com object, or can be ordinary class in VB? ... ObjClient.eInitialized ' late bound the client must have a sub eInitialized ... pass a client object pointer to the server, now from the server side we can call client methods in this object ...
    (microsoft.public.vb.enterprise)