Workflow:
I have a winform app with two forms, in the 1st form I query a liteDB
and it manipulates an IEnumerable<T>
instance inside a using
block with retrieved data.
IEnumerable<student> searchResult;
using(var db = new LiteDatabase(@"C:\Temp\MyData.db"))
{
var col = db.GetCollection<student>("students");
col.EnsureIndex(x => x.contact.phone);
searchResult = col.Find(x => x.contact.phone == "123456789");
}
Form2 frm2 = new Form2();
Form2.profileData = searchResult.AtElement(index);
Problem:
I then, need to send an element of searchResult<student>
to 2nd form in order to show user, as you can see in the last 2 lines of above code.
But since it's inside using
block, I get System.ObjectDisposedException
.
Data types and exception:
studentCollection.Find()
:
searchResult
:
Exception:
Addition:
What I already though of as possible way is:
Override and nullify existing dispose()
method then call my own implemented method after I'm done; Which is basically equals to not having a using
block, except that I don't have to take care of disposing other objects in above using
block, but only searchResult<student>
.
P.S: I'm newbie at whole thing, appreciate the help and explanation
CodePudding user response:
You need to access the element before exiting the using block.
using(var db = new LiteDatabase(@"C:\Temp\MyData.db"))
{
var col = db.GetCollection<student>("students");
col.EnsureIndex(x => x.contact.phone);
var searchResult = col.Find(x => x.contact.phone == "123456789");
Form2 frm2 = new Form2();
Form2.profileData = searchResult.AtElement(index);
}
CodePudding user response:
I'm not familliar with LiteDb, but I would assume it returns a proxy object for the database. So when the database is disposed, the proxy-object is no longer usable.
The simple method to avoid the problem is to add .ToList()
after the .Find(...)
. This will convert the proxy-list to an actual List<T>
in memory, and it can be used after the database is disposed. It is possible that the student
objects inside the list are also proxies, and if that is the case this will fail.
If that is the case you either need to find some way to make the database return real, non-proxy objects, or extend the lifetime of the database to be longer than that of your form, for example
IList<student> myIList;
using(var db = new LiteDatabase(@"C:\Temp\MyData.db"))
{
var col = db.GetCollection<student>("students");
col.EnsureIndex(x => x.contact.phone);
myIList = col.Find(x => x.contact.phone == "123456789");
using(var frm2 = new Form2()){
frm2.profileData = myIList.AtElement(index);
frm2.ShowDialog(this);
}
}
Note the usage of .ShowDialog
, this will block until the second form has been closed. That is not strictly necessary, but it makes it much easier to manage the lifetime of the database.