繁体   English   中英

C#实体框架ObjectContext实例已被处置

[英]C# Entity Framework ObjectContext instance has been disposed

当我要遍历列表时收到以下错误

The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.

我用以下代码打开表单

        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();
        }

这是我窗体的构造函数,在这里我的应用程序抛出上述错误

    public Aufenthaltsform(Gast g, Aufenthalt a)
    {
        InitializeComponent();

        MessageBox.Show(a.Mitreisende.Count.ToString());
    }

那是Aufenthalt对象

    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>();
        }
    }

您的Aufenthalt具有两个导航属性MitreisendeGast 在使用延迟加载时,需要非处置DbContext 这就是为什么在通过using语句处理上下文之后尝试读取这些属性时出错的原因:

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);

您可以:

  • 删除using语句以使上下文保持活动状态
  • 使用紧急加载而不是延迟加载
  • using语句中移动表单创建和替换
  • 获取Mitreisende计数并将编号传递给表单,而不是传递根对象并稍后使用导航属性

第一种选择DbContext是一个轻量级的对象,可以将其丢弃。

var db = new GastContext();
Aufenthalt a = db.Aufenthalte.First(x => x.AufenthaltID == id);
Aufenthaltsform frm = new Aufenthaltsform(currentGast, a);

第二种选择-不是很好的选择,因为您只需要计算相关实体即可。 为什么将它们全部加载到内存中? 但是你可以

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);   

第三种选择很明显

using (var db = new GastContext())
{
    Aufenthalt a = db.Aufenthalte.First(x => x.AufenthaltID == id);
    Aufenthaltsform frm = new Aufenthaltsform(currentGast, a);
    frm.ShowDialog();
}

最好的选择是不传递不需要的表单数据。 它只需要Mitreisende的数量,而不需要整个收藏。 因此,将您的表格更改为

public Aufenthaltsform(Gast g, int mitreisendeCount)
{
    InitializeComponent();
    MessageBox.Show(mitreisendeCount.ToString());
}

并这样称呼它

int mitreisendeCount;
using (var db = new GastContext())
{
    mitreisendeCount = db.Aufenthalte.First(x => x.AufenthaltID == id).Mitreisende.Count;
}

Aufenthaltsform frm = new Aufenthaltsform(currentGast, mitreisendeCount );

您应该确保在处理上下文之前执行查询:

a = db.Aufenthalte.First(x => x.AufenthaltID == id);
// place this within the disposable context (using)
int count = a.Mitreisende.Count;

对象a本身加载后填,但它有一个导航属性Mitreisende尚未在那一刻又充满(和Entity Framework还记得,它没有这样做还)。

当您调用a.Mitreisende.Count ,实体框架会尝试填充Mitreisende属性,但是它不能这样做,因为using语句导致DbContext被处置,从而导致错误。

有多个修复程序:

1)不要通过删除using块来处理DbContext。 .NET稍后会自行删除它,这在很多情况下不会受到伤害。

2)自己处理DbContext,但稍后再将其后两行放在该块内,而不是放在其后,再进行处理。

3)使用.Include语句,确保Entity Framework尽快加载Mitreisende ,而不是延迟加载它:

a = db.Aufenthalte.Include(x => x.Mitreisende).First(x => x.AufenthaltID == id);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM