2014-02-05 50 views
0

所以我有一堆實體模型。asp.net mvc數據邏輯結構

許多控制器和視圖以及控制器經常去執行linq查詢並使其可用於視圖。

但是可以說我有一個模型,用戶

,我有一個LINQ查詢來獲取所有活躍用戶

把在控制器如果做一次也許是好的,但我想再說一遍,即時通訊想知道正確的地方放置模型特定的查詢。

理想情況下,控制器然後說Users.getActiveUsers()或類似的。

+0

我想什麼你正在尋找的是[存儲庫模式](http://blogs.msdn.com/b/wriju/archive/2013/08/23/using-repository-pattern-in-entity-framework.aspx)。然後你有一個'IRepository ''用'IQueryable Get(System.Func 查詢)'方法...'UserRepo.Get(u => u.Username ==「Bob」)' – Basic

+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或其他)來解析接口的類型。

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); 
    } 
} 
+0

如果您的所有實體都從一個公共類繼承,那麼您可以創建一個通用的存儲庫(和接口),而不需要重複使用代碼。就我而言,我將'Id'字段放在基類中,這意味着它可以用於實體不可知的目的。 – Basic

+1

@基本我經常以基礎實體類結束,但並非總是如此。如果你有不同類型的標識字段(int,long,guid)或者甚至是複合標識的實體,那麼基類將不會對你有幫助 –

+1

非常真實。我只是指出了OP的可能勝利,但你說得對,它絕對不適合所有情況。 – Basic