I am in the process of migrating a legacy binary file format. Part of this involves converting objects to a byte array. But after a while I run into an OutOfMemoryException
. I created a small sample program to demonstrate the problem. You can download it here.
for (int i = 0; i < 20; i++)
{
Training training = service.GetNewTraining();
training.Name = Guid.NewGuid().ToString();
for (int j = 0; j < 10; j++)
{
Run run = service.GetNewRun();
run.Created = DateTime.Now;
run.Distance = GetRandom(10000, 40000); // Random between 10k and 40k.
TimeSpan time = TimeSpan.FromHours((run.Distance / 1000) / 25.0);
for (int k = 0; k < time.TotalSeconds; k++)
{
RunDataSample sample = new RunDataSample
{
Cadence = GetRandom(60, 110),
Distance = (float)(time.TotalHours * 25),
Time = TimeSpan.FromSeconds(k),
HeartBeat = GetRandom(80, 180),
Speed = 25,
Power = GetRandom(200, 400)
};
run.RunSamples.Add(sample);
}
training.Runs.Add(run);
}
service.Save();
}
I once tried adding a GC.Collect()
call after the service.Save()
call, but that didn't help either.
I have no need for the objects to be in the memory after I saved them. How can I clean them up properly?
In the included sample I am using an in-memory database, but in my real application I am using an SqlCe database with an x86 build.
asked
May 11 '11 at 09:43
jensen
39●9●9●13
Hello jensen, I'll check this.
I want to mention I am going to make a change to the data model as used in the sample application. I do not need the entire collection of samples each time, so I will only initialize the exposed collection when it's first accessed. When switching screens the object is not required, so it should be disposed and I will re-get it from the database when required. Since I collect 25 samples which I basically need on 1 single screen a user will almost never access there's no point in initializing them with the OnInitialize override.
But that won't solve the import OOME I'm having now.
I did some test with manually creating the session, open the session, open the transaction each time and that worked perfectly. I timed it and I get about 2 minutes to complete the operation. When using auto activation it takes about 5 minutes before the exception is thrown.
Now, I really would like to use the auto activation, because it would be a real pain if I need to manually manage the session each time. In a WPF app this is really difficult.
Something else that's bothering me. According to the documentation of Session.Persisting it will be called "when Session is about to SaveChanges() changes.". And SaveChanges() tells me I need to call it manually, which I do.
But the persisting event is thrown each and every time something in the object changes, even if it's not a property that has to persist. (In this case the collection.) How can I work around that?
I tried setting the collection to null after each Run was saved, and that helped a bit. No more OOME, but I still have the idea that the entire entity "hangs" on the Session, which is not needed. But I don't want to do that every time I use an object. If it's not in use anymore (when I switch screens) it should get disposed automatically.
I am also convinced the documentation of SaveChanges is wrong. If I use the DisconnectedState option, the Persisting event is still called every time a [Field] changes.
jensen,
sorry for the delay, I'll try investigating the issue tomorrow. Thanks for your patience.
I have a similar problem. Any ETA on this?