Reputation: 4748
So I have a bunch of entity models.
Lots of controllers and views and the controllers often go and do a linq query and making it available to the view.
However lets say I have a model Users
and I have a linq query to get all active users
Putting that in a controller might be fine if its done once, but I want to repeat it, im wondering where the correct place to be putting Model specific queries.
Ideally the controller then says Users.getActiveUsers() or similar.
Upvotes: 0
Views: 205
Reputation: 32604
You should look into the Repository Pattern.
The Repository Pattern allows you to abstract this database logic and reduce the redundancy of common data calls. Since you are formulating LINQ queries often, why not put them into a one common class?
public class UserRepository
{
private readonly _dbContext MyDbContext;
public IEnumerable<User> getActiveUsers()
{
// whatever you do to find the active users
return _dbContext.Where(user => user.Active == true);
}
}
Now you can inject this repository into your controller.
public class HomeController : Controller
{
private readonly UserRepository _userRepo;
public HomeController()
{
_userRepo = new UserRepository();
}
public ActionResult Index()
{
var activeUsers = _userRepo.getActiveUsers();
return View(activeUsers);
}
}
The above implementation will solve your problem, but it does tightly couple your controller to your repository. The solution to decouple them would be to use an interface for the UserRepository and then use Dependency Injection (with Ninject, Unity, AutoFaq or whatever) to resolve the type for the interface.
Upvotes: 2
Reputation: 236208
I suggest to move data-access logic to separate classes (repositories) which will act as in-memory collections of entities and hide all data-access logic. E.g. if you have entity User
you can create repository which will encapsulate all linq queries related to users:
public class UserRepository : IUserRepository
{
private YourDbContext _db;
public UserRepository(YourDbContext db)
{
_db = db;
}
public User GetById(int id)
{
return _db.Users.Find(id);
}
public IEnumerable<User> GetAll()
{
return _db.Users.AsEnumerable();
}
public IEnumerable<User> GetUsersByRole(string role)
{
return _db.Users.Where(u => u.Role == role).AsEnumerable();
}
}
That will keep all data-access code in one place, without duplications. When you will add another repositories you will find some duplicated logic (e.g. getting entity by id, or getting all entities) which can be moved to base generic repository class.
I also suggest to depend on repository interface in your controllers:
public interface IUserRepository
{
User GetById(int id);
IEnumerable<User> GetAll();
IEnumerable<User> GetUsersByRole(string role);
}
That will make unit-testing of controllers very easy (mocking repositories and injecting mocks):
public class UserController : Controller
{
private readonly IUserRepository _userRepository;
public UserController(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public ActionResult Index()
{
// Note: usually you should not use entities in view
// create appropriate view models and map entities to them
var model = _userRepository.GetAll();
return View(model);
}
}
Upvotes: 2