本文介绍了我应该把实体框架作为一个非托管资源?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我与使用在其构造为EF引用的类工作。

I am working with a class that uses a reference to EF in its constructor.

我已实施的IDisposable ,但我不知道我是否需要析构函数,因为我不能确定我可以归类为EF非托管资源。

I have implemented IDisposable, but I'm not sure if I need a destructor because I'm not certain I can classify EF as an unmanaged resource.

如果EF是一个管理的资源,那么我不需要析构函数,所以我认为这是一个适当的例子:

If EF is a managed resource, then I don't need a destructor, so I think this is a proper example:

public ExampleClass : IDisposable
{
    public ExampleClass(string connectionStringName, ILogger log)
    {
        //...
        Db = new Entities(connectionStringName);
    }

    private bool _isDisposed;

    public void Dispose()
    {
        if (_isDisposed) return;

        Db.Dispose();

        _isDisposed= true;
    }
}

如果EF未被托管,然后我会一起去这样的:

If EF is unmanaged, then I'll go with this:

public ExampleClass : IDisposable
{
    public ExampleClass(string connectionStringName, ILogger log)
    {
        //...
        Db = new Entities(connectionStringName);
    }

    public void Dispose()
    {
        Dispose(true);
    }

    ~ExampleClass()
    {
        Dispose(false);
    }

    private bool _isDisposed;

    protected virtual void Dispose(bool disposing)
    {
        if (_isDisposed) return;

        // Dispose of managed resources
        if (disposing)
        {
            // Dispose of managed resources; assumption here that EF is unmanaged.
        }
        // Dispose of unmanaged resources
        Db.Dispose();

        _isDisposed = true;
        //freed, so no destructor necessary.
        GC.SuppressFinalize(this);

    }
}



哪一个呢?

Which one is it?

推荐答案

您绝不会想使用在这种情况下终结(析构函数)。

You would never want to use a finalizer (destructor) in this case.

无论的DbContext 包含非托管资源或没有,甚至它是否负责任地释放这些非托管资源与否,是不是与您无关,是否可以尝试调用 DbContext.Dispose()从终结。

Whether DbContext contains unmanaged resources or not, and even whether it responsibly frees those unmanaged resources or not, is not relevant to whether you can try to invoke DbContext.Dispose() from a finalizer.

事实是,你有一个管理对象(其中的一个实例任何时候的DbContext 是),它的从不安全试图调用该实例上的任何方法。其原因是,由当时的终结器被调用时,的DbContext 对象可能已经被GC回收并不再存在。如果发生这种情况,你会得到一个的NullReferenceException试图打电话的时候, Db.Dispose()。或者,如果你是幸运的,而分贝仍是活着,异常也可以从在 DbContext.Dispose()抛出如果方法有上,至今已完成,并收集其他对象的依赖

The fact is that, any time you have a managed object (which an instance of DbContext is), it is never safe to attempt to invoke any method on that instance. The reason is that, by the time the finalizer is invoked, the DbContext object may have already been GC-collected and no longer exist. If that were to happen, you would get a NullReferenceException when attempting to call Db.Dispose(). Or, if you're lucky, and Db is still "alive", the exception can also be thrown from within the DbContext.Dispose() method if it has dependencies on other objects that have since been finalized and collected.

由于此的:

x无关访问的终结代码路径的终结对象,因为有显著风险,他们将已经敲定。

例如,有另一个终结对象b的引用不能可靠地使用A的终结b,反之亦然终结对象的。终结被称为随机顺序(简称关键终止弱排序担保)。

For example, a finalizable object A that has a reference to another finalizable object B cannot reliably use B in A’s finalizer, or vice versa. Finalizers are called in a random order (short of a weak ordering guarantee for critical finalization).

另外,还要注意从埃里克利珀的下面:

Also, note the following from Eric Lippert's When everything you know is wrong, part two:

误区二:终结运行在可预知的顺序

假设我们有对象的树,所有的终结,和所有的终结队列中。 。不要求任何该树从根到叶敲定,从叶到根,或任何其他命令

Suppose we have a tree of objects, all finalizable, and all on the finalizer queue. There is no requirement whatsoever that the tree be finalized from the root to the leaves, from the leaves to the root, or any other order.

神话:一个对象正在确定可以安全地访问另一个对象。

这个神话直接从以前的遵循。如果你有对象的树,你正在最后确定的根,那么孩子还活着 - 因为根本是活的,因为它是终结队列,所以孩子们有一个生活参考 - 但孩子们可能已经已经定稿,并在没有特别好的状态,有自己的方法或访问的数据。

This myth follows directly from the previous. If you have a tree of objects and you are finalizing the root, then the children are still alive — because the root is alive, because it is on the finalization queue, and so the children have a living reference — but the children may have already been finalized, and are in no particularly good state to have their methods or data accessed.

别的东西来考虑:你有什么处置?是您的关心确保数据库连接及时关闭?如果是这样,那么你会感兴趣的是什么有。

You can read more about this unfortunate situation here.

要确保的DbContext 的Dispose()方法总是被调用,不管里面有什么发生在 ExampleClass中的构造函数,你将不得不修改 ExampleClass中类是这样的:

To ensure that the DbContext's Dispose() method is always invoked, no matter what happens inside the ExampleClass constructor, you would have to modify the ExampleClass class to something like this:

public ExampleClass : IDisposable
{
    public ExampleClass(string connectionStringName, ILogger log)
    {
        bool ok = false;
        try
        {
            //...
            Db = new Entities(connectionStringName);

            // let's pretend I have some code that can throw an exception here.
            throw new Exception("something went wrong AFTER constructing Db");

            ok = true;
        }
        finally
        {
            if (!ok)
            {
                if (Db != null)
                {
                    Db.Dispose();
                }
            }
        }
    }

    private bool _isDisposed;

    public void Dispose()
    {
        if (_isDisposed) return;

        Db.Dispose();

        _isDisposed= true;
    }
}



不过上面是真的只有在构造一个问题不仅仅是创建一个的DbContext

这篇关于我应该把实体框架作为一个非托管资源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 09:33
查看更多