事情是这样的,前台网站有些数据不希望每次都从数据库里读,所以,应该做个缓存,而引起缓存更新的入口来自网站的后台管理,而前台和后台被部署在不同的网站中,这时缓存的更新就成了问题,前台的缓存与后台的操作不能联系到一起,为了解决这个问题,我引入了WCF作为中间件,所以与数据库的操作,读,写都来自一个入口,那就是WCF,WCF用户告诉你是否从缓存取数据,所有缓存的数据也缓存在WCF中,OK,想法不错,下面来说一下具体的实现步骤。
一 首先看一下结构图:
注意看我的结构图,前台aop_cache和后台aop_cache_background项目都引用aop_cache_webservice项目,而它们没有对数据层aop_cache_data的引用,这个aop_cache_webservice是一个WCF项目,主要实现与数据层的通讯工作,当然也可以与BLL业务层通讯,这个架构主要是讲如何实现前后台共享缓存,而并非讲架构,所以重要不再架构,而在实现共享缓存。
二 WCF层实现所需要的DLL,主要是unity,cache,interception,log4net等,如图:
三 对于unity,wcf,cache的调用上,我进行了二次封装,如图:
四 看了这些,我们再来看一下,WEB层调用WCF层的代码片断:
public ActionResult Index() { // 通过WCF获取远程数据,不走缓存, 走config中的<system.serviceModel> using (ServiceProxy<IService1> proxy = new ServiceProxy<IService1>()) { return View(proxy.Channel.GetClassroom_Info()); } }
web层的配置文件包含了对WCF的调用
<system.serviceModel> <bindings> <basicHttpBinding> <binding name="ServiceProxyBinding" sendTimeout="00:10:00" receiveTimeout="00:10:00" closeTimeout="00:10:00"></binding> </basicHttpBinding> </bindings> <client> <endpoint name="IService1" address="http://www.aop.com/Service1.svc" contract="aop_cache_WebService.IService1" binding="basicHttpBinding" bindingConfiguration="ServiceProxyBinding" /> </client> </system.serviceModel>
五 WCF层调用DAL层的代码,使用unity来做方法拦截与依赖注入,将cache功能注入到指定方法中
IClassroom_InfoRepository _iClassroom_InfoRepository = ServiceLocator.Instance.GetService<IClassroom_InfoRepository>(); public void InsertClassroom_Info(Classroom_Info entity) { _iClassroom_InfoRepository.InsertClassroom_InfoData(entity); } public List<Classroom_Info> GetClassroom_Info() { return _iClassroom_InfoRepository.GetClassroom_InfoData(); }
六 对于WCF的配置文件,我们要重要看一下,它包含了数据库连接串的配置和unity的配置
<configSections> <!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 --> <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" /> <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration" /> <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, log4net" /> <section name="cachingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Caching.Configuration.CacheManagerSettings, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" /> </configSections> <connectionStrings> <add name="DefaultConnection" providerName="System.Data.SqlClient" connectionString="Data Source=(LocalDb)\v11.0;Initial Catalog=aspnet-aop_cache-20131030092430;Integrated Security=SSPI;AttachDBFilename=|DataDirectory|\aspnet-aop_cache-20131030092430.mdf" /> <add name="TsingDa_NewLearningBarEntities" connectionString="metadata=res://*/Model1.csdl|res://*/Model1.ssdl|res://*/Model1.msl;provider=System.Data.SqlClient;provider connection string="data source=.;initial catalog=TsingDa_NewLearningBar;user id=sa;password=zzl123;MultipleActiveResultSets=True;App=EntityFramework"" providerName="System.Data.EntityClient" /> </connectionStrings> <!--BEGIN: Unity--> <unity xmlns="http://schemas.microsoft.com/practices/2010/unity"> <sectionExtension type="Microsoft.Practices.Unity.InterceptionExtension.Configuration.InterceptionConfigurationExtension, Microsoft.Practices.Unity.Interception.Configuration" /> <container> <extension type="Interception" /> <register type="Project.Caching.ICacheProvider, Project.Caching" mapTo="Project.Caching.EntLibCacheProvider, Project.Caching" /> <!--对WCF的访问进行的注入与缓存和异常的拦截--> <register type="aop_cache_Data.IClassroom_InfoRepository, aop_cache_Data" mapTo="aop_cache_Data.Classroom_InfoRepository, aop_cache_Data"> <interceptor type="InterfaceInterceptor" /> <interceptionBehavior type="Project.InterceptionBehaviors.CachingBehavior, Project.InterceptionBehaviors" /> </register> </container> </unity> <!--END: Unity--> <!--BEGIN: Caching--> <cachingConfiguration defaultCacheManager="ByteartRetailCacheManager"> <cacheManagers> <add name="ByteartRetailCacheManager" type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" expirationPollFrequencyInSeconds="600" maximumElementsInCacheBeforeScavenging="1000" numberToRemoveWhenScavenging="10" backingStoreName="NullBackingStore" /> <!-- expirationPollFrequencyInSeconds:过期时间(seconds) maximumElementsInCacheBeforeScavenging:缓冲中的最大元素数量 numberToRemoveWhenScavenging:一次移除的数量 --> </cacheManagers> <backingStores> <add type="Microsoft.Practices.EnterpriseLibrary.Caching.BackingStoreImplementations.NullBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.505.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" name="NullBackingStore" /> </backingStores> </cachingConfiguration> <!--END: Caching--> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Microsoft.Practices.Unity" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" /> </dependentAssembly> <dependentAssembly> <assemblyIdentity name="Microsoft.Practices.Unity.Interception" publicKeyToken="31bf3856ad364e35" culture="neutral" /> <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" /> </dependentAssembly> </assemblyBinding> </runtime> <system.diagnostics> <sources> <source name="System.ServiceModel" switchValue="Warning" propagateActivity="true"> <listeners> <add name="xml" /> </listeners> </source> </sources> <sharedListeners> <add name="xml" type="System.Diagnostics.XmlWriterTraceListener" initializeData="d:\wcf.svclog" /> </sharedListeners> </system.diagnostics> <system.serviceModel> <behaviors> <serviceBehaviors> <behavior> <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false --> <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/> <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 --> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors> <protocolMapping> <add binding="basicHttpsBinding" scheme="https" /> </protocolMapping> <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> </system.serviceModel>
七 DAL层的实现,由接口和实现两部分组成,接口的方法上规定了是否要进行cache操作
public interface IClassroom_InfoRepository { [Caching(CachingMethod.Remove, "GetClassroom_InfoData")] void InsertClassroom_InfoData(Classroom_Info entity); [Caching(CachingMethod.Get)] List<Classroom_Info> GetClassroom_InfoData(); }
实现很简单,只是一个测试而以
public class Classroom_InfoRepository : TsingDa_NewLearningBarRepository<Classroom_Info>, IClassroom_InfoRepository { public void InsertClassroom_InfoData(Classroom_Info entity) { base.Insert(entity); } public List<Classroom_Info> GetClassroom_InfoData() { return base.GetModel().ToList(); } }
本文转自博客园张占岭(仓储大叔)的博客,原文链接:DDD~WCF做中间件,实现多个项目的缓存共享,如需转载请自行联系原博主。