Max*_*Max 5 c# architecture asp.net-mvc
在我目前的一个应用程序中,我需要通过Webservice/SOAP从远程服务(CRM)获取客户数据.但是我也希望将数据缓存在mysql数据库中,以便我下次不需要连接到webservice(数据不会经常更改,远程服务很慢并且有带宽限制 - 因此缓存可以/必须).
我非常确定这项任务的技术部分,但我不太确定如何在我的网络应用程序中实现这种干净透明.
我的所有其他数据都来自一个mysql数据库,因此我使用NHibernate从数据库中查询返回列表或单个实体的存储库.
我的想法到目前为止:
1合一
使用CustomerRepository,它通过Id查找客户,如果成功,则返回它,否则调用webservice并将检索到的数据保存到数据库.
控制器看起来像这样:
class Controller
{
private CustomerRepository Rep;
public ActionResult SomeAction(int id)
{
return Json(Rep.GetCustomerById(id));
}
}
Run Code Online (Sandbox Code Playgroud)
伪/简单代码中的存储库如下:
class CustomerRepository
{
public Customer GetCustomerById(int id)
{
var cached = Database.FindByPK(id);
if(cached != null) return cached;
var webserviceData = Webservice.GetData(id);
var customer = ConvertDataToCustomer(webserviceData);
SaveCustomer(customer);
return customer;
}
}
Run Code Online (Sandbox Code Playgroud)
虽然上面看起来有些简单,但我认为CustomerRepository类会变得非常庞大和丑陋.所以我根本不喜欢这种方法.
存储库应该只加载数据库中的数据,至少应该是我应用程序中的"合同".
2在控制器中分离并粘在一起
对存储库(db访问)和webservice(远程访问)使用单独的类,让控制器完成工作:
控制器看起来像这样:
class Controller
{
private CustomerRepository Rep;
private Webservice Service;
public ActionResult SomeAction(int id)
{
var customer = Rep.GetCustomerById(id);
if(customer != null) return Json(customer);
var remote = Service.GetCustomerById(id);
Rep.SaveCustomer(remote);
return Json(remote);
}
}
Run Code Online (Sandbox Code Playgroud)
虽然这看起来好一点,但我仍然不喜欢将所有逻辑放在控制器中,因为如果服务不返回数据的错误处理被省略,并且可能会使事情更加混乱.
也许我可以创建Controller使用的另一个服务层,但代码将完全相同,但在另一个类中.
实际上我想让我的Controller使用一个接口/类,它封装了那些东西,但我不想要一个"完成所有"的类:访问存储库,访问web服务,保存数据......感觉有点对我不对......
到目前为止,所有的想法都可能会变得非常臃肿,包括缓存代码,错误处理等等.我想.
也许我可以使用AOP清理一些东西?
将如何你实现的东西,如上面?
使用的技术框架:ASP.NET MVC,用于DI的Spring.NET,用作ORM的NHibernate,用作数据库的mysql,通过SOAP访问远程服务.
您可以使用Decorator模式干净地实现您的体系结构.
让我们假设您有一个名为ICustomerRepository的接口.
您首先基于Web服务实现ICustomerRepository(让我们称之为WsCustomerRepository),并且在此实现中根本不用担心数据库.
然后,您实现另一个只与您的数据库进行通信的ICustomerRepository(MySqlRepository).
最后,创建第三个ICustomerRepository(CachingRepository),它实现您描述的缓存逻辑.它首先查询"本地"存储库,但如果它没有从中获得结果,它将查询"远程"存储库并在返回结果之前将结果插入"本地"存储库.
您的CachingRepository可能如下所示:
public class CachingRepository : ICustomerRepository
{
private readonly ICustomerRepository remoteRep;
private readonly ICustomerRepository localRep;
public CachingRepository(ICustomerRepository remoteRep, ICustomerRepository localRep)
{
this.remoteRep = remoteRep;
this.localRep = localRep;
}
// implement ICustomerRepository...
}
Run Code Online (Sandbox Code Playgroud)
正如您所看到的,CachingRepository甚至不需要了解具体的Web服务和数据库,但可以专注于其单一职责:缓存
这使您可以清楚地分离责任,就控制器而言,它们只与ICustomerRepository实例通信.
| 归档时间: |
|
| 查看次数: |
838 次 |
| 最近记录: |