Reputation: 129
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.
Upvotes: 0
Views: 705
Reputation: 129
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
Upvotes: 0
Reputation: 16991
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
Upvotes: 0