DDD~WCF做中間件(jian),實現多個項目的(de)緩存共享
事情是這樣(yang)的(de)(de)(de),前臺(tai)(tai)網(wang)(wang)站有些數據不希(xi)望每次都(dou)從數據庫里讀(du),所(suo)以,應該做個(ge)(ge)緩(huan)存,而(er)引起緩(huan)存更(geng)新的(de)(de)(de)入口來自網(wang)(wang)站的(de)(de)(de)后臺(tai)(tai)管(guan)理,而(er)前臺(tai)(tai)和后臺(tai)(tai)被(bei)部署在(zai)不同的(de)(de)(de)網(wang)(wang)站中,這時(shi)緩(huan)存的(de)(de)(de)更(geng)新就成了(le)問題,前臺(tai)(tai)的(de)(de)(de)緩(huan)存與(yu)后臺(tai)(tai)的(de)(de)(de)操(cao)作(zuo)(zuo)不能聯系到一起,為了(le)解決這個(ge)(ge)問題,我引入了(le)WCF作(zuo)(zuo)為中間件(jian),所(suo)以與(yu)數據庫的(de)(de)(de)操(cao)作(zuo)(zuo),讀(du),寫都(dou)來自一個(ge)(ge)入口,那就是WCF,WCF用戶告(gao)訴你是否(fou)從緩(huan)存取數據,所(suo)有緩(huan)存的(de)(de)(de)數據也緩(huan)存在(zai)WCF中,OK,想法不錯,下面來說一下具體的(de)(de)(de)實現(xian)步驟(zou)。
一(yi) 首(shou)先看一(yi)下結(jie)構圖:
注意看我的結構圖,前(qian)臺aop_cache和后(hou)(hou)臺aop_cache_background項目(mu)都引用(yong)(yong)aop_cache_webservice項目(mu),而(er)它們沒有對數據層aop_cache_data的引用(yong)(yong),這個aop_cache_webservice是(shi)一個WCF項目(mu),主要實(shi)(shi)現(xian)與數據層的通訊工作,當然也可以(yi)與BLL業務層通訊,這個架(jia)構主要是(shi)講(jiang)如(ru)何實(shi)(shi)現(xian)前(qian)后(hou)(hou)臺共享緩存,而(er)并非講(jiang)架(jia)構,所(suo)以(yi)重要不再架(jia)構,而(er)在實(shi)(shi)現(xian)共享緩存。
二(er) WCF層實(shi)現(xian)所(suo)需要的DLL,主要是unity,cache,interception,log4net等,如圖(tu):
三 對于(yu)unity,wcf,cache的(de)調用上(shang),我進行了二(er)次封(feng)裝,如圖:
四 看了這些,我們再來看一(yi)下,WEB層(ceng)調用WCF層(ceng)的代碼(ma)片斷:
public ActionResult Index() { // 通過WCF獲取遠程數據,不走(zou)緩(huan)存, 走(zou)config中的<system.serviceModel> using (ServiceProxy<IService1> proxy = new ServiceProxy<IService1>()) { return View(proxy.Channel.GetClassroom_Info()); } }
web層的(de)配(pei)置文件包含了對WCF的(de)調用(yong)
<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="//www.aop.com/Service1.svc" contract="aop_cache_WebService.IService1" binding="basicHttpBinding" bindingConfiguration="ServiceProxyBinding" />
</client>
</system.serviceModel>
五 WCF層(ceng)(ceng)調用DAL層(ceng)(ceng)的代(dai)碼,使用unity來做方(fang)法(fa)攔截與依賴注入,將(jiang)cache功能注入到指定方(fang)法(fa)中(zhong)
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的(de)配置文件,我們要重(zhong)要看(kan)一下,它包含了(le)數據庫(ku)連接(jie)串的(de)配置和unity的(de)配置
<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="//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:過期時(shi)間(seconds)
maximumElementsInCacheBeforeScavenging:緩沖中(zhong)的最大(da)元素數(shu)量
numberToRemoveWhenScavenging:一次移除的數(shu)量
-->
</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>
七(qi) DAL層的實現(xian),由接(jie)口(kou)和實現(xian)兩(liang)部(bu)分組成,接(jie)口(kou)的方法上規定(ding)了是(shi)否要(yao)進行cache操作
public interface IClassroom_InfoRepository { [Caching(CachingMethod.Remove, "GetClassroom_InfoData")] void InsertClassroom_InfoData(Classroom_Info entity); [Caching(CachingMethod.Get)] List<Classroom_Info> GetClassroom_InfoData(); }
實(shi)現很(hen)簡單,只是(shi)一(yi)個測(ce)試(shi)而以
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(); } }