C#Entity Framework ObjectContext实例已被释放

时间:2017-02-01 15:41:15

标签: c# entity-framework

当我想迭代List

时,我收到以下错误
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-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>();
        }
    }

3 个答案:

答案 0 :(得分:2)

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

答案 1 :(得分:0)

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

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

答案 2 :(得分:0)

对象a本身在加载后填充,但它具有当时尚未填充的导航属性Mitreisende(并且实体框架还记得它还没有这样做)

当您调用a.Mitreisende.Count时,实体框架会尝试填充Mitreisende属性,但它无法执行此操作,因为using语句导致DbContext被释放,从而导致错误。

有多种修复方法:

1)只需删除using块,就不要丢弃DbContext。 .NET会稍后将其删除,这在很多情况下不会受到伤害。

2)自己处理DbContext,但稍后通过将下两行放在块内,而不是在它之后再进行操作。

3)确保实体框架尽快加载Mitreisende,而不是使用.Include语句延迟a = db.Aufenthalte.Include(x => x.Mitreisende).First(x => x.AufenthaltID == id);

    var HelloWorld = function () {

    }

    HelloWorld.hello2 = function () {
      console.log("hello2");
    }

    HelloWorld.prototype.hello1 = function () {
      console.log("hello1");
    }

    // Only this part changed
    module.exports.HelloWorld = HelloWorld;