asp.net mvc的良好存储库模式

时间:2010-07-19 04:00:15

标签: asp.net-mvc repository-pattern

我已经在我的asp.net mvc web应用程序中实现了一个存储库模式......但我想知道这是一个很好的存储库模式还是我还能改进它...

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 ......我应该实现它还是我的存储库仍然可以改进......任何建议......

2 个答案:

答案 0 :(得分:15)

嗯,我肯定会采取一些措施来改善这一点。

首先:我将为您的存储库定义一个接口来实现。这允许您更好地控制依赖性,并且当与控制/依赖性注入反转(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()。命名非常差。对于您的存储库,尝试根据数据库端发生的情况对方法进行建模。试试AddInsertDeleteFindAllGetAllFindGetAllSaveChanges,方法名。

不要将类型附加/添加到方法名称中,因为您在ClientRepository中,这意味着您将添加或获取Client

第四:您混合使用LINQ语法。在某些地方,您使用声明性查询语法,而其他地方使用方法语法。选择1并在任何地方使用它。

第五:这条线让我担心:

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

对我而言,这看起来很像商业逻辑。不是应该在存储库中的东西。在数据库中声明列为UNIQUE,或将该逻辑移动到另一个验证层。

这些是我跳出来的主要事情。其中一些是个人偏好,但我希望这会有所帮助。

答案 1 :(得分:1)

为什么使用字符串作为Id的数组:

public bool deleteClients(string Ids, int userId)

我认为您应该使用int[]List<int>

我也会在FindAllClients中编写List而不是IQueryable。

public List<ClientBO> FindAllClients(int userId)

当然你应该编写接口IClientRepository,因为它是根据SOLID原则的正确方法。

如果你要编写接口,那么你可以更灵活地编写其他使用Repository和这个接口的类,如下所示:

public class ClientService : IClientService
{
    IClientRepository m_clientRepository;

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

然后,您将能够使用类似Moq的Mock-class IClientRepository来测试此代码。当然,如果您要编写其他IClientRepository(例如,XmlClientRepository),您只会更改使用存储库的类的初始化。

如果您使用ASP.NET MVC,您将能够在控制器中使用IClientRepository,并且它将更易于测试。

对于更灵活的解决方案,您可以使用IoC容器模式(NInject,Unity)。

我希望这个答案可以帮到你。