2010-07-19 132 views
3

我已經在我的asp.net mvc web應用程序中實現了一個存儲庫模式...但是我想知道這是一個好的存儲庫模式,還是我可以改進它更多...好的存儲庫模式爲asp.net mvc

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 
using TaxiMVC.BusinessObjects; 

namespace TaxiMVC.Models 
{ 
    public class ClientRepository 
    { 
     private TaxiDataContext taxidb = new TaxiDataContext(); 
     Client cli = new Client(); 

     //Get all Clients 
     public IQueryable<ClientBO> FindAllClients(int userId) 
     { 
      var client = from c in taxidb.Clients 
         where c.CreatedBy == userId && c.IsDeleted == 0 
         select new ClientBO() 
         { 
          ClientId = c.ClientId, 
          ClientName= c.ClientName, 
          ClientMobNo= Convert.ToString(c.ClientMobNo), 
          ClientAddress= c.ClientAddress 
         }; 
      return client; 
     } 

     //Get Client By Id 
     public ClientBO FindClientById(int userId,int clientId) 
     { 
      return (from c in taxidb.Clients 
        where c.CreatedBy == userId && c.ClientId == clientId && c.IsDeleted == 0 
         select new ClientBO() 
         { 
          ClientId = c.ClientId, 
          ClientName= c.ClientName, 
          ClientMobNo= Convert.ToString(c.ClientMobNo), 
          ClientAddress= c.ClientAddress 
         }).FirstOrDefault(); 
     } 

     //Insert a new client 
     public bool ClientInsert(ClientBO clientBO) 
     { 
      cli.ClientName = clientBO.ClientName; 
      cli.ClientMobNo = Convert.ToInt64(clientBO.ClientMobNo); 
      cli.ClientAddress = clientBO.ClientAddress; 
      cli.CreatedDate = clientBO.CreatedDate; 
      cli.IsDeleted = clientBO.IsDeleted; 
      cli.CreatedBy = clientBO.CreatedBy; 

      if (!taxidb.Clients.Where(c => c.ClientMobNo == cli.ClientMobNo).Any()) 
      { 
       taxidb.Clients.InsertOnSubmit(cli); 
       taxidb.SubmitChanges(); 
       return true; 
      } 
      else 
       return false; 
     } 

     //Client Update 
     public ClientBO updateClient(ClientBO clientBO) 
     { 
      var table = taxidb.GetTable<Client>(); 
      var cli = table.SingleOrDefault(c => c.ClientId == clientBO.ClientId && c.CreatedBy==clientBO.CreatedBy); 
      cli.ClientName = clientBO.ClientName; 
      cli.ClientMobNo = Convert.ToInt64(clientBO.ClientMobNo); 
      cli.ClientAddress = clientBO.ClientAddress; 
      taxidb.SubmitChanges(); 
      return clientBO; 
     } 

     //Delete Clients 
     public bool deleteClients(string Ids, int userId) 
     { 
      var idsToDelete = Ids.Split(',').Select(c => Convert.ToInt32(c)); 
      var clientsToDelete = taxidb.Clients.Where(c => idsToDelete.Contains(c.ClientId)); 
      foreach (var client in clientsToDelete) 
      { 
       client.IsDeleted = Convert.ToByte(1); 
      } 
      taxidb.SubmitChanges(); 
      return true; 
     } 
    } 
} 

和我ClientBo.cs,

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Web; 

namespace TaxiMVC.BusinessObjects 
{ 
    public class ClientBO 
    { 
     public int ClientId { get; set; } 
     public string ClientName { get; set; } 
     public string ClientMobNo { get; set; } 
     public string ClientAddress { get; set; } 
     public DateTime CreatedDate { get; set; } 
     public byte IsDeleted { get; set; } 
     public int CreatedBy { get; set; } 
    } 
} 

我沒有在這裏實現一個IRepository ...我應該已經實現,或應我的倉庫能夠進一步提高......任何建議。 ...

+0

