I am new to Repository concept and get some questions. I have created simple repository class in my MVC app.
public interface IRepository<TEntity> where TEntity : class
{
List<TEntity> FetchAll();
IQueryable<TEntity> Query { get; }
void Add(TEntity entity);
void Delete(TEntity entity);
void Save();
}
public class SqlRepository<T> : IRepository<T> where T : class
{
readonly DataContext _db;
public SqlRepository(DataContext db)
{
_db = db;
}
#region IRepository<T> Members
public IQueryable<T> Query
{
get { return _db.GetTable<T>(); }
}
public List<T> FetchAll()
{
return Query.ToList();
}
public void Add(T entity)
{
_db.GetTable<T>().InsertOnSubmit(entity);
}
public void Delete(T entity)
{
_db.GetTable<T>().DeleteOnSubmit(entity);
}
public void Save()
{
_db.SubmitChanges();
}
#endregion
}
In my Controller I initialize repository classes for specified table class like this
public class AdminController : Controller
{
private readonly SqlRepository<User> _userRepository = new SqlRepository<User>(new DataContext(ConfigurationManager.ConnectionStrings["ConnectionString"].ToString()));
private readonly SqlRepository<Order> _orderRepository = new SqlRepository<Order>(new DataContext(ConfigurationManager.ConnectionStrings["ConnectionString"].ToString()));
//Skip code
}
But I duplicate this code again and again in many places in my app. What is the best place to instanceate these repository classes?
I think you should refer to repository via it's interface:
public class AdminController : Controller
{
private readonly IRepository<User> _userRepository;
private readonly IRepository<Order> _orderRepository;
public AdminController(IRepository<User> userRepository,
IRepository<Order> orderRepository)
{
_userRepository = userRepository;
_orderRepository = orderRepository;
}
//Skip code
}
And inject implementations via some dependency injection framework.
UPDATE
You can use Ninject for dependency injection to your controllers. Here is Example how to add DependencyResolver to your application. In your case you can configure kernel this way:
IKernel kernel = new StandardKernel();
var connectionString = ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString;
kernel.Bind(typeof(DataContext)).ToMethod(context => new DataContext(connectionString));
kernel.Bind(typeof(IRepository<>)).To(typeof(SqlRepository<>));
And that's it. No duplication. Dependencies are resolved. Your class does not depend on concrete repositories. You can easy mock dependencies for testing.