Push Entity Framework exceptions to business layer I am trying to write an exception handler/parser, which I want to return from DAL to the business layer. I am writing below class because I don't want my business layer to know if I am using EF under my DAL.

Please suggest if below code adhere to SOLID principles?

using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using System.Data.Entity.Validation;

namespace WebAPis
{
    public enum ExceptionType
    {
        Unknown,
        EntityModified,
        EntityValidation,
        EntityUpdateException

    }
    public class EfResponse
    {
        private Exception Exception { get; set; }
        public void ParseException(Exception ex)
        {
            this.Exception = ex;
        }
        public bool IsSuccess { get { return this.Exception == null; } }
        public int RowsModified { get; set; }
        public ExceptionType Type
        {
            get
            {
                var type = ExceptionType.Unknown;

                if (this.Exception is DbEntityValidationException)
                    return ExceptionType.EntityValidation;

                if (this.Exception is DbUpdateException)
                    return ExceptionType.EntityUpdateException;

                if (this.Exception is DbUpdateConcurrencyException)
                    return ExceptionType.EntityModified;
                // add more types here
                return type;
            }
        }

        public DbUpdateExceptionDetail GetDbUpdateExceptionDetail
        {
            get
            {
                if (this.Type != ExceptionType.EntityUpdateException)
                    throw new Exception("Invaid exception details invoked");

                var toReturn = new DbUpdateExceptionDetail()
                {
                    // Parse exception here
                    ColumnName = "test column name"
                };
                return toReturn;

            }
        }
        public ConcurrencyExceptionDetail GetConcurrencyExceptionDetail
        {
            get
            {
                if (this.Type != ExceptionType.EntityModified)
                    throw new Exception("Invaid exception details invoked");

                var toReturn = new ConcurrencyExceptionDetail()
                {
                    // Parse exception here
                    MyProperty = "test property name"
                };
                return toReturn;
            }
        }
    }

    // Exception models
    public abstract class ExceptionDetail
    {
        public List&lt;string&gt; Exceptions { get; set; }
    }
    public class DbUpdateExceptionDetail : ExceptionDetail
    {
        public string ColumnName { get; set; }
    }

    public class ConcurrencyExceptionDetail : ExceptionDetail
    {
        public string MyProperty { get; set; }
    }

    // example dbcontext
    public class MyDbcontext : DbContext
    {
        public EfResponse Save()
        {
            var toReturn = new EfResponse();
            try
            {
                toReturn.RowsModified = this.SaveChanges();
            }
            catch (Exception ex)
            {
                toReturn.ParseException(ex);
            }

            return toReturn;
        }
    }
}
I think this is not a good idea for the following few reasons. 

You write


  I don't want my business layer to know if I am using EF under my DAL.



and yet the ExecptionType enum contains all the values strictly related to Entity Framework.
Also the name of the EfResponse object already suggests it's Entity Framework related too with its Ef prefix.
Then the public class MyDbcontext : DbContext is derived from DbContext which agian is Entity Framework.


This means that the EfResponse and the MyDbcontext aren't abstract enough and they don't separate you from either Entity Framework or any other DAL. They just use different names for some EF types.



Other things that aren't implemented correctly are the two detail properties. We don't use the Get prefix for them. Only for methods. The way they work is also a little bit strange. I first need to check the type of the exception to know which property I'm allowed to use or otherwise it'll might throw. They should return null if there is no exception of this type. The only exception they are allowed to throw is the InvalidOperationException if a EfResponse object is in the Success state.

The property RowsModified should not be publically settable. This should be a part of the constructor.



Some time ago there was a question about something similar that you might find interesting: Refactoring away from exceptions. I think what you are trying to do is virtually the same. I tried it and it's a real mess when you once start using it. You're better off with a simple repository encapsulating all db operations an their exceptions.