How to implement IDisposable inheritance in a repository? - c#

I am creating a generic repository and do not know what the correct way to implement the dispose functionality:
I'm not using IoC/DI, but i'll refactor my code in the future to do this, so:
My code:
IUnitOfWork Interface:
namespace MyApplication.Data.Interfaces
{
public interface IUnitOfWork
{
void Save();
}
}
DatabaseContext class:
namespace MyApplication.Data.Infra
{
public class DatabaseContext : DbContext, IUnitOfWork
{
public DatabaseContext(): base("SQLDatabaseConnectionString")
{
Database.SetInitializer<DatabaseContext>(null);
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
// Same code.
base.OnModelCreating(modelBuilder);
}
#region Entities mapping
public DbSet<User> User { get; set; }
// >>> A lot of tables
#endregion
public void Save()
{
base.SaveChanges();
}
}
}
IGenericRepository interface:
namespace MyApplication.Data.Interfaces
{
public interface IGenericRepository<T> where T : class
{
IQueryable<T> GetAll();
IQueryable<T> Get(Expression<Func<T, bool>> predicate);
T Find(params object[] keys);
T GetFirstOrDefault(Expression<Func<T, bool>> predicate);
bool Any(Expression<Func<T, bool>> predicate);
void Insert(T entity);
void Edit(T entity);
void Delete(Expression<Func<T, bool>> predicate);
}
}
GenericRepository class:
namespace MyApplication.Data.Repositories
{
public class GenericRepository<T> : IDisposable, IGenericRepository<T> where T : class
{
private DatabaseContext _context;
private DbSet<T> _entity;
public GenericRepository(IUnitOfWork unitOfWork)
{
if (unitOfWork == null)
throw new ArgumentNullException("unitofwork");
_context = unitOfWork as DatabaseContext;
_entity = _context.Set<T>();
}
public IQueryable<T> GetAll()
{
return _entity;
}
public IQueryable<T> Get(Expression<Func<T, bool>> predicate)
{
return _entity.Where(predicate).AsQueryable();
}
// I delete some of the code to reduce the file size.
#region Dispose
public void Dispose()
{
// HERE IS MY FIRST DOUBT: MY METHOD ITS OK?!
// I saw implementations with GC.Suppress... and dispose in destructor, etc.
_context.Dispose();
}
#endregion
}
}
IUserRepository interface:
namespace MyApplication.Data.Interfaces
{
public interface IUserRepository : IGenericRepository<User> { }
}
UserRepository class:
namespace MyApplication.Data.Repositories
{
public class UserRepository : GenericRepository<User>, IUserRepository, IDisposable
{
public UserRepository(IUnitOfWork unitOfWork) : base(unitOfWork) {}
}
}
UserController controller class:
namespace MyApplication.Presentation.MVCWeb.Controllers
{
[Authorize]
public class UserController : Controller
{
private IUserRepository _userRepository;
private IProfileRepository _profileRepository;
private IUnitOfWork _unitOfWork;
public UserController()
{
this._unitOfWork = new DatabaseContext();
this._userRepository = new UserRepository(_unitOfWork);
this._profileRepository = new ProfileRepository(_unitOfWork);
}
public ActionResult List()
{
return View(this._userRepository.GetAll().ToList());
}
public ActionResult Create()
{
ViewBag.Profiles = new SelectList(this._profileRepository.GetAll().ToList(), "Id", "Name");
return View(new User());
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create([Bind(Exclude = "Id, Status, CompanyId")] User model)
{
ViewBag.Profiles = new SelectList(this._profileRepository.GetAll().ToList(), "Id", "Name");
if (ModelState.IsValid)
{
model.EmpresaId = 1;
model.Status = Status.Active;
_userRepository.Insert(model);
_unitOfWork.Save();
return RedirectToAction("List");
}
else
{
return View();
}
}
}
So, when and how i disposal my controller and/or my repositories and context?

UPDATED ANSWER:
Example of my controller:
private IGenericRepository<Profile> _repository;
private IUnitOfWork _unitOfWork = new DatabaseContext();
public ProfileController()
{
this._repository = new GenericRepository<Profile>(_unitOfWork);
}
public class ProfileController : Controller
{
private IGenericRepository<Profile> _repository;
private IUnitOfWork _unitOfWork = new DatabaseContext();
public ProfileController()
{
this._repository = new GenericRepository<Profile>(_unitOfWork);
}
}
With the code that you have now, the best thing to do is to override Controller.Dispose(bool disposing) and dispose of the repository in there.
protected override void Dispose(bool disposing)
{
if (disposing)
{
IDisposable d = _repository as IDisposable;
if (d != null)
d.Dispose();
GC.SupressFinalize(this);
}
base.Dispose(disposing);
}
Once you start using an IOC container, all of this disposal code will go away. Construction and disposal should happen at the container level. The container will be the only place where it is known or cared that the repository and unit of work are disposable.
But I suspect that none of these classes need to be disposable in the first place. You should use SqlConnection in a using block. It does not need to be a class-level field in DatabaseContext.
Please forgive the length of this answer. I must establish some fundamentals in order for my recommendation to make sense.
S.O.L.I.D.
SOLID ... stands for five basic principles of object-oriented programming and design. The two principles that are of concern here are the I and S.
Interface Segregation Principle (ISP)
Including IDisposable on the IGenericRepository<T> interface explicitly violates the ISP.
It does this because a repository's disposability (and the imperative to properly dispose of the object) is unrelated to it's designed purpose, which is to Get and Store aggregate root objects. By combining the interfaces together, you get a non-segregated interface.
Why is this important aside from violating some theoretical principle? I will explain that below. But first I have to cover another of the SOLID principles:
Single Resposibility Principle
I always keep this article, Taking the Single Responsibility Principle Seriously, handy when I re-factor functional code into good OO code. This is not an easy subject and the article is very dense. But it is invaluable as a thorough explanation of SRP.
Understanding SRP and disregarding the flaws in 99.9% of all MVC controllers out there which take many DI constructor parameters, the one flaw that is pertinent here is:
Making the controller be responsible for both using the repository and disposing of the repository crosses over to a different level of abstraction, and this violates the SRP.
Explanation:
So you're calling at least two public methods on the repository object. One to Get an object and one to Dispose of the repository. There's nothing wrong with that, right? Ordinarily no, there is nothing wrong with calling two methods on the repository or any object.
But Dispose() is special. The convention of disposal of an object is that it will no longer be useful after being disposed. This convention is one reason why the using pattern establishes a separate code block:
using (var foo = new Bar())
{
... // This is the code block
}
foo.DoSomething(); // <- Outside the block, this does not compile
This is technically legal:
var foo = new Bar();
using (foo)
{
... // This is the code block
}
foo.DoSomething(); // <- Outside the block, this will compile
But this gives a warning of usage of an object after it has been disposed. This is not proper which is why you don't see examples of this usage in the MS documentation.
Because of this unique convention, Dispose(), is more closely related to constructing and destructing an object than to the usage of other members of an object, even though it is exposed as a simple public method.
Construction and Disposal are on the same low level of abstraction. But because the controller is not constructing the repository itself, it lives on a higher level of abstraction. When disposing the repository, it is reaching outside of its level of abstraction to fiddle with the repository object at a different level. This violates the SRP.
Code Reality
Okay, all that theory means exactly what as far as my code is concerned?
Consider what the controller code looks like when it disposes of the repository itself:
public class CustomerController : Controller
{
IGenericRepository<Customer> _customerRepo;
IMapper<Customer, CustomerViewModel> _mapper;
public CustomerController(
IMapper<Customer, CustomerViewModel> customerRepository,
IMapper<Customer, CustomerViewModel> customerMapper)
{
_customerRepo = customerRepository;
_customerMapper = customerMapper;
}
public ActionResult Get(int id)
{
CustomerViewModel vm;
using (_customerRepo) // <- This looks fishy
{
Customer cust = _customerRepo.Get(id);
vm = _customerMapper.MapToViewModel(cust);
}
return View(wm);
}
public ActionResult Update(CustomerViewModel vm)
{
Customer cust = _customerMapper.MapToModel(vm);
CustomerViewModel updatedVm;
using(_customerRepo) // <- Smells like 3 week old flounder, actually
{
Customer updatedCustomer = _customerRepo.Store(cust);
updatedVm = _customerMapper.MapToViewModel(updatedCustomer);
}
return View(updatedVm);
}
}
The controller must receive a useful (non disposed) repository when it is constructed. This is a common expectation. But don't call two methods in the controller or it will break. This controller is a one-shot deal only. Plus, you cannot even call one public method from within another. E.g. the Update method could call Get after storing the model in the repository in order to return an updated Customer View. But this would blow up.
Conclusion
Receiving the repository as a parameter means that something else is responsible for creating the repository. That something else should also be responsible for properly disposing of the repository.
The alternative of disposing an object at the same level of abstraction as using its (other) public members, when the lifetime of the object and possible subsequent usage of the object is not under direct control, is a ticking time bomb.
The rule of IDisposable is this: It is never acceptable to inherit IDisposable in a another functional interface declaration because IDisposable is never a functional concern, but an implementation detail only.

Have your Interface inherit from IDisposable:
public interface IGenericRepository<T> : IDisposable where T : class
{
//...
}
Class:
public class GenericRepository<T> : IGenericRepository<T>
{
public void Dispose()
{
//....
}
}

Single Resposibility Principle
If you look at SRP and use that in MVC it tells you that when you have transactions that are made up of multiple methods (CRUDS) thats not a correct way of implementing the transactions.
So you should put those multiple (CRUD) methods in one method and in that Transaction method implement using for the database context so you can pass that database context to those called private methods that make up the transaction method. If all those (CRUD) methods succeed you can call the Commit method (SaveChanges). When those methods fail you do nothing (=Rollback). So make sure no Commit is executed in those methods but delegate it to the Transaction method.
By implementing the 2nd bullet IDispose is not needed in Repositories because using takes care of cleaning up the database context.
If Connection Pooling is used thats an efficient way of implementing it and it will be scalable.
In the way you setup a Class above it feels wrong. Because in the constructor for the Repository you could set the database context and use that same contextin several methods but then you would need to implement IDispose because you need to cleanup the connections yourself. In lots of examples for Repositories its implemented this way buts from a SRP point of view thats not right and should be changed according to the 2nd bullet above.

Context: You asked for the correct way to implement the dispose functionality.
Solution: This is an alternative for this and any other cases. this automatic alternative is suggested by Visual Studio itself (I tested in VS2017 and VS2019) :
Add the IDisposable contract next to your class name => class MyClass : IDisposable
Then with cursor still on that word "IDisposable", do Alt+Enter or Ctrl+. to enable "Quick Actions"
Then select "Implement interface with Dispose pattern"
Finally you can complete that code-pattern for your managed and unmanaged objects following suggestions indicated in comments.

Related

Autofac factory of unit of work in a singleton

Plain and simple as the title suggests, is this a possible thing using Autofac dependency injection? I have been trying and searching everywhere.. I'm losing hope here.
My class has to be singleton - that can't change. I want it to take a factory of unit of works - for database transactions.
Please help me figure this one out, I'm deseperate.
Tried Func<> and registering my unit of work in every possible way (all sorts of lifetimes, externally owned or not) but failed because the DbContext within the unit of work is disposed and not created again after the first request
Edit:
Added code that will hopefully help understanding my problem:
public class SingletonDataService : IDataService
{
private _uowFactory;
public SingletonDataService(Func<IEFUnitOfWork> uowFactory)
{
_uowFactory = uowFactory
}
public List<Folder> GetAllFolders ()
{
using (uow = uowFactory())
{
return uow.FoldersRepository.GetAll();
}
}
}
public MyDbContext : DbContext
{
public DbSet<Folder> Folders {get; set;}
public DbSet<Letter> Letters {get; set;}
public MyDbContext() : base("myContext...")
}
public EFUnitOfWork : IEFUnitOfWork, IDisposable
{
public IRepository<Folder> FoldersRepository;
public IRepository<Letter> LettersRepository;
private DbContext _context;
public EFUnitOfWork(IRepository<Folder> folders, IRepository<Letter> letters, DbContext context)
{
_folders = folders;
_letters = letters;
_context = context;
}
private bool disposed = false;
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
_context.Dispose();
}
disposed = true;
}
}
}
public Repository<T> : IRepository<T> where T: BaseEntity
{
private DbContext _context;
private DbSet<T> _set
public Repository(DbContext context)
{
_context = context;
_set = _context.Set<T>();
}
}
public LettersController : ApiController
{
private IDataService _dataService;
public LettersController(IDataService dataService)
{
_dataService = dataService;
}
[HttpGet]
public IHttpActionResult GetAllLetters()
{
return Ok(_dataService.GetAllLetters());
}
}
// Must be singleton
builder.Register<SingletonDataService>().As(IDataService).SingleInstance();
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.InstancePerLifetimeScope();
builder.Register<EFUnitOfWork>().As(IEFUnitOfWork).InstancePerLifetimeScope();
builder.Register<DbContext>().As(AppDbContext).InstancePerLifetimeScope();
In the first request everything works fine, in the second third and so on I get this exception :
system.ObjectDisposedException: The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
I clearly see it happens because the context in my repository is now null, but I don't how to to change that with the DI.
What I want to achieve is so easy without DI :
How can I achieve the following with Autofac??
public class UowFactory
{
public UowFactory()
{
}
public IEFUnitOfWork Create()
{
var context = new AppDbContext()
var uow = new EFUnitOfWork(new Repository<Folder>(context), new Repository<Letter>(context), context);
return uow;
}
}
Issue
You are registering the critial components with InstancePerLifetimeScope()
When the autofac container is built it also creates a root ILifetimeScope which lives until IContainer.Dispose() is called. Now unless you create nested ILifetimeScope somewhere in the chain to the SingletonDataService, the ILifetimeScope which is used your components is the root ILifetimeScope and InstancePerLifetimeScope() effectly becomes equivalent to SingleInstance().
Solution
One of the possible solutions is to create an ILifetimeScope per IEFUnitOfWork and its children. Autofac facilitates this by providing the Owned<T> type. We can use it in conjunction with a Func<> factory (also see documentation):
public class SingletonDataService : IDataService
{
private Func<Owned<IEFUnitOfWork>> _uowFactory;
public SingletonDataService(Func<Owned<IEFUnitOfWork>> uowFactory)
{
_uowFactory = uowFactory
}
public List<Folder> GetAllFolders ()
{
using (var uow = _uowFactory())
{
return uow.Value.FoldersRepository.GetAll();
}
}
}
This should play nicely with the following registrations:
// Must be singleton
builder.Register<SingletonDataService>().As(IDataService).SingleInstance();
builder.RegisterGeneric(typeof(Repository<>))
.As(typeof(IRepository<>))
.InstancePerLifetimeScope();
builder.Register<EFUnitOfWork>().As(IEFUnitOfWork).InstancePerLifetimeScope();
builder.Register<DbContext>().As(AppDbContext).InstancePerLifetimeScope();
However, note, that DbContext being bound with InstancePerLifetimeScope basically makes the manual disposal in EFUnitOfWork redundant.
Sidenote on proper Disposal
Since IDisposable types should support graceful multi-disposal , one should be able to simplify EFUnitOfWork.Dispose() to
public void Dispose()
{
_context.Dispose();
}
Also note, that i left out the call GC.SuppressFinalize(this);. This call is only relevant in case the class implements a custom finalizer (~EFUnitOfWork method) - or a deriving class could do so, otherwise the object is not put on the finalizer queue anyway.
Your problem is that you have a singleton (SingletonDataService) depend on a service that has a shorter lifetime (EFUnitOfWork). When the SingletonDataService instance is created by autofac, it gets an instance of EFUnitOfWork, but this instance will always stay the same (its actual lifetime will be longer than you expect) and thus gets disposed and used again, giving errors.
You have two possible solutions:
One is to create a UowFactory class like the one you defined at the bottom (but with dependencies on IRepository<Folder>, IRepository<Letter>, DbContext), register that as anything (for example singleton, but it won't matter) and make the SingletonDataService depend on it. This will likely not be a viable solution to you though, since it will also extend the lifetime of the IRepository<Folder>, IRepository<Letter>, DbContext instances and create problems there.
The proper solution is to remove the reason why you would want the SingletonDataService to be a singleton, probably some cache. And move it to a new service (CacheService?) on which the SingletonDataService depends and make that new service a singleton.

How can I wrap DbContext in a wrapper that will allow unit testing of custom methods?

I have the following situation. Trying to wrap an adapter around a DB Context for various reasons, with simplified unit testing being one of them. Slimmed down version of the code as follows:
public interface IDbAdapter
{
void SaveChanges(string userId);
}
public interface IDbContext
{
IDbAdapter Attempt();
}
public class DbAdapter : IDbAdapter
{
private readonly DbContext _dbContext;
public DbAdapter(DbContext dbContext)
{
_dbContext = dbContext;
}
public virtual void SaveChanges(string userId)
{
PopulateAuditFields(userId);
_dbContext.SaveChanges();
}
}
public partial class MyEntities: IDBContext
{
private IDbAdapter _dbAdapter;
public virtual IDbAdapter Attempt()
{
return _dbAdapter ?? (_dbAdapter = new DbAdapter(this));
}
}
Now this works. Code simply performs a (MyEntities Object).Attempt().SaveChanges(userId) and the unit tests can simply mock this method entirely. There's a bunch of other methods as well on this adapter, but they are not listed here.
However, I am not sure about having to perform this "redirection" to the wrapper implementation. Is there a cleaner way to achieve such a wrapper?
Just curious what you would recommend in this situation? I also don't want to create extension methods on the interface, because this has caused me a rabbit hole in regards to unit testing; I've also tried have an Adapter Factory with a public static Func<> property which I can swap out at testing, but that caused issues when running multiple tests in parallel.
Edit:
I failed to mention that the MyEntities is a partial class, extending the auto-generated DbContext that is made via Database-First approach of Entity Framework. Thus, I can not create a parameterless constructor on the partial class.

Using the Generic repository/Unit of work pattern in large projects

I'm working on a quite large application. The domain has about 20-30 types, implemented as ORM classes (for example EF Code First or XPO, doesn't matter for the question). I've read several articles and suggestions about a generic implementation of the repository pattern and combining it with the unit of work pattern, resulting a code something like this:
public interface IRepository<T> {
IQueryable<T> AsQueryable();
IEnumerable<T> GetAll(Expression<Func<T, bool>> filter);
T GetByID(int id);
T Create();
void Save(T);
void Delete(T);
}
public interface IMyUnitOfWork : IDisposable {
void CommitChanges();
void DropChanges();
IRepository<Product> Products { get; }
IRepository<Customer> Customers { get; }
}
Is this pattern suitable for really large applications? Every example has about 2, maximum 3 repositories in the unit of work. As far as I understood the pattern, at the end of the day the number of repository references (lazy initialized in the implementation) equal (or nearly equal) to the number of domain entity classes, so that one can use the unit of work for complex business logic implementation. So for example let's extend the above code like this:
public interface IMyUnitOfWork : IDisposable {
...
IRepository<Customer> Customers { get; }
IRepository<Product> Products { get; }
IRepository<Orders> Orders { get; }
IRepository<ProductCategory> ProductCategories { get; }
IRepository<Tag> Tags { get; }
IRepository<CustomerStatistics> CustomerStatistics { get; }
IRepository<User> Users { get; }
IRepository<UserGroup> UserGroups { get; }
IRepository<Event> Events { get; }
...
}
How many repositories cab be referenced until one thinks about code smell? Or is it totally normal for this pattern? I could probably separate this interface into 2 or 3 different interfaces all implementing IUnitOfWork, but then the usage would be less comfortable.
UPDATE
I've checked a basically nice solution here recommended by #qujck. My problem with the dynamic repository registration and "dictionary based" approach is that I would like to enjoy the direct references to my repositories, because some of the repositories will have special behaviour. So when I write my business code I would like to be able to use it like this for example:
using (var uow = new MyUnitOfWork()) {
var allowedUsers = uow.Users.GetUsersInRolw("myRole");
// ... or
var clothes = uow.Products.GetInCategories("scarf", "hat", "trousers");
}
So here I'm benefiting that I have a strongly typed IRepository and IRepository reference, hence I can use the special methods (implemented as extension methods or by inheriting from the base interface). If I use a dynamic repository registration and retrieval method, I think I'm gonna loose this, or at least have to do some ugly castings all the time.
For the matter of DI, I would try to inject a repository factory to my real unit of work, so it can lazily instantiate the repositories.
Building on my comments above and on top of the answer here.
With a slightly modified unit of work abstraction
public interface IMyUnitOfWork
{
void CommitChanges();
void DropChanges();
IRepository<T> Repository<T>();
}
You can expose named repositories and specific repository methods with extension methods
public static class MyRepositories
{
public static IRepository<User> Users(this IMyUnitOfWork uow)
{
return uow.Repository<User>();
}
public static IRepository<Product> Products(this IMyUnitOfWork uow)
{
return uow.Repository<Product>();
}
public static IEnumerable<User> GetUsersInRole(
this IRepository<User> users, string role)
{
return users.AsQueryable().Where(x => true).ToList();
}
public static IEnumerable<Product> GetInCategories(
this IRepository<Product> products, params string[] categories)
{
return products.AsQueryable().Where(x => true).ToList();
}
}
That provide access the data as required
using(var uow = new MyUnitOfWork())
{
var allowedUsers = uow.Users().GetUsersInRole("myRole");
var result = uow.Products().GetInCategories("scarf", "hat", "trousers");
}
The way I tend to approach this is to move the type constraint from the repository class to the methods inside it. That means that instead of this:
public interface IMyUnitOfWork : IDisposable
{
IRepository<Customer> Customers { get; }
IRepository<Product> Products { get; }
IRepository<Orders> Orders { get; }
...
}
I have something like this:
public interface IMyUnitOfWork : IDisposable
{
Get<T>(/* some kind of filter expression in T */);
Add<T>(T);
Update<T>(T);
Delete<T>(/* some kind of filter expression in T */);
...
}
The main benefit of this is that you only need one data access object on your unit of work. The downside is that you don't have type-specific methods like Products.GetInCategories() any more. This can be problematic, so my solution to this is usually one of two things.
Separation of concerns
First, you can rethink where the separation between "data access" and "business logic" lies, so that you have a logic-layer class ProductService that has a method GetInCategory() that can do this:
using (var uow = new MyUnitOfWork())
{
var productsInCategory = GetAll<Product>(p => ["scarf", "hat", "trousers"].Contains(u.Category));
}
Your data access and business logic code is still separate.
Encapsulation of queries
Alternatively, you can implement a specification pattern, so you can have a namespace MyProject.Specifications in which there is a base class Specification<T> that has a filter expression somewhere internally, so that you can pass it to the unit of work object and that UoW can use the filter expression. This lets you have derived specifications, which you can pass around, and now you can write this:
using (var uow = new MyUnitOfWork())
{
var searchCategories = new Specifications.Products.GetInCategories("scarf", "hat", "trousers");
var productsInCategories = GetAll<Product>(searchCategories);
}
If you want a central place to keep commonly-used logic like "get user by role" or "get products in category", then instead of keeping it in your repository (which should be pure data access, strictly speaking) then you could have those extension methods on the objects themselves instead. For example, Product could have a method or an extension method InCategory(string) that returns a Specification<Product> or even just a filter such as Expression<Func<Product, bool>>, allowing you to write the query like this:
using (var uow = new MyUnitOfWork())
{
var productsInCategory = GetAll(Product.InCategories("scarf", "hat", "trousers");
}
(Note that this is still a generic method, but type inference will take care of it for you.)
This keeps all the query logic on the object being queried (or on an extensions class for that object), which still keeps your data and logic code nicely separated by class and by file, whilst allowing you to share it as you have been sharing your IRepository<T> extensions previously.
Example
To give a more specific example, I'm using this pattern with EF. I didn't bother with specifications; I just have service classes in the logic layer that use a single unit of work for each logical operation ("add a new user", "get a category of products", "save changes to a product" etc). The core of it looks like this (implementations omitted for brevity and because they're pretty trivial):
public class EFUnitOfWork: IUnitOfWork
{
private DbContext _db;
public EntityFrameworkSourceAdapter(DbContext context) {...}
public void Add<T>(T item) where T : class, new() {...}
public void AddAll<T>(IEnumerable<T> items) where T : class, new() {...}
public T Get<T>(Expression<Func<T, bool>> filter) where T : class, new() {...}
public IQueryable<T> GetAll<T>(Expression<Func<T, bool>> filter = null) where T : class, new() {...}
public void Update<T>(T item) where T : class, new() {...}
public void Remove<T>(Expression<Func<T, bool>> filter) where T : class, new() {...}
public void Commit() {...}
public void Dispose() {...}
}
Most of those methods use _db.Set<T>() to get the relevant DbSet, and then just query it with LINQ using the provided Expression<Func<T, bool>>.

Auto Dispose Sql Connections properly

My application is using 3 layers: DAL / Service / UL.
My typical DAL class looks like this:
public class OrdersRepository : IOrdersRepository, IDisposable
{
private IDbConnection _db;
public OrdersRepository(IDbConnection db) // constructor
{
_db = db;
}
public void Dispose()
{
_db.Dispose();
}
}
My service calls the DAL class like this (injecting a database connection):
public class ordersService : IDisposable
{
IOrdersRepository _orders;
public ordersService() : this(new OrdersRepository(new Ajx.Dal.DapperConnection().getConnection()))
{
}
public ordersService(OrdersRepository ordersRepo)
{
_orders = ordersRepo;
}
public void Dispose()
{
_orders.Dispose();
}
}
And then finally within my UI layer, this is how I access my service layer:
public class OrdersController : Controller, IDisposable
{
//
// GET: /Orders/
private ordersService _orderService;
public OrdersController():this(new ordersService())
{
}
public OrdersController(ordersService o)
{
_orderService = o;
}
void IDisposable.Dispose()
{
_orderService.Dispose();
}
}
This all works good. But as you can see, I am relying on IDisposable within every layer. UI disposes service object and then service object disposes DAL object and then DAL object disposes the database connection object.
I am sure there has to be a better way of doing it. I am afraid users can forget to dispose my service object (within UI) and I will end up with many open database connections or worse. Please advise the best practice. I need a way to auto-dispose my database connections OR any other unmanaged resources (files etc).
Your question comes back to the principle of ownership:
he who has ownership of the resource, should dispose it.
Although ownership can be transferred, you should usually not do this. In your case the ownership of the IDbConnection is transferred from the ordersService to the OrdersRepository (since OrdersRepository disposes the connection). But in many cases the OrdersRepository can't know whether the connection can be disposed. It can be reused throughout the object graph. So in general, you should not dispose objects that are passed on to you through the constructor.
Another thing is that the consumer of a dependency often can't know if a dependency needs disposal, since whether or not a dependency needs to be disposed is an implementation detail. This information might not be available in the interface.
So instead, refactor your OrdersRepository to the following:
public class OrdersRepository : IOrdersRepository {
private IDbConnection _db;
public OrdersRepository(IDbConnection db) {
_db = db;
}
}
Since OrdersRepository doesn't take ownership, IDbConnection doesn't need to dispose IDbConnection and you don't need to implement IDisposable. This explicitly moves the responsibility of disposing the connection to the OrdersService. However, ordersService by itself doesn't need IDbConnection as a dependency; it just depends on IOrdersRepository. So why not move the responsibility of building up the object graph out of the OrdersService as well:
public class OrdersService : IDisposable {
private readonly IOrdersRepository _orders;
public ordersService(IOrdersRepository ordersRepo) {
_orders = ordersRepo;
}
}
Since ordersService has nothing to dispose itself, there's no need to implement IDisposable. And since it now has just a single constructor that takes the dependencies it requires, the class has become much easier to maintain.
So this moves the responsibility of creating the object graph to the OrdersController. But we should apply the same pattern to the OrdersController as well:
public class OrdersController : Controller {
private ordersService _orderService;
public OrdersController(ordersService o) {
_orderService = o;
}
}
Again, this class has become much easier to grasp and it doesn't needs to dispose anything, since it doesn't has or took ownership of any resource.
Of course we just moved and postponed our problems, since obviously we still need to create our OrdersController. But the difference is that we now moved the responsiblity of building up object graphs to a single place in the application. We call this place the Composition Root.
Dependency Injection frameworks can help you making your Composition Root maintainable, but even without a DI framework, you build your object graph quite easy in MVC by implementing a custom ControllerFactory:
public class CompositionRoot : DefaultControllerFactory {
protected override IController GetControllerInstance(
RequestContext requestContext, Type controllerType) {
if (controllerType == typeof(OrdersController)) {
var connection = new Ajx.Dal.DapperConnection().getConnection();
return new OrdersController(
new OrdersService(
new OrdersRepository(
Disposable(connection))));
}
else if (...) {
// other controller here.
}
else {
return base.GetControllerInstance(requestContext, controllerType);
}
}
public static void CleanUpRequest() }
var items = (List<IDisposable>)HttpContext.Current.Items["resources"];
if (items != null) items.ForEach(item => item.Dispose());
}
private static T Disposable<T>(T instance)
where T : IDisposable {
var items = (List<IDisposable>)HttpContext.Current.Items["resources"];
if (items == null) {
HttpContext.Current.Items["resources"] =
items = new List<IDisposable>();
}
items.Add(instance);
return instance;
}
}
You can hook your custom controller factory in the Global asax of your MVC application like this:
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
ControllerBuilder.Current.SetControllerFactory(
new CompositionRoot());
}
protected void Application_EndRequest(object sender, EventArgs e)
{
CompositionRoot.CleanUpRequest();
}
}
Of course, this all becomes much easier when you use a Dependency Injection framework. For instance, when you use Simple Injector (I'm the lead dev for Simple Injector), you can replace all of this with the following few lines of code:
using SimpleInjector;
using SimpleInjector.Integration.Web;
using SimpleInjector.Integration.Web.Mvc;
public class MvcApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
var container = new Container();
container.RegisterPerWebRequest<IDbConnection>(() =>
new Ajx.Dal.DapperConnection().getConnection());
container.Register<IOrdersRepository, OrdersRepository>();
container.Register<IOrdersService, OrdersService>();
container.RegisterMvcControllers(Assembly.GetExecutingAssembly());
container.Verify();
DependencyResolver.SetResolver(
new SimpleInjectorDependencyResolver(container));
}
}
There are a few interesting things going on in the code above. First of all, the calls to Register tell Simple Injector that they need to return a certain implementation should be created when the given abstraction is requested. Next, Simple Injector allows registering types with the Web Request Lifestyle, which makes sure that the given instance is disposed when the web request ends (just as we did in the Application_EndRequest). By calling RegisterMvcControllers, Simple Injector will batch-register all Controllers for you. By supplying MVC with the SimpleInjectorDependencyResolver we allow MVC to route the creation of controllers to Simple Injector (just as we did with the controller factory).
Although this code might be a bit harder to understand at first, the use of a Dependency Injection container becomes really valuable when your application starts to grow. A DI container will help you keeping your Composition Root maintainable.
Well, if you're really paranoid about that you can use the finalizer (destructor) to automatically execute the Dispose when the object is being garbage collected. Check this link which explains basically all you need to know about IDisposable, skip to the Examples section if just want a quick sample how to do that. The finalizer(destructor) is the ~MyResource() method.
But any way, you should always encourage the consumers of your libraries to use correctly the Dispose. The automatic cleaning up, by means of garbage collector still presents flaws. You don't know when the garbage collector will do its job, so if you get lots of these classes instantiated and used, then forgotten, in a short time, you may still be in trouble.