嚴格來說,它不是「存儲庫」模式。 你可以在這裏閱讀更多: http://fabiomaulo.blogspot.com/2009/09/repository-or-dao-repository.html – griZZZly8 2010-07-19 05:01:23

回答

15

嗯,我肯定會做一些事情來改善這一點。

第一個:我將爲您的Repository定義一個接口來實現。這允許您更好地控制依賴關係,並且當與控制反轉/依賴注入(IOC/DI)框架結合使用時,這會得到極大改善。 IOC/DI框架包括StructureMap或NInjet。閱讀Scott Hanselman的this,這是一個非常全面的列表。

你的界面可能看起來像:

public interface IClientRepository 
{ 
    IQueryable<ClientBO> FindAllClients(int userId); 
    ClientBO FindClientById(int userId, int clientId); 
    ClientInsert(ClientBO clientBO); 
    ClientBO updateClient(ClientBO clientBO); 
    bool deleteClients(string Ids, int userId); 
} 

二:不要做你的業務對象(ClientBO)持久性對象(Client)轉換你的倉庫內。這意味着如果您對BO進行了任何更改,則需要通過並更改整個存儲庫。

我注意到你有很多左 - 右分配代碼,例如。

cli.ClientName = clientBO.ClientName; 

我會認真調查AutoMapper的使用。它使這個「猴子代碼」變得更加簡單。

編輯:Here is a blog post描述如何使用AutoMapper刪除左右分配代碼。

第三名:您的命名結構遍佈整個店鋪。我們有:FindAllClients(),ClientInsert()updateClient()所有在一個類。非常非常差的命名。對於您的存儲庫,嘗試對數據庫端將發生的事情建模。嘗試AddInsert,Delete, FindAllGetAllFindGetAllSaveChanges,方法名稱。

不要在方法名稱中附加/添加類型,因爲在ClientRepository中,這意味着您將添加或獲取Client's。

第四個:您的混合您的LINQ語法。在某些地方,您使用聲明性查詢語法和其他地方使用方法語法。選擇1並在任何地方使用。

第五:此行讓我擔心:

if (!taxidb.Clients.Where(c => c.ClientMobNo == cli.ClientMobNo).Any()) 

這看起來很像商業邏輯給我。不是應該在存儲庫中的東西。要麼在數據庫中聲明該列爲UNIQUE,要麼將該邏輯移入另一個驗證層。

這些是我跳出來的主要事情。其中一些是個人喜好,但我希望這有助於。

+1

@Alaistar +1好的答案..但我不能得到你的第二點。 ..你可以更新第二個點與自動映射前ex ... – 2010-07-19 05:37:49

+0

更新與鏈接到一個很好的博客文章,描述過程。 – 2010-07-19 06:09:17

+0

好的答案 - 但我會質疑你對LINQ語法的看法。採取實用的方法來定義LINQ語句沒什麼問題,用最容易理解的方式編寫。 – 2010-07-19 08:38:57

1

爲什麼你使用字符串編號的數組:

public bool deleteClients(string Ids, int userId) 

我認爲你應該使用int[]List<int>

另外我會在FindAllClients中寫List但不是IQueryable。

public List<ClientBO> FindAllClients(int userId) 

當然,您應該編寫接口IClientRepository,因爲根據SOLID原則它是正確的方法。

如果你寫的接口,那麼你可以寫一個更靈活地使用資源庫與該接口的其他類,像這樣:

public class ClientService : IClientService 
{ 
    IClientRepository m_clientRepository; 

    public ClientService(IClientRepository rep) 
    { 
     m_clientRepository = rep; 
    } 
} 

然後你就可以用模擬轉來測試該代碼使用類似Moq的類IClientRepository。當然,如果您要編寫其他IClientRepository(例如,XmlClientRepository),您只會更改使用存儲庫的類的初始化。

如果你使用ASP.NET MVC,你將能夠在你的控制器中使用IClientRepository,它將更具可測性。

如需更多易於理解的解決方案,您可以使用IoC容器模式(NInject,Unity)。

我希望這個答案能幫到你。