0

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.

Ram Koti
  • 2,203
  • 7
  • 26
  • 36
Tony
  • 89
  • 1
  • 12
  • Wrap your `using` around the `DbContext` constructor with a `try` / `catch`. – Bradley Uffner Jun 21 '18 at 10:56
  • Can you post the crash stacktrace? Because when using MVVM the crash should not happen in the View, but in the ViewModel or Model. – Sentry Jun 21 '18 at 11:11
  • So you catch the exception.... and immediately throw it again. Suggests your real problem is that you don't know much about C#. You should stop, go grab a copy of CLR Via C# and read it. Take a day to do it. You'll come back 1000x better off than you are right now. And you won't feel like you're stumbling around all the time instead of programming. –  Jun 21 '18 at 12:56
  • Thanks Sentry, Taking a closer look at the stack trace was actually the answer. I have a static table which is loaded from DB. This was naturally done before MyList was loaded. So I was trying to catch the exception in the wrong place all the time. – Tony Jun 21 '18 at 16:10

2 Answers2

0

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

Bradley Uffner
  • 16,641
  • 3
  • 39
  • 76
  • Thanks for the reply, much appreciated - I like the concept and it works nicely in LINQPad. I tried to implement in WPF context around the Intialisation of MyListRepo, where data is loaded with LoadData function etc with little success. I still get crash on InitializeComponent if DB is paused. – Tony Jun 21 '18 at 15:21
0

The root cause of my problem was that I had broken the encapsulation principal. I thought I would be cleaver and put a table which is frequently referenced in a list in a static class referenced by the view. This is why the exception was being thrown "outside" the ViewModel - I know beginner mistake. After I fixed that the using around the DbContext worked perfectly.

Thanks for all the advice

Tony
  • 89
  • 1
  • 12