所以我有一堆实体模型。
许多控制器和视图以及控制器经常会执行linq查询并将其提供给视图。
但是,假设我有一个模型用户
我有一个linq查询来获取所有活跃用户
将它放在控制器中可能没问题,如果它完成一次,但我想重复它,我想知道在哪里放置模型特定查询的正确位置。
理想情况下,控制器会显示Users.getActiveUsers()或类似内容。
答案 0 :(得分:2)
您应该查看存储库模式。
存储库模式允许您抽象此数据库逻辑并减少公共数据调用的冗余。由于您经常编写LINQ查询,为什么不将它们放入一个公共类?
public class UserRepository
{
private readonly _dbContext MyDbContext;
public IEnumberable<User> getActiveUsers()
{
// whatever you do to find the active users
return _dbContext.Where(user => user.Active == true);
}
}
现在您可以将此存储库注入您的控制器。
public class HomeController : Controller
{
private readonly UserRepository _userRepo;
public HomeController()
{
_userRepo = new UserRepository();
}
public ActionResult Index()
{
var activeUsers = _userRepo.getActiveUsers();
return View(activeUsers);
}
}
上述实现将解决您的问题,但它确实将您的控制器与您的存储库紧密耦合。解耦它们的解决方案是使用UserRepository的接口,然后使用依赖注入(使用Ninject,Unity,AutoFaq或其他)来解析接口的类型。
答案 1 :(得分:2)
我建议将数据访问逻辑移动到单独的类(repositories),这些类将充当实体的内存集合并隐藏所有数据访问逻辑。例如。如果您有实体User
,则可以创建存储库,该存储库将封装与用户相关的所有linq查询:
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();
}
}
这将把所有数据访问代码保存在一个地方,而不会重复。当您添加另一个存储库时,您会发现一些重复的逻辑(例如,通过id获取实体,或获取所有实体),这些逻辑可以移动到基础generic repository类。
我还建议依赖控制器中的存储库接口:
public interface IUserRepository
{
User GetById(int id);
IEnumerable<User> GetAll();
IEnumerable<User> GetUsersByRole(string role);
}
这将使控制器的单元测试非常容易(模拟存储库和注入模拟):
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);
}
}