Link to home
Start Free TrialLog in
Avatar of atomicgs12
atomicgs12Flag for United States of America

asked on

DataSet.Merge eats up a lot of memory Visual Basic/Database

I have a visual basic application that has about 5 or 6 forms and each form is associated with the same database. The problem is that on each load of the form the current code does a .dataset.merge with the current database against the database downloaded from the server. The onboard database is only about 1kb in size but on each 'merge' the memory seems to decrease by almost 1mb. If I comment out the 'merge' and only load the form hardly any memory is used. These forms are pre-loaded at start up so the memory is held up to a point where when the last page is loaded the application crashes, at different times/points. My question is it normal for a 'merge' to eat up so much memory? Is there a more elegant way of doing a merge maybe so that I don't have to do it for each form but only once and all the forms have access to same and only one merge?

Thanks
Avatar of Jeff Certain
Jeff Certain
Flag of United States of America image

I'm a little confused about your scenario. Specifically, why are you merging the data from several forms into a single DataSet?

Once I understand the problem a bit better, I'm sure I can help guide you down a better path. :)
Avatar of atomicgs12

ASKER

Maybe I am explaining it incorrectly. There is a local db, myDBLocal and what I am presuming is the db that synchs with the server, mdDB.
Basically there is a call like:
ToLaunch.myDSData.Merge(myRefData)

Where from different parts of the code the variables are declared as follows:
Partial Class myDBLocal
    Partial Class RL_InventoryDataTable

    End Class

End Class

Private myRefData As New Schemas. myDBLocal
ByVal ToLaunch As FormBase
Public WithEvents myDSData As Schemas. myDBLocal
 I guess looking at it more closely now I see that the merge is on the same db but I don't really understand what is going on and why each call to ToLaunch.myDSData.Merge is eating up so much memory.

Thanks
Avatar of Nasir Razzaq
I think what you can do is keep the dataset in a module where its accessible to all the forms. Then in the load of main form, do the merge only once and you can use the dataset for the life of your application.
Do you have a link to some example that might do something like this and/or can you give me a simplified example. Something I could follow and adapt to my application?
THanks
Add a new item of type Module in the project. Add following code


Public Module Module1
Public MyDS As New DataSet

End Module


Now you can access MyDS across the whole app and it will remain in scope. You may also add any global functions in this module and call them from anywhere in the app.
thanks CodeCruiser. Do you have any idea why they would be calling a 'merge' on the dataset of itself each time a form/page is opened?
>Do you have any idea why they would be calling a 'merge' on the dataset of itself each time a form/page is opened?

Not sure I understand your question. Who are "they"?
In the application, as I stated before, as each form is created the code is calling dataset.merge. My question was do you have any idea why the original designer(s) 'they' would be calling merge as each form is initialized?
I have no idea. You would have to find that out. Is there any changes being made to db or dataset between the forms opening?
"Is there any changes being made to db or dataset between the forms opening? " No, it's like the forms are just synching/merging with the original database and attaching themselves (the forms) to the merged dataset. Seems odd.
Then the shared dataset would make more sense.
How would I go about associating my global dataset, say I call it g_DS with each form/page as it is done with the call ToLaunch.myDSData.Merge(myRefData)? Is there some way like ToLaunch.myDSData = g_DS or some other method?

Thanks
The global dataset is accessible in each form so you dont have to associate it. You can reference it directly as g_DS in any form.
CodeCruiser: thanks

Sorry for all the questions but I'm a little confused from your original answer. You said to create a global like:
Public Module Module1
Public MyDS As New DataSet

End Module

and originally I said I had to database/schemes or what every they are called, myRefData  and  myDSData ,  and they where created like:

Private myRefData As New Schemas. myDBLocal
Public WithEvents myDSData As Schemas. myDBLocal

So in your above example when you said 'Public MyDS As New DataSet' which of the two, myRefData  and  myDSData, are you saying MyDS is equivalen to?

Also is doing 'Public WithEvents myDSData As Schemas. myDBLocal' creating myDSData as a 'DataSet'?
Either I missed your comment about schema etc or you did not mention it before. I assumed based on "DataSet.Merge" that we are dealing with dataset.
"Either I missed your comment about schema etc or you did not mention it before. I assumed based on "DataSet.Merge" that we are dealing with dataset. " 

So now what? Was there more to follow in your last message?
Show me the full code that is doing the merging. Is it same in every form?
Yes it is the same for every form:
THe code is below, I could not paste everything it would have been way to long but the offending code is below with some pseudo code in place of larger sections:

Private myDSref As New Schemas.myDBLocal
Public WithEvents myDSstage As Schemas.myDBLocal

Me.myDSstage = New Schemas.myDBLocal
Me.myDSstage.DataSetName = "myDBLocal"
Me.myDSstage.Prefix = ""
Me.myDSstage.SchemaSerializationMode = System.Data.SchemaSerializationMode.IncludeSchema

Me.LoadRefData(myDSref)

