Multi-Hierarchy IDisposable Implementation for DbContext in C#

c# entity-framework entity-framework-6

Accepted Answer

The class below is one to look at if you're looking for a general disposable abstract class, but as @Matthew and @D Stanley pointed out, the repository should always initialize the context.

public abstract class DisposableObject : IDisposable
{
    private bool _disposed = false;

    public virtual bool IsDisposed
    {
        get { return _disposed; }
    }

    protected void CheckDisposed()
    {
        if (IsDisposed)
        {
            throw new ObjectDisposedException(this.GetType().FullName);
        }
    }

    protected void CheckDisposed(string err)
    {
        if (IsDisposed)
        {
            throw new ObjectDisposedException(this.GetType().FullName, err);
        }
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            OnDispose(disposing);
        }
        _disposed = true;
    }

    protected abstract void OnDispose(bool disposing); // this for the implementor to dispose their items

    ~DisposableObject()
    {
        Dispose(false);
    }

}

It will look like this for your repository pattern implementation:

public abstract class Repository<T> : IDisposable where T : DbContext
{
    private bool _disposed;
    private T _context;
    public Repository(T context)
    {
        _context = context;
    }

    protected T Context { get { return _context; } }

    public void SetSomething()
    {
        //...Access the database and set something for tracing
        // _context.Database.SqlQuery(....);
    }

    public void UnSetSomething()
    {
        //...Access the database and cancel something for tracing
        //_context.Database.SqlQuery(....);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (_context != null)
            {
                _context.Dispose();
                _context = null;
            }

            OnDispose(disposing);
        }
        _disposed = true;
    }

    // this for the implementor to dispose their items but not the context because it's already disposed from the base class
    protected abstract void OnDispose(bool disposing); 

    ~Repository()
    {
        Dispose(false);
    }
}

So, set up your Schedule Repository in that manner.

public class ScheduleRepository : Repository<AppContext>
{

    public ScheduleRepository()
        :base(new AppContext())
    {

    }
    public Schedule GetById(int id) { 
        this.Context.Schedules. (....) // blah blah
    }

    protected override void OnDispose(bool disposing)
    {
        // if you are working with any thing that you must free it up
        // do it here, but not the context
    }
}

Edit::::

That is how your logic class will seem.

public class ScheduleFacade
{
    private ScheduleRepository _repository;
    public ScheduleFacade()
    {
        _repository = new ScheduleRepository();
    }

    public ScheduleSetting GetScheduleById(string scheduleId)
    {
        if (!string.IsNullOrEmpty(scheduleId))
        {
            _repository.SetSomething();

            ScheduleSetting settings = _repository.GetScheduleById(scheduleId);

            _repository.UnSetSomething();

            return LoadScheduleSettings(settings);
        }
        else
        {
            throw new ArgumentException("The scheduleId parameter cannot be empty.");
        }
    }

    private ScheduleSetting LoadScheduleSettings(ScheduleSetting settings)
    {
        //...code ....
    }
}

thus EF won't be necessary

0
4/10/2015 8:20:23 PM


Related Questions





Related

Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow
Licensed under: CC-BY-SA with attribution
Not affiliated with Stack Overflow