I get the following error when I want to iterate over a List
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
I open the Form with the following code
private void dataGridView1_CellDoubleClick(object sender, DataGridViewCellEventArgs e)
{
int id = int.Parse(dataGridView1.Rows[e.RowIndex].Cells[0].Value.ToString());
Aufenthalt a;
using (var db = new GastContext())
{
a = db.Aufenthalte.First(x => x.AufenthaltID == id);
}
Aufenthaltsform frm = new Aufenthaltsform(currentGast, a);
frm.ShowDialog();
}
And this is the constructor of my form and here my Application throws the above error
public Aufenthaltsform(Gast g, Aufenthalt a)
{
InitializeComponent();
MessageBox.Show(a.Mitreisende.Count.ToString());
}
That's the Aufenthalt-Object
public class Aufenthalt
{
public int AufenthaltID { get; set; }
public DateTime Anreisedatum { get; set; }
public DateTime Abreisedatum { get; set; }
public virtual List<Mitreisender> Mitreisende { get; set; }
public virtual Gast Gast { get; set; }
public Aufenthalt()
{
Mitreisende = new List<Mitreisender>();
}
}
Your Aufenthalt
has two navigation properties - Mitreisende
and Gast
. Which require non-disposed DbContext
when you are using lazy-loading. That's why you have error when try read those properties after disposing context via using
statement:
Aufenthalt a;
using (var db = new GastContext())
{
a = db.Aufenthalte.First(x => x.AufenthaltID == id);
}
// db is disposed here
Aufenthaltsform frm = new Aufenthaltsform(currentGast, a);
You can:
using
statement to keep context alive using
statement First option - DbContext
is a lightweight object, it's ok not to dispose it.
var db = new GastContext();
Aufenthalt a = db.Aufenthalte.First(x => x.AufenthaltID == id);
Aufenthaltsform frm = new Aufenthaltsform(currentGast, a);
Second option - not very good option, because you only need count of related entities. Why loading them all into memory? But you can
Aufenthalt a;
using (var db = new GastContext())
{
a = db.Aufenthalte.Include(x => x.Mitreisende).First(x => x.AufenthaltID == id);
}
Aufenthaltsform frm = new Aufenthaltsform(currentGast, a);
Third option is obvious
using (var db = new GastContext())
{
Aufenthalt a = db.Aufenthalte.First(x => x.AufenthaltID == id);
Aufenthaltsform frm = new Aufenthaltsform(currentGast, a);
frm.ShowDialog();
}
And best option is not passing to form data which are not required. It needs only count of Mitreisende, not whole collection. So change your form to
public Aufenthaltsform(Gast g, int mitreisendeCount)
{
InitializeComponent();
MessageBox.Show(mitreisendeCount.ToString());
}
And call it this way
int mitreisendeCount;
using (var db = new GastContext())
{
mitreisendeCount = db.Aufenthalte.First(x => x.AufenthaltID == id).Mitreisende.Count;
}
Aufenthaltsform frm = new Aufenthaltsform(currentGast, mitreisendeCount );
You should ensure that the query is executed before the context is disposed:
a = db.Aufenthalte.First(x => x.AufenthaltID == id);
// place this within the disposable context (using)
int count = a.Mitreisende.Count;
The object a
itself is filled after loading, but it has a navigation property Mitreisende
that has not been filled yet at that moment (and Entity Framework also remembers that it has not done so yet).
The moment you call a.Mitreisende.Count
, Entity Framework tries to fill the Mitreisende property, but it can not do so because the using
statement caused the DbContext to be disposed, leading to the error.
There are multiple fixes:
1) Don't dispose the DbContext, simply by removing the using
block. .NET will remove it by itself a little later, which in many cases will not hurt.
2) Dispose the DbContext by yourself, but do it a little later by putting the next 2 lines inside the block, instead of after it.
3) Make sure that Entity Framework loads the Mitreisende
as soon as possible instead of delaying it, using an .Include
statement:
a = db.Aufenthalte.Include(x => x.Mitreisende).First(x => x.AufenthaltID == id);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.