【问题标题】:What is the proper way to Dispose of my ObjectContext?处置我的 ObjectContext 的正确方法是什么?
【发布时间】:2013-06-27 13:59:18
【问题描述】:

我不太确定Dispose 我的ObjectContext 的正确方法是什么。这是我的设置方式:

public abstract class DataManagerBase<T> where T:ObjectContext
{
    protected T _context = null;

    public string Message { get; set; }

    public DataManagerBase(T context)
    {
       _context = context;
    }
}

要在其他课程中使用它,我正在做类似的事情:

public class Test : DataManagerBase<DataEntities>
{
     public Test(DataEntities context) 
        : base(context){}

     public void InsertRecord(Person p)
     {
         if(_context != null)
         {
             try
             {
                 //Do insert logic
             }
             catch(Exception ex)
             {

             }
         }
    }

}

我有其他方法使用相同的_context,所以我没有使用using 语句,所以如果抛出异常,我是否应该检查_context 是否不为空然后处理它?基本上我想确保 _context 在我完成后被处理,无论是否有异常。将finally 添加到每个try/catch 会不正确吗?

将此方法添加到我的 DataManagerBase 类中,然后在其他类中调用它就可以了:

 public void DisposeContext()
 {
        if (_context != null)
        {
            _context.Dispose();
        }
 }

【问题讨论】:

  • 你调用 base 的东西不是继承自任何东西?
  • 作为一个快速而肮脏的解决方案,是的,在您的 finally 语句中添加一个空检查和 dispose() 方法就可以了。更理想的解决方案是将所有调用封装在 using 块中以供您使用。
  • @MystereMan - 抱歉已修复。忘记添加了。
  • @BradM - 我听说过 using 语句,不幸的是它不是那样做的,所以现在我必须确保它是关闭的,所以我想如果它不是过度杀戮,我一切都可以结束了吗?
  • @BradM - 在 finally 中的每个方法末尾调用 dispose 将意味着您将无法在该对象的同一实例上调用其他方法。

标签: c# asp.net-mvc-3 entity-framework .net-3.5 datacontext


【解决方案1】:

经验法则是:不要处置不是您创建的对象。所以你不应该在你一开始就提供的任何类中处理你的上下文。

但是,您应该在课堂上调用context.Dispose(),您实际上是在其中创建此特定实例。当你这样做时 - 不应该有其他对象使用它。您要做的是避免您遇到的设计问题,而不是修复它。那是错误的,恕我直言。当你忘记在某处放置另一个空检查时,这会在某个时候咬你。

使用您提供的代码,示例可能如下所示:

void SomeMethodInOuterScope()
{
    var context = new DataEntities();

    var test = new Test(context);

    try
    {
        test.InsertRecord(new Person());
        ...............
    }
    catch(Exception ex)
    {
        ....
    }
    finally
    {
        context.Dispose();
    }
}

这是另一个例子(当上下文不是本地时)

class SomeClassInOuterScope : IDisposable
{
    private DataEntities _context;

    public SomeClassInOuterScope()
    {
        _context = new DataEntities();
    }

    public void Test()
    {
        var test = new Test(_context);
        test.InsertRecord(new Person());
        ...............
    }

    public void Dispose()
    {
        _context.Dispose();
    }
}

void SomeMethodInOuterOuterScope()
{
    var someclass = new SomeClassInOuterScope();

    try
    {
        someclass.Test();
        ...............
    }
    catch(Exception ex)
    {
        ....
    }
    finally
    {
        someclass.Dispose();
    }
}

【讨论】:

  • 你有我在DataManagerBase 类中如何使用using 的例子吗?我还在DataManagerBase 的帖子中添加了一个方法,但不确定这是否正确?
  • @Xaisoft 再次,您应该在创建此实例的 smae 类中处理您的上下文。您没有在 DataManagerBase 中创建上下文(您只需将现有实例传递给构造函数),因此您不应该将它放置在那里。在你调用new DataEntities()的同一类中调用Dispose()
  • 好的,如果我错了,请纠正我,在我的一个控制器中,我在构造函数中执行DataEntities _context = new DataEntities(),但你说的是不是这个,我应该把它放在一个using 语句在我使用的任何地方,例如在 InsertRecords 方法中。
  • Afaik,创建上下文非常便宜。但它保留了您使用的缓存实体。除非您需要它们进行一些后续操作以更好地快速杀死上下文。
  • @Nik - 谢谢,这就是我的想法,所以在finally 中的disposing 就足够了。你在catch 中没有dispose 是有原因的吗?
【解决方案2】:

最好是在一个地方创建和删除它。喜欢

using(var context = factory.CreateContext())
{
    // use your context
}

【讨论】:

  • 如果这是正确/最好的方法,是否值得在每个地方进行更新?
  • 是的,至少为了保持一致性。您将需要以某种方式创建抽象类的实现。如果抽象是强制性的,那么创建某种工厂可能是一种解决方案。
  • 我有,例如我有一些实现 DataManager 类的管理器类。
  • 那你就少了一个问题:-)
【解决方案3】:

你不能在你的抽象类上添加Dispose 方法吗?也许实现 IDisposable。

让调用代码的提供者使用using 块。

所以关于抽象类:

 public void Dispose()
 {
        if (_context != null)
        {
            _context.Dispose();
        }
 }

调用代码:

using(var db = new Test())
{
... 
}

这样做的缺点是你依赖调用代码来管理你的上下文的一次性。

【讨论】:

  • 我了解 Dispose 方法部分,但如果我在我的测试类中,我为什么要使用 (var db = new Test()?
  • 因为 Test 类上的 using 语句在离开 using 块的上下文后直接调用抽象类上的 Dispose 方法
【解决方案4】:

虽然可能需要处理上下文,但这并不是绝对必要的。垃圾收集器最终将处理它,并且实体框架使用 ado.net 连接池,因此它不会真正持有连接。

这样做不是最有效的,但它不会导致任何泄漏,除非你的类本身有泄漏。每当您的 Test 类超出范围时,上下文最终将由 gc 处理。

如果您一遍又一遍地创建大量此类对象,您真的会担心,但情况可能并非如此。

我并不是说这是一个好的做法,但如果这是某种类型的错误修复,或者是临时的事情.. 可能没有必要。

【讨论】:

  • 好吧,我在昨天遇到了 StackOverFlow 异常,我怀疑这可能与它有关 :)
  • @Xaisoft - 不。递归调用某些东西时会发生堆栈溢出。没有办法不处理对象可以做到这一点。您必须查看调用堆栈并查看一遍又一遍地调用了哪些方法。
  • 谢谢,我找到了 StackOverFlow 的原因,我有一个调用自身的方法,哈哈。谢谢。
猜你喜欢
  • 2015-02-11
  • 1970-01-01
  • 2014-09-23
  • 2010-10-08
  • 2013-07-24
  • 2011-12-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多