Private Sub LoadRefData(ByVal mdsRd As Schemas.myDBLocal)
    Dim dtaLot As New Schemas.myDBLocalTableAdapters.RL_LotTableAdapter
    Dim dtaRow As New Schemas.myDBLocalTableAdapters.RL_RowTableAdapter
    Dim dtaSpace As New Schemas.myDBLocalTableAdapters.RG_SpaceTableAdapter
    Dim dtaMake As New Schemas.myDBLocalTableAdapters.RL_MakeGenerationProfileTableAdapter

    dtaLot.Fill(mdsRd.RL_Lot)
    dtaRow.Fill(mdsRd.RL_Row)
    dtaSpace.Fill(mdsRd.RG_Space)
    dtaMakeGenProf.Fill(mdsRd.RL_MakeGenerationProfile)
End Sub

Private Sub PrepAndLaunchForm(ByVal frmToLaunch As FormBase, ByVal Hiden As Boolean, ByVal pArr() As Object)
    frmToLaunch.Enabled = False
    If frmToLaunch.Contoller Is Nothing Then
        frmToLaunch.Parent = Me
        frmToLaunch.Contoller = Controller
        frmToLaunch.Clear()
        frmToLaunch.InputParam = pArr
        frmToLaunch.myDSstage.Merge(myDSref) 'THIS IS THE OFFENDING LINE
        AddHandler frmToLaunch.OnClosingForm, AddressOf scr_OnClosing
    Else
        frmToLaunch.Parent = Me
        frmToLaunch.Clear()
        frmToLaunch.InputParam = pArr
    End If
    frmToLaunch.Dock = DockStyle.Fill
    If Not Hiden Then
        frmToLaunch.Show()
        frmToLaunch.OnDisplayForm(Hiden)
    Else
        frmToLaunch.Show()
        frmToLaunch.OnDisplayForm(Hiden)
        frmToLaunch.Hide()
    End If
    frmToLaunch.Enabled = True
End Sub

PrepAndLaunchForm is called from a loop that passes in each form

pseudo code
For 1 to 6

    PrepAndLaunchForm(frmToLoad, Hiden, pArr)

End for loop

Thanks
>Yes it is the same for every form:
Hence its a candidate for moving to a common place and be accessed by every form. Now there are two options

1) The code needs to be executed only once so the main form can execute it and all other forms can then access the same objects which would reduce your processing and memory requirements.
2) Each form needs to execute the code at start up to make sure its accessing the most up to date data etc in which case you can still move the code to module and make it more maintainable but this wont reduce the memory and processing requirements.
I agree and I would have to go with option 1 for the app is useless as it is now, crashing after loading the 6th form.

Though I am still not sure which code to extract to a module and how to associate that 'global' back to each form. Can you give me an example, using the code above, or at least pseudo code as what to extract and how you would reassociate it back to each form?

Thanks so much
Ok .Here is a general example

Public Module Module1
 Public MyDS As New DataSet
End Module


Main Form Load:
Dim dbadp As New SQLDataAdapter("Select * from ...", "connection string")
dbadp.Fill(MyDS)
dbadp.Dispose


Form1:
DataGridView1.DataSource = MyDS

Form2:
DataGridView2.DataSource = MyDS

...
OK kind of get the idea but from my code, cut and paste, where they are doing:
Private Sub LoadRefData(ByVal mdsRd As Schemas.myDBLocal)
    Dim dtaLot As New Schemas.myDBLocalTableAdapters.RL_LotTableAdapter
    Dim dtaRow As New Schemas.myDBLocalTableAdapters.RL_RowTableAdapter
    Dim dtaSpace As New Schemas.myDBLocalTableAdapters.RG_SpaceTableAdapter
    Dim dtaMake As New Schemas.myDBLocalTableAdapters.RL_MakeGenerationProfileTableAdapter

    dtaLot.Fill(mdsRd.RL_Lot)
    dtaRow.Fill(mdsRd.RL_Row)
    dtaSpace.Fill(mdsRd.RG_Space)
    dtaMakeGenProf.Fill(mdsRd.RL_MakeGenerationProfile)
End Sub

Passing in 'myDSref' then doing a merge with 'myDSstage' as in the line:
" frmToLaunch.myDSstage.Merge(myDSref)" what is going on here? How would I accomplish the same thing with the global? Just do the merge in "Main Form Load:" portion of your general example?

Thanks
Where is that code from? And where is the merge in that code?
All the code I have posted is from the same project that I have been talking about from the beginning.

Everything I am talking about is the same code. If you look above in the area where I pasted the large amount of code you will see both this method 'LoadRefData' and the call to merge in the 'PrepAndLaunchForm' and launch method.

When you open this question do you not see the history? I seem to keep pasting the same code over and over again.

Thanks
ASKER CERTIFIED SOLUTION
Avatar of Nasir Razzaq
Nasir Razzaq
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Sounds like a plan. I'll make the changes and let you know how it goes.
Thanks