我已经在我的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 ......我应该实现它还是我的存储库仍然可以改进......任何建议......
答案 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()
。命名非常差。对于您的存储库,尝试根据数据库端发生的情况对方法进行建模。试试Add
或Insert
,Delete
,FindAll
或GetAll
,Find
或GetAll
,SaveChanges
,方法名。
不要将类型附加/添加到方法名称中,因为您在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)。
我希望这个答案可以帮到你。