如果数据库连接在实例化DbContext资源的using语句中失败,我该如何自动抛出ApplicationException?

时间:2016-08-04 16:57:29

标签: c# asp.net entity-framework exception-handling using

编辑,先阅读:不是使用我的ApplicationException的using语句,它是我在实际代码中使用的DependencyResolver。我一开始并没想过要看那里,但果然,如果我尝试直接实例化这个类(就像我在下面简化的示例代码中所做的那样),它按预期工作。如果我在using语句中使用DependencyResolver,它只会按照我在下面记录的方式运行。我根本没想到在我的问题中提到这一点,因为我忽略了它。我使用的是Unity容器,仅供参考。我会通过它来更新它,并且可能会删除它。

更新2:确定结果是,当服务位置抛出异常时返回空资源是MVC中完全正常且预期的行为。当我第一次遇到这种行为并迷惑自己时,我完全不知道我正在使用依赖注入这一事实。因此,我会留下这个问题,万一其他人发现自己处于类似情况。在创建使用DependencyResolver服务定位器解析的资源时,您不能抛出异常!它会吞下异常并返回一个空资源!

如果有人想知道我根据这些新信息改变了什么:我只是将数据库检查/异常抛出逻辑放在存储库中的几个关键方法中,而不是在构造函数中。我也停止使用Unity并切换到Ninject,并从服务定位器模式转到将我的容器包装在单例类中,但这与我遇到的导致此线程的问题无关,而且更像是一种风格选择。

结束修改

所以我想说我有一些访问数据库的类,比如这个......

public class Foo : IDisposable {

    private DbContext db = new FooDbContext();

    public DoSomething(){
        // do something with the FooDbContext...
    }

    // Dispose is implemented here as well...

}

当我去使用那个课程时,我会像这样访问它......

using (Foo foo = new Foo()){
    foo.DoSomething();
}

所以我想要完成的是,每当构造一个Foo类时,如果底层DbContext无法建立连接,则抛出ApplicationException。

所以我将以下构造函数添加到Foo类...

public Foo() {
    try
        {
            db.Database.Connection.Open();
        }
        catch
        {
            throw new ApplicationException("Database is not currently available. Try again later.");
        }
}

但问题出现了,回到这段代码......

using (Foo foo = new Foo()){
    foo.DoSomething();
}

当数据库不可用时执行using语句(并且我已经通过调试确认了这一点),在构造Foo时抛出ApplicationException ,但是忽略了ApplicationException,并且无论如何都要调用DoSomething方法。那时,我得到的是NullReferenceException而不是我想要的ApplicationException,因为foo为null。

我的ApplicationException发生了什么变化?为什么被忽略?我该怎么做才能确保ApplicationException冒泡?

我实际上并不想处理ApplicationException。对于某些上下文,这是一个ASP.NET MVC应用程序。我希望ApplicationException不被处理,并让我设置的自定义错误页面向用户显示ApplicationException中包含的消息。

1 个答案:

答案 0 :(得分:1)

我认为你的问题没有进入db和连接细节是因为使用了block,使用块吞下了构造函数中发生的异常。

http://www.digitallycreated.net/Blog/51/c%23-using-blocks-can-swallow-exceptions

https://msdn.microsoft.com/en-us/library/aa355056.aspx