wpfentity-frameworkexceptionmvvminitializecomponent

How can I catch and elegantly handle exception where database is unavailable in WPF


I am trying to catch the exception when the Database is unavailable in WPF with EF. I am using MVVM and Repo pattern with IUnityContainer in C#.

My problem is that if the database is unavailable the program crashes on InitializeComponent() statement in the code behind of the View. I have tried searching on catching Exceptions and Error Handling etc. and most of the suggestions center around Try Catch logic, which is to be expected. I have tried to wrap statement in a try-catch block as below but it still crashes in the same place on InitalizeComponent.

Public MyListView() {
    try {
        IntializeComponent();
    } catch (Exception) {
        throw;
    }    
}

I have also tried to add Try-Catch Blocks in various other points of my code such as where the DB is Initialised:

Database.SetInitializer(new DataInitialiser());

Where the Unity container is registered:

_container.RegisterType<IRepo<MyList>, MyListRepo>(new TransientLifetimeManager());

and where the data is loaded:

MyLists = new ObservableCollection<MyList>(await _repo.GetAllAsync());

I would like to preserve the MVVM pattern so catch the exception and provide an elegant response to the user from within the ViewModel. So my specific question is where can I catch the Exception when the database is unavailable.

Thanks in advance.


Solution

  • Typically the using around each DbContext would be protected by a try / catch block.

    If you want something a little more centralized, you could do something like this:

    public static class EfHelper
    {
        public static void SafeExecute<T>(Action<T> action) where T : DbContext, new()
        {
            try
            {
                using (var context = new T())
                {
                    action.Invoke(context);
                }
            }
            catch (Exception ex)
            {
                // Put your standard error handling here.
                Debug.WriteLine("There was an error");
            }
        }
    }
    

    Usage:

    void Main()
    {
        EfHelper.SafeExecute<TestContext>(context =>
        {
            context.DoSomething();
        });
    }
    

    You would probably want to expand this a bit to allow the caller to know if the operation succeeded or failed. You could do that by returning a bool, or propagating the exception if another flag is set, etc.

    If you have LINQPad installed, you can see a simple demo here: http://share.linqpad.net/4x2g36.linq