Proper use of "Using" statement for datacontext

I’m using Linq to Entities and lately, I found that a lot of folks recommending wrapping the datacontext in a using statement like this:
Using(DataContext db = new DataContext) {
var xx = db.customers;
}
This makes sense. However, I’m not sure how to incorporate this practice in my model.
For example: I have an interface (let’s call it customer) and it is implemented by a repository like this:
namespace Models
{
public class rCustomer : iCustomer
{
readonly DataContext db = new DataContext();
public customer getCustomer(Guid id)
{
return db.customers.SingleOrDefault(por => por.id == id);
}
public iQueryable<customer> getTopCustomers()
{
return db.customers.Take(10);
}
//*******************************************
//more methods using db, including add, update, delete, etc.
//*******************************************
}
}
Then, to take the advantage of using, I will need to change the methods to look like this:
namespace Models
{
public class rCustomer : iCustomer
{
public customer getCustomer(Guid id)
{
using(DataContext db = new DataContext()) {
return db.customers.SingleOrDefault(por => por.id == id);
}
}
public iQueryable<customer> getTopCustomers()
{
using(DataContext db = new DataContext()) {
return db.customers.Take(10);
}
}
//*******************************************
//more methods using db
//*******************************************
}
}
My question is: the recommendation of using “Using” is really that good? Please take in consideration that this change will be a major one, I have about 25 interfaces/repository combos, and each has about 20-25 methods, not to mention the need to re-test everything after finish.
Is there other way?
Thanks!
Edgar.
You can implement a Database factory which will cause your DbContext is being reused.
You can achieve this as follows:
DatabaseFactory class:
public class DatabaseFactory : Disposable, IDatabaseFactory
{
private YourEntities _dataContext;
public YourEntities Get()
{
return _dataContext ?? (_dataContext = new YourEntities());
}
protected override void DisposeCore()
{
if (_dataContext != null)
_dataContext.Dispose();
}
}
Excerpt of the Repository base class:
public abstract class Repository<T> : IRepository<T> where T : class
{
private YourEntities _dataContext;
private readonly IDbSet<T> _dbset;
protected Repository(IDatabaseFactory databaseFactory)
{
DatabaseFactory = databaseFactory;
_dbset = DataContext.Set<T>();
}
protected IDatabaseFactory DatabaseFactory
{
get;
private set;
}
protected YourEntities DataContext
{
get { return _dataContext ?? (_dataContext = DatabaseFactory.Get()); }
}
Your table's repository class:
public class ApplicationRepository : Repository<YourTable>, IYourTableRepository
{
private YourEntities _dataContext;
protected new IDatabaseFactory DatabaseFactory
{
get;
private set;
}
public YourTableRepository(IDatabaseFactory databaseFactory)
: base(databaseFactory)
{
DatabaseFactory = databaseFactory;
}
protected new YourEntities DataContext
{
get { return _dataContext ?? (_dataContext = DatabaseFactory.Get()); }
}
}
public interface IYourTableRepository : IRepository<YourTable>
{
}
}
This works perfectly together with AutoFac constructor injection as well.
Considering the code provided I see, you esplicitly use readonly DataContext db = new DataContext(); like a global variable, so you consider to have that object lifetime along with your rCustomer class instance lifetime.
If this is true, what you can do, instead of rewriting everything, you can implement IDisposable and inside Dispose() code something like
private void Dispose()
{
if(db != null)
db.Dispose();
}
Hope this helps.
As others have mentioned, it's important for the data contexts to be disposed. I won't go into that further.
I see three possible designs for the class that ensure that the contexts are disposed:
The second solution you provide in which you create a data context within the scope of each method of rCustomer that needs it so that each datacontext is in a using block.
Keep the data context as an instance variable and have rCustomer implement IDisposable so that when rCustomer is disposed you can dispose of it's data context. This means that all rCustomer instances will need to be wrapped in using blocks.
Pass an instance of an existing data context into rCustomer through its constructor. If you do this then rCustomer won't be responsible for disposing of it, the user of the class will. This would allow you to use a single data context across several instances of rCustomer, or with several different classes that need access to the data context. This has advantages (less overhead involved in creating new data contexts) and disadvantages (larger memory footprint as data contexts tend to hold onto quite a lot of memory through caches and the like).
I honestly think option #1 is a pretty good one, as long as you don't notice it performing too slowly (I'd time/profile it if you think it's causing problems). Due to connection pooling it shouldn't be all that bad. If it is, I'd go with #3 as my next choice. #2 isn't that far behind, but it would likely be a bit awkward and unexpected for other members of your team (if any).
The DataContext class is wrapped in a Using statement because it implements the IDisposable interface.
Internal to the DataContext it is using SqlConnection objects and SqlCommand objects. In order to correctly release these connection back to the Sql Connection Pool, they need to be disposed of.
The garbage collector will eventually do this, but it will take two passes due to the way IDisposable objects are managed.
It's strongly encouraged that Dispose is called and the Using statement is a nice way to do this.
Read these links for more indepth explanation:
http://social.msdn.microsoft.com/Forums/en-US/adodotnetentityframework/thread/2625b105-2cff-45ad-ba29-abdd763f74fe/
http://www.c-sharpcorner.com/UploadFile/DipalChoksi/UnderstandingGarbageCollectioninNETFramework11292005051110AM/UnderstandingGarbageCollectioninNETFramework.aspx
An alternative would be to make your rCustomer class implement IDisposable, and then in your Dispose method, you can call Dispose on your DataContext if it is not null. However, this just pushes the Disposable pattern out of your rCustomer class, into whatever types are using rCustomer.

Categories

Resources