在前面的企业库学习之路里我分别使用了Data Access构建多数据库访问和使用Exception Handle+Logging记录系统的异常。今天我来介绍下企业库中的Caching模块在本项目中如何应用。 首先先补习下企业库的Caching Application Block的相关知识: 1、四大缓存方式,在Caching Application Block中,主要提供以下四种保存缓存数据的途径,分别是:内存存储(默认)、独立存储(Isolated Storage)、数据库存储(DataBase Cache Storage)和自定义存储(Custom Cache Storage)。 2、多种存储方式,抛开自定义存储不谈,内存存储是最基本的缓存,仅仅是将数据缓存到内存当中,虽然速度快但是无法进行持久化存储,而独立存储和数据库存储一个是存储到本地的磁盘中(视操作系统不同存储到不同的位置)而另一个则是存储到数据库中(方便进行分布式缓存),所以可以进行持久化保存不会因为关机而丢失(可以到。在EntLib50Src\Blocks\Caching\Src\Database\Scripts下找到脚本进行安装) 3、优秀的易用性,虽然在.NET类库System.Web中已经提供了Cache类,但是有局限性,仅可适用于控制台、Winform、Web、服务等。 4、安全性,企业库中的缓存模块可以和加密模块很好的结合起来,当适用数据库缓存、独立存储或者自定义存储的时候可以适用加密模块对缓存的数据进行加密,但存储到内存当中的数据就无法进行加密了。 在了解了缓存的基本知识后我们就可以开始进行具体的操作了。 我现在就是使用Cache模块为项目中反射具体数据库DAL层对象实例进行缓存,这样不用每次在调用底层的时候都反射一次,只需在第1次反射后缓存,以后的访问直接从缓存中读取,提高了访问的速度。 通过企业库配置工具添加个Caching Settings 这里使用默认设置,保存到内存中,过期轮询时间,最大存储数量和移除数量都使用了默认的设置。 如果不想使用默认的内存存储可以建立独立存储或者数据库存储。 这里有个要提的就是企业库的缓存模块的数据库存储是使用存储过程来进行缓存与数据库之间的交互,但是本项目中使用了多数据库,如Sqlite,就无法支持存储过程,所以这边需要自定义存储方式,可以直接查看企业库代码中Cache.DataBase.DataBackingStore.cs类,仿照DataBackingStore类自定义一个存储方式,只不过在进行数据库交互的时候使用SQL语句进行。 继续回到主题上,我这边写了一个简单的CacheHelper,用以操作缓存,其中我自定义了一个缓存刷新操作类(此类必须为可序列化),用于将已经过期的对象重新加入到缓存当中,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
using System; using System.Collections.Generic; using System.Linq; using System.Text; using Microsoft.Practices.EnterpriseLibrary.Caching; using Microsoft.Practices.EnterpriseLibrary.Caching.Expirations; using Microsoft.Practices.EnterpriseLibrary.Common.Configuration; namespace EntLibStudy.Helper { public static class CacheHelper { //2种建立CacheManager的方式 //ICacheManager cache = EnterpriseLibraryContainer.Current.GetInstance<ICacheManager>(); private static ICacheManager cache = CacheFactory.GetCacheManager(); /// <summary> /// 添加缓存 /// </summary> /// <param name="key">键</param> /// <param name="value">值</param> /// <param name="isRefresh">是否刷新</param> public static void Add(string key, object value, bool isRefresh = false) { if (isRefresh) { //自定义刷新方式,如果过期将自动重新加载,过期时间为5分钟 cache.Add(key, value, CacheItemPriority.Normal, new MyCacheItemRefreshAction(), new AbsoluteTime(TimeSpan.FromMinutes(5))); } else { cache.Add(key, value); } } /// <summary> /// 获取缓存对象 /// </summary> /// <param name="key">键</param> /// <returns></returns> public static object GetCache(string key) { return cache.GetData(key); } /// <summary> /// 移除缓存对象 /// </summary> /// <param name="key">键</param> public static void RemoveCache(string key) { cache.Remove(key); } } /// <summary> /// 自定义缓存刷新操作 /// </summary> [Serializable] public class MyCacheItemRefreshAction : ICacheItemRefreshAction { #region ICacheItemRefreshAction 成员 /// <summary> /// 自定义刷新操作 /// </summary> /// <param name="removedKey">移除的键</param> /// <param name="expiredValue">过期的值</param> /// <param name="removalReason">移除理由</param> void ICacheItemRefreshAction.Refresh(string removedKey, object expiredValue, CacheItemRemovedReason removalReason) { if (removalReason == CacheItemRemovedReason.Expired) { ICacheManager cache = CacheFactory.GetCacheManager(); cache.Add(removedKey, expiredValue); } } #endregion } } |
1、缓存等级,在企业库的缓存模块中已经提供了4个缓存等级:Low,Normal,High和NotRemovable,在超出最大缓存数量后会自动根据缓存等级来移除对象。 2、ICacheItemRefreshAction,这个接口用来方便开发人员扩展使用的,开发人员可以根据移除原因在对象过期后进行相应的操作,其中CacheItemRemovedReason分 Expired:过期被移除 Removed:被手动移除 Scavenged:因为缓存数量已满,则根据缓存等级移除较低级的缓存 Unknown:未知移除,不建议使用 3、过期方式,企业库默认提供4种过期方式 AbsoluteTime:绝对是时间过期,传递一个时间对象指定到时过期 SlidingTime:缓存在最后一次访问之后多少时间后过期,默认为2分钟,有2个构造函数可以指定一个过期时间或指定一个过期时间和一个最后使用时间
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public SlidingTime(TimeSpan slidingExpiration) { // Check that expiration is a valid numeric value if (!(slidingExpiration.TotalSeconds >= 1)) { throw new ArgumentOutOfRangeException("slidingExpiration", Resources.ExceptionRangeSlidingExpiration); } this.itemSlidingExpiration = slidingExpiration; } public SlidingTime(TimeSpan slidingExpiration, DateTime originalTimeStamp) : this(slidingExpiration) { timeLastUsed = originalTimeStamp; } |
ExtendedFormatTime :指定过期格式,以特定的格式来过期,通过ExtendedFormat.cs类来包装过期方式,具体可参照ExtendedFormat.cs,源代码中已经给出了很多方式 FileDependency:依赖于文件过期,当所依赖的文件被修改则过期,这个我觉得很有用,因为在许多网站,如论坛、新闻系统等都需要大量的配置,可以将配置文件信息进行缓存,将依赖项设为配置文件,这样当用户更改了配置文件后通过ICacheItemRefreshAction.Refresh可以自动重新缓存。 在介绍了Cache的相关参数后我们来看下具体如何使用,我这边将原来的DataAccess类重新修改了一下,因为觉得如果每次多增加一个数据表,对应的工厂就需要多写一个反射方法实在是不方便,所以修改成泛型类(同时附了原来的反射代码,可以对比下那种方式比较好),在BLL层调用的时候只需传递要转成的接口即可,代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
public static class DataAccess<T> { private static readonly string assemblyString = ConfigurationManager.AppSettings["DAL"]; /// <summary> /// 通用对象反射(包含缓存) /// </summary> /// <param name="className">要反射的类名</param> /// <returns></returns> public static T CreateObject(string className) { var typeName = assemblyString + "." + className; //判断对象是否被缓存,如果已经缓存则直接从缓存中读取,反之则直接反射并缓存 var obj = (T)CacheHelper.GetCache(typeName); if (obj == null) { obj = (T)Assembly.Load(assemblyString).CreateInstance(typeName, true); CacheHelper.Add(typeName, obj, true); } return obj; } public static IClassInfoService CreateClassInfo() { string typeName = assemblyString + ".ClassInfoService"; //判断对象是否被缓存,如果已经缓存则直接从缓存中读取,反之则直接反射并缓存 if (CacheHelper.GetCache(typeName) != null) { return (IClassInfoService)CacheHelper.GetCache(typeName); } else { IClassInfoService service = (IClassInfoService)Assembly.Load(assemblyString).CreateInstance(typeName, true); CacheHelper.Add(typeName, service, true); return service; } } |
BLL层调用代码如下:
1 |
private IClassInfoService classInfoService = DataAccess<IClassInfoService>.CreateObject("ClassInfoService"); |
需要注意的是由于使用企业库的Cache,如果缓存到数据库或者独立存储必须要求缓存对象必须是可序列化的,内存中缓存就不需要,而我这边缓存的对象为DAL层中具体的操作类,所以如果要更改为非内存存储需要将操作类加上[Serializable]特性。 这样以后再添加新的表就无需修改工厂中的DataAccess类了。 以上就是缓存在本项目中的一些基本应用,由于水平有限,所以暂时无法提出缓存的一些高级应用,请大家见谅。 相关Cache模块配置可以查看huangcong写的Cache模块(初级),一些相关知识可以查看virusswb写的缓存的设计目的。 注意: 1、MSSQL数据库在DataBase目录下(需要自行附加数据库),SQLite数据库在Web目录的App_Data下,由于考虑到项目的大小,所以每个项目的BIN目录都已经删除,如出现无法生成项目请自行添加相关企业库的DLL。 2、由于微软企业库5.0 学习之路这个系列我是准备以一个小型项目的形式介绍企业库的各模块,所以源代码会根据系列文章的更新而更新,所以源代码不能保证与文章中所贴代码相同。 3、项目开发环境为:VS2010+SQL2005。 4、管理员帐户:admin 密码:admin 源代码下载地址:点我下载 转自:http://www.cnblogs.com/kyo-yo/archive/2010/06/24/Learning-EntLib-Forth-Use-Caching.html
View Details在前一篇文章:[EntLib]微软企业库5.0 学习之路——第二步、使用VS2010+Data Access模块建立多数据库项目中我们搭建好了项目的整体多数据库环境,实现了项目的多数据库访问,而整个项目中最主要的异常处理却没有进行部署,今天我们就使用企业库中的Exception Handling+Logging模块为项目加上异常处理以及异常日志记录。 (注:关于Exception Handling和Logging模块的相关基本概念可以查看TerryLee的异常处理和日志检测这2篇文章) 首先说一下企业库Logging模块的个人感觉,个人感觉企业库的日志记录太繁琐了,而且要自定义也比较烦,无法通过简单的配置达到我自己的要求,企业库中的日志记录模块在可以记录许多信息如下: Timestamp: 2010-6-12 3:16:39 Message: HandlingInstanceID: 669fed01-a758-434b-896e-a8e25ebf8c9b An exception of type 'System.Exception' occurred and was caught. —————————————————————- 06/12/2010 11:16:39 Type : System.Exception, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 Message : Test Source : EntLibStudy.Helper Help link : Data : System.Collections.ListDictionaryInternal TargetSite : System.String Test() Stack Trace : 在 EntLibStudy.Helper.BasePage.Test() 位置 F:\EntLibStudy\Helper\BasePage.cs:行号 87 在 EntLibStudy.Helper.BasePage.<Page_Load>b__0() 位置 F:\EntLibStudy\Helper\BasePage.cs:行号 81 在 Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.ExceptionManagerImpl.Process[TResult](Func`1 action, TResult defaultResult, String policyName) 位置 以下省略N行。。。。。。 这些信息很多都不是我想要的,我想要的仅仅是异常的提示信息,异常发生的时间,以及异常发生的位置,好方便我们第一时间到异常发生的源头进行调试检查(可能企业库的这些异常信息更加有用,但是我个人认为很多时候都会干扰我们),所以我们仅仅需要其中的几条有用的信息就够了,比如Message,Timestamp、Stack Trace和Severity这4个就基本上够用了,所以我做了个处理,就是使用企业库中Logging模块提供的自定义CustomerTraceListener来实现我们需要的功能。 首先建立一个异常日志记录表(SQLite版)
1 2 3 4 5 6 7 |
CREATE TABLE [ExceptionLog] ( [Id] integer PRIMARY KEY AUTOINCREMENT NOT NULL, [Message] nvarchar(1024) NOT NULL, [LogDate] nvarchar(1024) NOT NULL, [ExceptionLevel] nvarchar(32) NOT NULL, [Exception] ntext NOT NULL ) |
我编写了一个类继承自CustomTraceListener,并重写了记录方法,具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
using System; using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Diagnostics; using System.Globalization; using System.Linq; using System.Text; using Microsoft.Practices.EnterpriseLibrary.Common.Configuration; using Microsoft.Practices.EnterpriseLibrary.Data; using Microsoft.Practices.EnterpriseLibrary.Logging; using Microsoft.Practices.EnterpriseLibrary.Logging.Configuration; using Microsoft.Practices.EnterpriseLibrary.Logging.Formatters; using Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners; namespace EntLibStudy.Helper.EntLibExtension.ExceptionExtension { [ConfigurationElementType(typeof(CustomTraceListenerData))] public class ExceptionCustomerListener : CustomTraceListener { string writeLogSQL = String.Empty; Database database; Exception ex; public ExceptionCustomerListener() : base() { database = DBHelper.CreateDataBase(); } public override void TraceData(TraceEventCache eventCache, string source, TraceEventType eventType, int id, object data) { if ((this.Filter == null) || this.Filter.ShouldTrace(eventCache, source, eventType, id, null, null, data, null)) { if (data is LogEntry) { LogEntry logEntry = data as LogEntry; ExecuteSQL(logEntry); } else if (data is string) { Write(data as string); } else { base.TraceData(eventCache, source, eventType, id, data); } } } public override void Write(string message) { ExecuteWriteLogSQL(TraceEventType.Information, DateTime.Now, message, database); } public override void WriteLine(string message) { Write(message); } /// <summary> ///执行SQL /// </summary> /// <param name="logEntry">日志对象</param> private void ExecuteSQL(LogEntry logEntry) { using (DbConnection connection = database.CreateConnection()) { try { connection.Open(); using (DbTransaction transaction = connection.BeginTransaction()) { try { ExecuteWriteLogSQL(logEntry, database, transaction); transaction.Commit(); } catch { transaction.Rollback(); throw; } } } finally { connection.Close(); } } } /// <summary> /// 执行写入日志数据库语句 /// </summary> /// <param name="severity">异常等级</param> /// <param name="message">消息</param> /// <param name="db">保存日志的数据库实例</param> private void ExecuteWriteLogSQL(TraceEventType severity, DateTime timeStamp, string message, Database db) { writeLogSQL = (string)this.Attributes["writeLogSQL"]; DbCommand cmd = db.GetSqlStringCommand(writeLogSQL); string exceptionMessage = Utils.GetBetweenString(message, "Message :", "Source :", 9); string exceptionInfo = Utils.GetBetweenString(message, "Stack Trace :", "Additional Info:", 13); db.AddInParameter(cmd, "@Message", DbType.String, exceptionMessage); db.AddInParameter(cmd, "@LogDate", DbType.DateTime, timeStamp); db.AddInParameter(cmd, "@Level", DbType.String, message); db.AddInParameter(cmd, "@Exception", DbType.String, exceptionInfo); db.ExecuteNonQuery(cmd); } /// <summary> /// 执行写入日志数据库语句 /// </summary> /// <param name="logEntry">日志对象</param> /// <param name="db">保存日志的数据库实例</param> /// <param name="transaction">事务对象</param> private void ExecuteWriteLogSQL(LogEntry logEntry, Database db, DbTransaction transaction) { writeLogSQL = (string)this.Attributes["writeLogSQL"]; DbCommand cmd = db.GetSqlStringCommand(writeLogSQL); string exceptionMessage = Utils.GetBetweenString(logEntry.Message, "Message :", "Source :", 9); string exceptionInfo = Utils.GetBetweenString(logEntry.Message, "Stack Trace :", "Additional Info:", 13); db.AddInParameter(cmd, "@Message", DbType.String, exceptionMessage); db.AddInParameter(cmd, "@LogDate", DbType.DateTime, logEntry.TimeStamp.ToLocalTime()); db.AddInParameter(cmd, "@Level", DbType.String, logEntry.LoggedSeverity); db.AddInParameter(cmd, "@Exception", DbType.String, exceptionInfo); db.ExecuteNonQuery(cmd, transaction); } } } |
其中在类的初始化的时候获取配置文件的默认数据库对象,通过重写TraceData方法来调用ExecuteSQL方法来执行异常日志插入。 在ExecuteWriteLogSQL方法中有句代码:
1 |
writeLogSQL = (string)this.Attributes["writeLogSQL"]; |
这个代码就是从配置文件中Listener的Attributes中获取所配置的执行SQL语句(这里不同于Logging模块自带的数据库以存储过程的记录方式,而是使用配置的SQL语句的方式,因为本项目是面向多数据库的,并不是所有的数据库都有存储过程的,比如SQLite),下面看下具体的配置信息: 配置文件创建主要分为以下2步: 1、在企业库的配置工具添加一个Exception Handle模块,然后添加一个名为Exception Policy的策略,再为这个策略添加异常类型,默认我选择所有异常类型(All Exceptions),Post Handle Action为: NotifyRethow(对不理解Post Handle Action的处理方式的可以看下下面的解释) PostHandlingAction 决定了在异常处理链完成后将发生什么活动。默认情况下,PostHandlingAction 被设置为 NotifyRethrow 。 None:应用程序块为此异常执行所有的处理程序,然后在 HandleException 方法的调用点上返回 false 给应用程序。应用程序检查此值以继续运行。 NotifyRethrow:应用程序块为此异常执行所有的处理程序,然后在 HandleException 方法的调用点上返回 true 给应用程序。应用程序检查到此值就重新抛出原始异常。 ThrowNewException:应用程序块为此异常执行所有的处理程序,然后在所有处理程序运行后抛出存在的异常。 2、为异常策略创建处理方式,我这边选择Loggin Exception Handler(在创建的同时配置工具会我们自动创建好Logging模块,并自动创建了一个日志分类:General,不过这个日志分类的默认Listener为event log,就是记录到系统的事件中),这时我们再创建一个CustomerTraceListener选择From File->自定义Listener所在DLL。 这边我碰到了一个问题就是添加了CustomerTraceListener,在对话框中我点击From File选择我编写的自定义Listener所在DLL,可惜没任何反应,不知道是不是要在DLL中做什么处理,所以我只能采用老办法:手写配置文件 首先看下Exception Handle模块的配置信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<exceptionHandling> <exceptionPolicies> <add name="ExceptionPolicy"> <exceptionTypes> <add name="All Exceptions" type="System.Exception, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" postHandlingAction="NotifyRethrow"> <exceptionHandlers> <add name="Logging Exception Handler" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.LoggingExceptionHandler, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" logCategory="General" eventId="100" severity="Error" title="Enterprise Library Exception Handling" formatterType="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.TextExceptionFormatter, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling" priority="0" /> </exceptionHandlers> </add> </exceptionTypes> </add> </exceptionPolicies> </exceptionHandling> |
接下来是日志模块配置,在日志模块下我配置了3个Listener,其中Custom Trace Listener为我自定义的异常日志记录,Event Log Listener(系统日志记录)和Rolling Flat File Trace Listener(文本文件记录,按天回滚记录)为在日志分类General无法正常记录日志时的记录下日志分类General为何无法记录,因为异常日志默认保存到数据库中,但是如果数据库中存在问题,或者链接被关闭这时就无法正常记录异常,所以:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<loggingConfiguration name="" tracingEnabled="true" defaultCategory="General"> <listeners> <add listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.CustomTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging" writeLogSQL="insert into ExceptionLog(Message,LogDate,ExceptionLevel,Exception) values(@Message,@LogDate,@Level,@Exception)" type="EntLibStudy.Helper.EntLibExtension.ExceptionExtension.ExceptionCustomerListener, EntLibStudy.Helper, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" traceOutputOptions="None" name="Custom Trace Listener" initializeData="" formatter="Text Formatter" /> <add name="Event Log Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FormattedEventLogTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FormattedEventLogTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" source="Enterprise Library Logging" formatter="Text Formatter" log="" machineName="." traceOutputOptions="None" /> <add name="Rolling Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.RollingFlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.RollingFlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" fileName="rolling.log" formatter="Text Formatter" rollInterval="Day" /> </listeners> <formatters> <add type="Microsoft.Practices.EnterpriseLibrary.Logging.Formatters.TextFormatter, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" template="Timestamp: {timestamp}{newline}&#xA;Message: {message}{newline}&#xA;Category: {category}{newline}&#xA;Priority: {priority}{newline}&#xA;EventId: {eventid}{newline}&#xA;Severity: {severity}{newline}&#xA;Title:{title}{newline}&#xA;Machine: {localMachine}{newline}&#xA;App Domain: {localAppDomain}{newline}&#xA;ProcessId: {localProcessId}{newline}&#xA;Process Name: {localProcessName}{newline}&#xA;Thread Name: {threadName}{newline}&#xA;Win32 ThreadId:{win32ThreadId}{newline}&#xA;Extended Properties: {dictionary({key} - {value}{newline})}" name="Text Formatter" /> </formatters> <categorySources> <add switchValue="All" name="General"> <listeners> <add name="Custom Trace Listener" /> </listeners> </add> </categorySources> <specialSources> <allEvents switchValue="All" name="All Events" /> <notProcessed switchValue="All" name="Unprocessed Category" /> <errors switchValue="All" name="Logging Errors &amp; Warnings"> <listeners> <add name="Event Log Listener" /> <add name="Rolling Flat File Trace Listener" /> </listeners> </errors> </specialSources> </loggingConfiguration> |
在配置完后我们就可以进行代码编写,在页面里进行异常控制。 在ASP.NET中,异常处理主要有4种,执行顺序为:Page_Error事件>ErrorPage属性>Application_Error事件> <customErrors>,我这边采用Page_Error,由于在本项目中我已经建立了BasePage,所有的页面都继承这个页面,所以我只需在这个页面中编写Page_Error事件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
protected void Page_Error(object sender, EventArgs e) { //获取最新的异常信息 var ex = Server.GetLastError(); //处理异常 HandleException(ex, "ExceptionPolicy"); //清空异常 Server.ClearError(); } /// <summary> /// 异常处理方法 /// </summary> /// <param name="ex">异常信息</param> /// <param name="policy">异常处理策略</param> protected void HandleException(Exception ex, string policy) { bool rethrow = false; var exManager = EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>(); rethrow = exManager.HandleException(ex, policy); if (rethrow) { this.RedirectPermanent("~/error.aspx"); } } |
其中exManager.HandleException(ex, policy)为根据策略名处理异常,我这边使用的ExceptionPolicy,这个策略的处理方式为异常日志记录,它会帮我们调用到我们自定义的ExceptionCustomerListener 类,进行异常日志记录。 这样我们就完成了统一捕获系统中发生的异常了,本文也到此结束,欢迎大家指点! ——————————--文章扩展分割线———————————————-- 当然企业库中的Exception Handle和Logging模块远不止这些,Exception Handle还提供了异常替换(将指定的异常替换成其他的异常信息),异常包装(将一个异常包装到另外一个异常当中) Logging模块提供了许多的记录方式,如文本,XML,邮件,消息队列等等,所以我们可以根据我们的需求自由的选择。 本文仅仅就我的实际项目需求进行了简单的扩展,所以可能还有许多的不足,大家可根据自己的需求进行研究扩展,如果大家有好的异常记录处理办法可以提出来让我借鉴下。:) PS:我在文中提到了企业库的Logging模块太繁琐,大家可以看下我的使用log4net完成程序异常日志记录(使用SQLite数据库记录和普通文本记录)这篇文章,如果仅仅是要进行系统的异常记录的话log4net是个不错的选择,配置又方便而且也轻便,单若想完整使用企业库的功能的话就还是使用Exception Handle+Logging这个组合了。 注意: 1、MSSQL数据库在DataBase目录下(需要自行附加数据库),SQLite数据库在Web目录的App_Data下,由于考虑到项目的大小,所以每个项目的BIN目录都已经删除,如出现无法生成项目请自行添加相关企业库的DLL。 2、由于微软企业库5.0 学习之路这个系列我是准备以一个小型项目的形式介绍企业库的各模块,所以源代码会根据系列文章的更新而更新,所以源代码不能保证与文章中所贴代码相同。 3、项目开发环境为:VS2010+SQL2005。 4、管理员帐户:admin 密码:admin 源代码下载地址:点我下载 转自:http://www.cnblogs.com/kyo-yo/archive/2010/06/17/Learning-EntLib-Third.html
View Details在通过上一篇文章:[EntLib]微软企业库5.0 学习之路——第一步、基本入门 对EntLib5.0的相关知识进行了了解,并通过微软给出的学习例子我们可以了解企业库的各模块的基本用法(由于园子里的好几位兄弟都已经把企业库的各模块的使用都介绍过了,所以我这边就不进行具体功能的介绍,我写的学习之路是以企业库如何在一个项目中的使用为基础来介绍,以一个简单的学生信息管理系统项目为基础,如何使用企业库来对这个项目进行开发、优化)。 (本文内容比较简单,高手们可以直接忽略不看了,仅仅就是数据库访问操作和工厂分层) 现在我就开始进入学习之路的第二步——Data Access模块,这个模块是企业库中被使用频率最高的模块,它很好的封装了数据库操作应用,为我们进行多数据库系统开发提供了便利,只需更改配置文件就可以很快的切换数据库访问(可惜还是要重写SQL语句,没法和ORM比)。 下面是我在配置企业库的时候碰到问题,如果没有碰到可以略去不看(可能有点小白) 注意:此处切换数据库配置必须是计算机中已经安装好相应的数据库访问模块,如需要进行从MS SQL向SQLite数据库的变更时,计算机中必须安装好SQLite数据库访问模块(在这里我就碰到了这个问题,原来我机器上在VS2008开发时已经安装过SQLite数据库访问模块,但是新装了VS2010,在VS2010引用对话框中也能访问到在VS2008安装的SQLite(但是在企业库5.0配置器中无法查看到SQLite),但是发现更改企业库的配置文件后无法访问SQLite数据库,尝试了很多方法都没用,结果死马当活马医又重新装了一遍SQLite数据库访问模块再重新打开企业库配置器就可以看到SQLite数据库了(所以请确保在企业库编辑器中可以查看到要切换的数据库,否则可能导致无法访问数据库)。看下图: 回归正题,这次的学习由于VS2010发布了,而且企业库5.0也都支持.NET4.0,所以决定企业库的学习之路采用VS2010进行学习(顺便熟悉下.NET4的特性,毕竟公司的项目不可能立马转移到.NET4.0的,现在就当练手吧) 好了,现在就开始进行第2步的学习了,首先看下项目的结构: 项目采用仿MS PetShop架构,如不了解此架构可以到此查看了解:PetShop的系统架构设计 其中DAL和DALSQLite层对应MS SQL和SQLite数据库,Helper为整个项目的帮助器 现在来具体了解下DAL层 在DAL层中引用了Helper,IDAL,EnterpriseLibrary.Common和EnterpriseLibrary.Data这4个项目,其中Helper项目中有个DBHelper.cs,用于获取当前的数据对象,其代码如下(采用了C#4.0的语法特性,默认参数,数据库对象名默认为空,这样则会调用企业库默认的数据库对象,同时也可以在调用的时候赋值,这样则根据传递过来的数据库对象名来创建数据库,通过这个参数我们将原来需要重载的2个方法才能实现合并成了一个方法):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
using Microsoft.Practices.EnterpriseLibrary.Common.Configuration; using Microsoft.Practices.EnterpriseLibrary.Data; namespace EntLibStudy.Helper { public static class DBHelper { /// <summary> /// 获取数据库对象 /// </summary> /// <param name="name">数据库实例名(默认name为空,调用默认数据库实例)</param> /// <returns>数据库对象</returns> public static Database CreateDataBase(string name = "") { //return DatabaseFactory.CreateDatabase(name); return EnterpriseLibraryContainer.Current.GetInstance<Database>(name); } } } |
在DAL层中则引用Helper来获取数据库对象,进行数据库操作,我们现在来看下具体的数据库访问类编写代码,学员操作类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
using System; using System.Collections.Generic; using System.Data; using System.Data.Common; using System.Linq; using System.Text; using Microsoft.Practices.EnterpriseLibrary.Data; using EntLibStudy.Model; using EntLibStudy.Helper; namespace EntLibStudy.DAL { public class StudentService : EntLibStudy.IDAL.IStudentService { /// <summary> /// 新增学生 /// </summary> /// <param name="student">学生对象</param> /// <returns></returns> public int Add(Student student) { Database db = DBHelper.CreateDataBase(); StringBuilder sb = new StringBuilder(); sb.Append("insert into Student values(@ClassId,@SID,@Password,@Name,@Sex,@Birthday,@IsAdmin);SELECT @@IDENTITY;"); DbCommand cmd = db.GetSqlStringCommand(sb.ToString()); db.AddInParameter(cmd, "@ClassId", DbType.String, student.ClassId); db.AddInParameter(cmd, "@SID", DbType.String, student.Sid); db.AddInParameter(cmd, "@Password", DbType.String, student.Password); db.AddInParameter(cmd, "@Name", DbType.String, student.Name); db.AddInParameter(cmd, "@Sex", DbType.Int32, student.Sex); db.AddInParameter(cmd, "@Birthday", DbType.DateTime, student.Birthday); db.AddInParameter(cmd, "@IsAdmin", DbType.Int32, student.IsAdmin); int id = Convert.ToInt32(db.ExecuteScalar(cmd)); return id; } /// <summary> /// 更新 /// </summary> /// <param name="classInfo">学生对象</param> /// <returns>是否成功</returns> public bool Update(Student student) { Database db = DBHelper.CreateDataBase(); StringBuilder sb = new StringBuilder(); sb.Append("update Student set ClassId=@ClassId,"); sb.Append("SID=@SID,"); sb.Append("Password=@Password,"); sb.Append("Name=@Name,"); sb.Append("Sex=@Sex,"); sb.Append("Birthday=@Birthday,"); sb.Append("IsAdmin=@IsAdmin "); sb.Append(" where ID=@ID"); DbCommand cmd = db.GetSqlStringCommand(sb.ToString()); db.AddInParameter(cmd, "@ClassId", DbType.String, student.ClassId); db.AddInParameter(cmd, "@SID", DbType.String, student.Sid); db.AddInParameter(cmd, "@Password", DbType.String, student.Password); db.AddInParameter(cmd, "@Name", DbType.String, student.Name); db.AddInParameter(cmd, "@Sex", DbType.Int32, student.Sex); db.AddInParameter(cmd, "@Birthday", DbType.DateTime, student.Birthday); db.AddInParameter(cmd, "@IsAdmin", DbType.Int32, student.IsAdmin); db.AddInParameter(cmd, "@ID", DbType.Int32, student.Id); return db.ExecuteNonQuery(cmd) > 0 ? true : false; } /// <summary> /// 删除 /// </summary> /// <param name="id">学生ID</param> /// <returns>是否成功</returns> public bool Delete(int id) { Database db = DBHelper.CreateDataBase(); StringBuilder sb = new StringBuilder(); sb.Append("delete from Student "); sb.Append(" where ID=@ID"); DbCommand cmd = db.GetSqlStringCommand(sb.ToString()); db.AddInParameter(cmd, "@ID", DbType.Int32, id); return db.ExecuteNonQuery(cmd) > 0 ? true : false; } /// <summary> /// 根据学生ID查询学生对象 /// </summary> /// <param name="id">学生ID</param> /// <returns></returns> public Student SelectById(int id) { Student student = null; Database db = DBHelper.CreateDataBase(); StringBuilder sb = new StringBuilder(); sb.Append("select * from Student "); sb.Append(" where ID=@ID"); DbCommand cmd = db.GetSqlStringCommand(sb.ToString()); db.AddInParameter(cmd, "@ID", DbType.Int32, id); using (IDataReader reader = db.ExecuteReader(cmd)) { if (reader.Read()) { student = new Student() { Id = reader.GetInt32(0), ClassId = reader.GetInt32(1), Sid = reader.GetString(2), Password = reader.GetString(3), Name = reader.GetString(4), Sex = reader.GetInt32(5), Birthday = reader.GetDateTime(6), IsAdmin = reader.GetInt32(7) }; } } return student; } /// <summary> /// 查询所有学生信息 /// </summary> /// <returns></returns> public IList<Student> SelectAll() { List<Student> list = new List<Student>(); Database db = DBHelper.CreateDataBase(); StringBuilder sb = new StringBuilder(); sb.Append("select * from Student "); DbCommand cmd = db.GetSqlStringCommand(sb.ToString()); using (IDataReader reader = db.ExecuteReader(cmd)) { while (reader.Read()) { list.Add(new Student() { Id = reader.GetInt32(0), ClassId = reader.GetInt32(1), Sid = reader.GetString(2), Password = reader.GetString(3), Name = reader.GetString(4), Sex = reader.GetInt32(5), Birthday = reader.GetDateTime(6), IsAdmin = reader.GetInt32(7) }); } } return list; } /// <summary> /// 查询所有学生信息 /// </summary> /// <returns></returns> public IList<Student> SelectAllMapper() { var list = new List<Student>(); Database db = DBHelper.CreateDataBase(); DataAccessor<Student> studentAccessor; //studentAccessor = db.CreateSqlStringAccessor("select * from Student", // MapBuilder<Student>.MapAllProperties(). // Build() // ); studentAccessor = db.CreateSqlStringAccessor("select * from Student", MapBuilder<Student>.MapAllProperties(). Map(p => p.Id).ToColumn("ID"). Map(p => p.Sid).ToColumn("SID"). Map(p => p.Password).WithFunc(f => "******").//将密码转换为"*",无法直接查看 Map(p => p.Name).WithFunc(ToUpperName).//将学员名称转换为大写 Map(p => p.Sex).ToColumn("Sex"). Map(p => p.Birthday).ToColumn("Birthday"). Build() ); list = studentAccessor.Execute().ToList(); return list; } /// <summary> /// 将学员名称转换为大写 /// </summary> /// <param name="dataRecord"></param> /// <returns></returns> private string ToUpperName(IDataRecord dataRecord) { var name = (string)dataRecord["Name"]; return name.ToUpper(); } public Student SelectBySid(string sid) { Student student = null; Database db = DBHelper.CreateDataBase(); StringBuilder sb = new StringBuilder(); sb.Append("select * from Student "); sb.Append(" where SID=@SID"); DbCommand cmd = db.GetSqlStringCommand(sb.ToString()); db.AddInParameter(cmd, "@SID", DbType.String, sid); using (IDataReader reader = db.ExecuteReader(cmd)) { if (reader.Read()) { student = new Student() { Id = reader.GetInt32(0), ClassId = reader.GetInt32(1), Sid = reader.GetString(2), Password = reader.GetString(3), Name = reader.GetString(4), Sex = reader.GetInt32(5), Birthday = reader.GetDateTime(6), IsAdmin = reader.GetInt32(7) }; } } return student; } } } |
其中的代码都是采用了比较常见的老套路: 1、获取数据库对象 2、构建Command对象并进行执行语句及参数赋值 3、通过数据库对象调用相应方法执行Command 企业库在Data Access上帮我们做了比较好的封装,相当于为我们提供了如SQLHelper,OracleHelper类,只不过这个帮助类转换了一个个数据库的对象,通过数据库对象来对数据库数据进行操作 (个人认为通过这种方式进行操作更加直观,而且企业库的对SQL语句的参数操作方法也很直观:AddInParameter,AddOutParameter,GetParameterValue很好的区分了参数的操作,比原来的SQLCommand好多了) 如果仔细看了上面操作代码的朋友肯定发现了类中有个叫SelectAllMapper的方法,这个方法采用的是企业库5.0中新提供的Accessor进行RowMapper来直接为实体赋值,相比原来的使用reader方式取值赋值更加优雅,只要SQL查询出来的对象字段和实体对象属性一样就可以使用MapAllProperties()方法直接赋值,如果不同的话可以使用map方法来对个别属性单独映射,而且在映射的时候还可以使用WithFunc来进行进一步操作,在代码中我将密码进行了替换,以“*”的形式展示,同时把学员的名称以大写的形式展示。 (注:更多的企业库Data Access模块方法使用可以点击这里下载微软给出的学习例子和http://www.entlib.com/发布的学习手册) 在完成底层的操作,现在我们就开始对企业库的数据库访问进行配置: 在Web层的Web.config上右键打开企业库配置器:Blocks-Add Data Settings-Add DataBase Connstring,新建2个数据库对象,一个是MS SqlServer数据库,一个是SQLite数据库. 新建一个数据库设置 新建二个数据库连接 一个为EntLibStudy,另一个为EntLibSQLite 我们来看下具体的配置文件代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
<configuration> <configSections> <section name="dataConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Data.Configuration.DatabaseSettings, Microsoft.Practices.EnterpriseLibrary.Data, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" /> </configSections> <dataConfiguration defaultDatabase="EntLibStudy" /> <connectionStrings> <add name="EntLibStudy" connectionString="server=VOLK\SQL2005;database=EntLibStudy;Integrated Security=True;" providerName="System.Data.SqlClient" /> <add name="EntLibStudySQLite" connectionString="data source=|DataDirectory|EntLibStudySQLite.db3" providerName="System.Data.SQLite" /> </connectionStrings> <appSettings> <add key="DAL" value="EntLibStudy.DAL" /> </appSettings> <system.web> <compilation debug="true" targetFramework="4.0" > <expressionBuilders> <add expressionPrefix="RouteUrl" type="System.Web.Compilation.RouteUrlExpressionBuilder"/> <add expressionPrefix="RouteValue" type="System.Web.Compilation.RouteValueExpressionBuilder"/> </expressionBuilders> </compilation> <authentication mode="Forms"> </authentication> </system.web> </configuration> |
至此我们就完成了Data Access模块的代码编写和基本设置(具体代码请到文章底部下载源代码,类似代码则不再描述)。 这时如果项目需求发生了变更,由于成本太高不能使用MS SQL SERVER,而要改用SQLite数据库时则只需更改配置文件,将dataConfiguration配置节中defaultDatabase更改为EntLibStudySQLite,将appSettings配置节中DAL的值改为EntLibStudy.DALSQLite即可立刻切换到SQLite数据库。 下面我来看下运行出来的效果: 红色框中地址采用了ASP.NET4中的路由功能,实现了地址重写 红框中如上面的分析,在DAL层进行属性映射的时候已经将密码以*代替,学员姓名以大写形式展现(此页面仅用来展示属性映射,无其他用处,页面地址为:~/Student/StudentList.aspx) 至此,学习之路的第二步——Data Access模块的学习就到此为止了,其他一些东西请下载源代码查看。 注意: 1、MSSQL数据库在DataBase目录下(需要自行附加数据库),SQLite数据库在Web目录的App_Data下,由于考虑到项目的大小,所以每个项目的BIN目录都已经删除,如出现无法生成项目请自行添加相关企业库的DLL。 2、由于微软企业库5.0 学习之路这个系列我是准备以一个小型项目的形式介绍企业库的各模块,所以源代码会根据系列文章的更新而更新,所以源代码不能保证与文章中所贴代码相同。 3、项目开发环境为:VS2010+SQL2005。 4、管理员帐户:admin 密码:admin 项目下载地址:点我下载 转自:http://www.cnblogs.com/kyo-yo/archive/2010/06/10/Learning-EntLib-Second.html
View Details话说在大学的时候帮老师做项目的时候就已经接触过企业库了但是当初一直没明白为什么要用这个,只觉得好麻烦啊,竟然有那么多的乱七八糟的配置(原来我不知道有配置工具可以进行配置,请原谅我的小白)。 直到去年在做项目的时候在看代码生成工具的时候看到了许多生成工具都内置了企业库的数据库访问及一些相关模块,才突然顿悟了,可能企业库应该还是有点用的,于是就试着使用了企业库的一些模块(当时版本是4.1),果然觉得企业库还是很不错的,微软在企业库中为我们封装了许多日常经常使用的模块,如:数据库访问,缓存,日志,异常处理,加密,IOC等等,在日常的项目开发中,企业库已经贯穿了一个项目从底层到表示层基本上需要用到的模块,大大方便了我们的开发,毕竟自己再重复造轮子还不如就用微软的(毕竟企业库现在都到5.0) 最近在看园子里有好几位都在写,如:virus,huangcong。我现在写的其实基本上都是自己的学习之路(可能没前面2位写的好,但就当自己的学习笔记吧)。 废话不多说了,首先开始学习企业库的基本概念,一下摘自sfbirp的企业库学习笔记: 一、什么是企业库? 企业库包含一系列应用程序模块和核心架构。这些高复用的组件旨在帮助开发者解决一些共同的企业开发问题。 企业库同时提供高可配置的特性,使我们管理重复的工作更加容易,例如我们知道的在应用的很多地方发生的横切关注点。包括像日志记录、缓存、异常管理等。另外,它提供的依赖注入容器能够简化和分解你的设计,使他们更加可实验和容易理解,帮助你创建更加高性能的设计和各种应用。 二、使用企业库的3个简单步骤: 1.引用和配置你需要的程序集。 2.通过企业库配置应用。 3.在你的代码中创建和使用企业库对象。 三、企业库的好处: 应用模块帮助解决开发者从一个项目到另一个项目面对的共同问题。他们的设计封装了微软推荐的做法,这些都是基于微软框架的应用开发。例如,数据访问应用模块提供了对ADO.NET访问最频繁使用的特征。在某些情况下,应用模块还添加了一些基础类库没有直接提供的相关功能。 四、企业库的目标: 1.一致。所有的企业库模块都坚持一致的设计模式和实现方式。 2.可扩展性。所有的应用模块包括定义扩展点,允许开发人员通过添加自己的代码定制应用模块的行为。 3.易用性。企业库提供了许多实用性的东西,包括一个图形化配置工具,简单的安装过程,完成的文档和示例。 4.集成。企业库应用模块被设计得能够一起很好的工作,并且也被这样测试过。但是你不必一起使用他们。我们可以单独使用这些应用模块,同时这些应用模块之间也有些依赖,比如在企业库核心和Unity中的一些通用组件。 上面是企业库的基本概念,理解了企业库的相关知识后,我们可以开始来安装企业库了 1、下载地址:点我进入下载页面(不是直接下载),安装后就可以使用了。 这次5.0相比4.1的最大改动就是整个配置工具采用了WPF重新构建和实例化和管理对象生命周期的全依赖注入的实现,同时支持VS2008SP1和VS2010,话说虽然这次的配置工具变化挺大的,但是一旦熟悉了就觉得比4.1的好,因为可以清楚的看见每个模块的之间的依赖关系。 附相关改动,还是摘自sfbirp的企业库学习笔记: 一、Unity和对象生成器的整合 在这个版本中,用于创建对象的基本技术是一个单一的依赖注入容器,默认的是Unity。你可以使用容器生成企业库对象的实例并注入到其他的对象。 企业库提供一个标准的接口从Unity容器中来获得定义在企业库配置中的对象的实例,如SqlDatabase或LogWriter.另外,注入友好的实例门面处理静态门面之外是有效的,因为静态门面不能用注入,但是为了向后兼容以前的版本而存在。在本版本中的示例中都是用依赖注入,但是以前版本中是用的静态工厂类和静态门面在这个版本中还是支持的。对象生成器,一个低版本的依赖注入机制在这个版本中被归入Unity中,在项目中不再需要单独引用对象生成器集。 支持Unity容器,必须引用一个被包含在企业库中的Microsoft.Practices.ServiceLocation程序集。如果要使用一个第3方的依赖注入容器,必须直接实现IServiceLocator接口或者通过适配器实现。 二、影响所有模块的变化: 1.在企业库中主要修正是使用依赖注入机制。所用的应用模块以及核心系统都是用依赖注入机制,并使用Unity作为默认的依赖注入容器,来创建和管理企业库对象。 2.自主容器的实现通过实现Common Service Locator项目提供的 IServiceLocator 接口来完成。 3.由于错误配置引发的错误将提供更多有用的错误信息。 4.配置系统公开了一个 fluent接口,用来为单个对象或整个应用创建和填充配置源。fluent API使得为各种情景创建配置源更加容易。 5.ConfigurationView类被删除. 6.一些配置元素有默认值,可能不同于以前版本的隐式默认值. 7.企业库现在允许你通过另一个配置文件合成一个混合配置文件. 8.可以可通过不同的配置文件读取不同的配置信息. 9.企业库不支持XAML浏览器应用程序(XBAP). 10.WmiEnabled标志为了像前兼容仍然存在企业库中,但是在5.0中是被忽略的,而且将来会被删除. 11.改进式的安装允许你只安装部分应用模块及配置工具. 12.在以前版本中要做统一集成,必须添加核心企业库的扩展和每个模块的扩展。现在如果你只需要直接访问容器,那么只有核心扩展是必须的。单独模块将自动支持。 旧的功能为了保持像前兼容仍然保留,但已经不起作用。 13.FileConfigurationSource.Save 的签名已经改变,参数由3个变为2个。 14.快速入门不再包含在主安装程序中。 三、Breaking变化: 1.企业库现在抛出了一个配置错误ActivationException,之前是System.Configuration.ConfigurationErrorsException。这包括试着解决没有配置信息错误的一个实例提供者。 2.以前版本在获取应用模块错误时抛出BuildFailedException错误,现在对于所有的应用模块都抛出ActivationException 3 .之前的版本,在讲一个空源传到容器来调用容器的时候,会抛出ArgumentNullException,现在抛出NullReferenceException 4.ObjectBuilder2不再是一个单独的程序集,而是集成到了Unity集合中,在项目中也不需要引用ObjectBuilder2.dll。 5.WMI支持已经从企业库中删除,除了在logging模块中的WMI跟踪监听器。 6.如果你没有关闭DbDataReader,可能会导致随机的、很难在您的代码中找到的错误,尤其是当你正在一个由TransactionScope上下文创建的隐式事务下操作时。 你必须始终确保您的应用程序及时关闭DbDataReader,无论是明确的DbDataReader.Close方法关闭或是逼迫DbDataReader释放。 7.如果你使用 validator 特性必须引用 System.ComponentModel.DataAnnotations程序集。 8.为FileConfigurationSource.Save方法签名已更改。该方法有两个参数,而不是3个参数 9.Microsoft.Practices.EnterpriseLibrary.Configuration.Design.dll集合的功能和其他设计时集合被一个新的集合Microsoft.Practices.EnterpriseLibrary.Configuration.DesignTime.dll代替。 10,性能计数器异常从PolicyInjection.CallHandlers移到 PolicyInjection 程序集。 11.包含在Policy Injection Application Block中的CachingCallHandler有未处理的安全漏洞,已经从Policy Injection Application Block中移除。 四、配置工具的改变: 1.新的企业拥有一个新的GUI库和一个元数据驱动的可扩展性模。 2.支持向导 3.新的类型选择。 4.不支持对依赖策略的Environmental Overrides 。日志模块处理Categories。 五、缓存模块变化: 1.缓存清除已被完全重写的性能优化 六、数据库访问模块: 1.ExecuteReader, ExecuteXmlReader, ExecuteScalar, and ExecuteNonQuery方法具有异步版本。 2.包含了很多新的方法和类允许你提取数据作为对象序列。例如在合适的时候使用客户端查询技术,如LINQ. 3.存在的方法ExecuteReader和新的方法BeginExecuteReader不接收CommandBehavior 参数。默认的当调用这些方法的时候这些方法 会自动设置CommandBehavior 属性到reder中用来关闭连接直到指定一个事务。 七、异常处理模块: 1.日志异常处理重新使用日志模块的Log Writer and Trace Listeners 。这在之前版本中不是默认设置。 2.增加一个功能,通过ExceptionManager.Process 方法接收一个默认值并返回一个值。 在安装完企业库同时知道了5.0的变化后,就开始正式的学习了,学习的最好办法不是看企业库的源代码(我是看不懂),而是下载微软发布的学习例子 学习例子下载地址:点我进入下载页面(不是直接下载) 这个学习例子里面已经包含了所需的类库及代码演示(C#和VB.NET都有),同时可以右键例子中的App.config来看下例子中的模块是怎么配置的。 同时,在学习例子的时候可以看下由http://www.entlib.com/发布的中文学习手册,虽然是4.1的,但是里面的所有内容都和5.0的例子一样(5.0只不过是重新实现了1遍),把例子和文档结合起来看学习起来就快了很多了: 中文学习手册:点我下载 Entlib5程序:点我进入下载页面(不是直接下载), 到此,Entlib5的学习之路的第一步就结束了,基本上通过微软发布的学习例子和对应的中文学习手册可以对5.0的使用已经有了个基本的了解。 转自:http://www.cnblogs.com/kyo-yo/archive/2010/06/07/Study-Entlib5-First.html
View DetailsADO.NET Entity Framework,即下一代的ADO.NET。它是比Linq To SQL更加强大的ORM,让开发人员只需要着眼于领域对象模型的开发,而不需要考虑它们是如何与关系数据库交互。上一篇文章简单介绍了在项目中如何使用ADO.NET实体框架,从现在开始,正式进入了ADO.NET的学习之旅。这篇文章主要介绍在ADO.NET实体框架中如何进行查询(以Northwind数据库为例)。 1. 使用EntityCommand进行查询 在实体框架中,我们可以通过EntityCommand进行查询,它的使用方法就像ADO.NET中的SqlCommand。不同的是SqlCommand使用标准SQL语句对数据库进行查询,而EntityCommand使用Entity SQL对EntityContainer进行查询,当然最终实体框架会将Entity SQL转换成标准SQL语句查询数据库。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<span style="color: #2b91af;">EntityConnection</span> con = <span style="color: #0000ff;">new</span><span style="color: #2b91af;">EntityConnection</span>(<span style="color: #a31515;">"Name=NorthwindEntities"</span>); con.Open(); <span style="color: #0000ff;">using</span> (<span style="color: #2b91af;">EntityCommand</span> cmd = <span style="color: #0000ff;">new</span><span style="color: #2b91af;">EntityCommand</span>(<span style="color: #a31515;">"select value c from NorthwindEntities.Customers as c"</span>, con)) { <span style="color: #2b91af;">EntityDataReader</span> reader = cmd.ExecuteReader(<span style="color: #2b91af;">CommandBehavior</span>.SequentialAccess); <span style="color: #0000ff;">while</span> (reader.Read()) { <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"ID [{0}], ContactTitle [{1}]"</span>, reader[<span style="color: #a31515;">"CustomerID"</span>], reader[<span style="color: #a31515;">"ContactTitle"</span>]); } } |
首先是建立一个EntityConnection,它接受一个参数,表明使用的是在config文件中的哪个连接字符串。 <connectionStrings> <add name="NorthwindEntities" connectionString="metadata=.\Northwind.csdl|.\Northwind.ssdl|.\Northwind.msl;provider=System.Data.SqlClient;provider connection string="Data Source=localhost\sqlexpress;Initial Catalog=Northwind;Integrated Security=True"" providerName="System.Data.EntityClient" /> </connectionStrings> 可以看到这个连接字符串和以往ADO.NET中使用的连接字符串并不一样。metadata:指明.csdl/.ssdl/.msl三个文件的路径,这三个文件的作用以后再做说明。provider:表示使用的是SqlClient或者Oledb或者Odbc。provider connection string:这一项便是以往所用的连接字符串。providerName表示现在用的是EntityClient。 接着构造EntityCommand,最后通过EntityDataReader进行数据的读取,值得注意的是这里的EntityCommand接受的是Entity SQL语句,而不是标准SQL语句,具体的Entity SQL语法可以参考帮助文档。 2. 使用ObjectQuery进行查询 实体框架提供一个名为ObjectQuery的类,它让开发人员通过Entity SQL进行查询,查询结果以对象的形式供使用。
1 2 3 4 5 6 7 8 9 10 11 |
<span style="color: #0000ff;">using</span> (<span style="color: #2b91af;">NorthwindEntities</span> ctx = <span style="color: #0000ff;">new</span><span style="color: #2b91af;">NorthwindEntities</span>()) { <span style="color: #2b91af;">ObjectQuery</span><<span style="color: #2b91af;">Customer</span>> query = ctx.CreateQuery<<span style="color: #2b91af;">Customer</span>>(<span style="color: #a31515;">"NorthwindEntities.Customers"</span>); <span style="color: #2b91af;">ObjectResult</span><<span style="color: #2b91af;">Customer</span>> result = query.Execute(<span style="color: #2b91af;">MergeOption</span>.NoTracking); <span style="color: #0000ff;">foreach</span> (<span style="color: #2b91af;">Customer</span> c <span style="color: #0000ff;">in</span> result) { <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"ID [{0}], ContactTitle [{1}]"</span>, c.CustomerID, c.ContactTitle); } } |
首先调用CreateQuery方法来创建ObjectQuery对象(当然这里也可以使用new,只是传进的参数不同而已),它接受Entity SQL语句作为参数。然后调用Execute方法进行查询,它接受MergeOption枚举型的参数,表示解决冲突的方法。查询结果以对象的形式(这里是Customer)保存在ObjectResult中。 下面是使用new的写法:
1 2 3 4 5 6 7 8 9 10 |
<span style="color: #0000ff;">using</span> (<span style="color: #2b91af;">NorthwindEntities</span> ctx = <span style="color: #0000ff;">new</span><span style="color: #2b91af;">NorthwindEntities</span>()) { <span style="color: #2b91af;">ObjectQuery</span><<span style="color: #2b91af;">Customer</span>> query = <span style="color: #0000ff;">new</span><span style="color: #2b91af;">ObjectQuery</span><<span style="color: #2b91af;">Customer</span>>(<span style="color: #a31515;">"Customers"</span>, ctx); <span style="color: #0000ff;">foreach</span> (<span style="color: #2b91af;">Customer</span> c <span style="color: #0000ff;">in</span> query) { <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"ID [{0}], ContactTitle [{1}]"</span>, c.CustomerID, c.ContactTitle); } } |
3. ADO.NET Entity Framework Tool自动生成Entities和各个对象的代码,帮助开发人员减少了很多体力活。这样,我们可以简单写成:
1 2 3 4 5 6 7 8 9 |
<span style="color: #0000ff;">using</span> (<span style="color: #2b91af;">NorthwindEntities</span> ctx = <span style="color: #0000ff;">new</span><span style="color: #2b91af;">NorthwindEntities</span>()) { <span style="color: #0000ff;">foreach</span> (<span style="color: #2b91af;">Customer</span> c <span style="color: #0000ff;">in</span> ctx.Customers) { <span style="color: #2b91af;">Console</span>.WriteLine(<span style="color: #a31515;">"ID [{0}], ContactTitle [{1}]"</span>, c.CustomerID, c.ContactTitle); } } |
其实这里,也是使用ObjectQuery来进行查询。当然,可以给查询加上更多的条件,在上一篇文章中也有说明这里就不写了。 值得关注的是:自动生成的实体类中有这样一个方法,比如Customer:
1 2 3 4 5 6 7 |
<span style="color: #0000ff;">public</span><span style="color: #0000ff;">static</span><span style="color: #2b91af;">Customer</span> CreateCustomer(<span style="color: #0000ff;">string</span> customerID, <span style="color: #0000ff;">string</span> companyName) { <span style="color: #2b91af;">Customer</span> customer = <span style="color: #0000ff;">new</span><span style="color: #2b91af;">Customer</span>(); customer.CustomerID = customerID; customer.CompanyName = companyName; <span style="color: #0000ff;">return</span> customer; } |
并不像以前一样,提供带参数的构造函数,而是提供CreateCustomer的静态方法来构造Customer实例。这似乎和前一段时候贫血充血的问题有关了,实体对象该不该有行为,是贫血还是充血?虽然只是一个方法,不过相信这也表明了微软的态度吧。 转自:http://www.cnblogs.com/blusehuang/archive/2007/10/14/923549.html
View Details前一段时间园子里有很多文章介绍分析了Linq To SQL,它可以说是一个简单实现的ORM,是微软针对数据和对象的阻抗不平衡的问题。C# 3.0推出一些新的特性,比如Extension Method, Lambda Expression, Anonymous Type,其实这些新特性都是用来为Linq服务。Linq To SQL将程序员从以往写大量的sql查询语句、取值、赋值中解放出来,在intellisense和编译上做了很多工作,使得这些查询能够在编译期进行检查。同时微软推出ADO.NET Entity Framework,即下一代的ADO.NET。它是比Linq To SQL更加强大的ORM,让开发人员只需要着眼于领域对象模型的开发,而不需要考虑它们是如何与关系数据库交互。 本文由一个简单的例子进行介绍Entity Framework是如何使用的。在此之前,必须下载ADO.NET Entity Framework runtime 和tools,官方也提供了很多示例下载。下面正式开始ADO.NET Entity Framework之旅(开发工具VS 2008 beta,以Northiwind数据库为例)。 首先建立一个Console project(要选择.NET Framework 3.5),然后点击Add New Item,看见ADO.NET Entity Data Model选项: 然后会出现Wizard,选择数据库,选择表、视图、存储过程等,按照向导一步步来就可以了,在这里只选择Customers和Orders表。在Solution Explore视图里面点击Northwind.edmx,可以看到Entity的信息(看上去很像Linq To SQL的dbml设计视图),然后将它们改名为Customer和Order。 现在我们就可以进行查询了,先引用命名空间:
1 2 |
<span style="color: #0000ff;">using</span> System.Data.Objects; <span style="color: #0000ff;">using</span> NorthwindModel; |
1 |
首先我们查询所有的Customer,代码和Linq To SQL中的十分相似。 |
1 2 3 4 5 6 7 |
<span style="color: #0000ff;">using</span> (<span style="color: #2b91af;">NorthwindEntities</span> ctx = <span style="color: #0000ff;">new</span><span style="color: #2b91af;">NorthwindEntities</span>()) { <span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">var</span> customer <span style="color: #0000ff;">in</span> ctx.Customers) { <span style="color: #2b91af;">Console</span>.WriteLine(customer.CustomerID); } } |
接着来查询某个Customer,
1 |
<span style="color: #2b91af;">Customer</span> alfki = ctx.Customers.Where(<span style="color: #a31515;">"it.CustomerID = 'ALFKI'"</span>).First(); |
"it.CustomerID = 'ALFKI’"表示查询条件语句,该语句看着又像C#代码又像SQL,被成为Entity SQL Language,具体语法在帮助文档上有很详细的Reference。 这里也可以使用Linq进行查询(Linq To Entities),需要引用System.Linq命名空间,似乎Entity Framework不支持Single方法,会抛出异常。
1 |
<span style="color: #2b91af;">Customer</span> alfki = ctx.Customers.First<<span style="color: #2b91af;">Customer</span>>(it => it.CustomerID == <span style="color: #a31515;">"ALFKI"</span>); |
1 |
或者 |
1 2 |
<span style="color: #2b91af;">Customer</span> alfki = (<span style="color: #0000ff;">from</span> c <span style="color: #0000ff;">in</span> ctx.Customers <span style="color: #0000ff;">where</span> c.CustomerID == <span style="color: #a31515;">"ALFKIA"</span><span style="color: #0000ff;">select</span> c).First(); |
1 |
在Entity Framework中进行一对多的查询很简单,但是值得注意的是Entity Framework默认是Lazy Load,即关联数据在需要的时候才加载。 |
1 |
在本例子中,如果直接查询该Customer关联的orders,查询不到结果。 |
1 2 3 4 |
<span style="color: #0000ff;">foreach</span> (<span style="color: #0000ff;">var</span> order <span style="color: #0000ff;">in</span> alfki.Orders) { <span style="color: #2b91af;">Console</span>.WriteLine(order.OrderID); } |
需要在使用orders之前调用 alfki.Orders.Load(), 再次运行便可以得到正确的结果。
1 |
[未完待续] |
转自:http://www.cnblogs.com/blusehuang/archive/2007/10/10/920020.html
View DetailsHttpWebRequest 是 .net 基类库中的一个类,在命名空间 System.Net 下面,用来使用户通过 HTTP 协议和服务器交互。 HttpWebRequest 对 HTTP 协议进行了完整的封装,对 HTTP 协议中的 Header, Content, Cookie 都做了属性和方法的支持,很容易就能编写出一个模拟浏览器自动登录的程序。 程序使用 HTTP 协议和服务器交互主要是进行数据的提交,通常数据的提交是通过 GET 和 POST 两种方式来完成,下面对这两种方式进行一下说明: 1. GET 方式。 GET 方式通过在网络地址附加参数来完成数据的提交,比如在地址 http://www.google.com/webhp?hl=zh-CN 中,前面部分 http://www.google.com/webhp 表示数据提交的网址,后面部分 hl=zh-CN 表示附加的参数,其中 hl 表示一个键(key), zh-CN 表示这个键对应的值(value)。程序代码如下: HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create( "http://www.google.com/webhp?hl=zh-CN" );req.Method = "GET";using (WebResponse wr = req.GetResponse()){ //在这里对接收到的页面内容进行处理} 2. POST 方式。 POST 方式通过在页面内容中填写参数的方法来完成数据的提交,参数的格式和 GET 方式一样,是类似于 hl=zh-CN&newwindow=1 这样的结构。程序代码如下: string param = "hl=zh-CN&newwindow=1";byte[] bs = Encoding.ASCII.GetBytes(param); HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create( "http://www.google.com/intl/zh-CN/" );req.Method = "POST";req.ContentType = "application/x-www-form-urlencoded";req.ContentLength = bs.Length; using (Stream reqStream = req.GetRequestStream()){ reqStream.Write(bs, 0, bs.Length);}using (WebResponse wr = req.GetResponse()){ //在这里对接收到的页面内容进行处理} 在上面的代码中,我们访问了 www.google.com 的网址,分别以 GET 和 POST 方式提交了数据,并接收了返回的页面内容。然而,如果提交的参数中含有中文,那么这样的处理是不够的,需要对其进行编码,让对方网站能够识别。 3. 使用 GET 方式提交中文数据。 GET 方式通过在网络地址中附加参数来完成数据提交,对于中文的编码,常用的有 gb2312 和 utf8 两种,用 gb2312 方式编码访问的程序代码如下: Encoding myEncoding = Encoding.GetEncoding("gb2312");string address = "http://www.baidu.com/s?" + HttpUtility.UrlEncode("参数一", myEncoding) + "=" + HttpUtility.UrlEncode("值一", myEncoding);HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(address);req.Method = "GET";using (WebResponse wr = req.GetResponse()){ //在这里对接收到的页面内容进行处理} 在上面的程序代码中,我们以 GET 方式访问了网址 http://www.baidu.com/s ,传递了参数“参数一=值一”,由于无法告知对方提交数据的编码类型,所以编码方式要以对方的网站为标准。常见的网站中, www.baidu.com (百度)的编码方式是 gb2312, www.google.com (谷歌)的编码方式是 utf8。 4. 使用 POST 方式提交中文数据。 POST 方式通过在页面内容中填写参数的方法来完成数据的提交,由于提交的参数中可以说明使用的编码方式,所以理论上能获得更大的兼容性。用 gb2312 方式编码访问的程序代码如下: Encoding myEncoding = Encoding.GetEncoding("gb2312");string param = HttpUtility.UrlEncode("参数一", myEncoding) + "=" + HttpUtility.UrlEncode("值一", myEncoding) + "&" + HttpUtility.UrlEncode("参数二", myEncoding) + "=" + HttpUtility.UrlEncode("值二", myEncoding); byte[] postBytes = Encoding.ASCII.GetBytes(param); HttpWebRequest req = (HttpWebRequest) HttpWebRequest.Create( "http://www.baidu.com/s" );req.Method = "POST";req.ContentType = "application/x-www-form-urlencoded;charset=gb2312";req.ContentLength = postBytes.Length; using (Stream reqStream = req.GetRequestStream()){ reqStream.Write(bs, 0, bs.Length);}using (WebResponse wr = req.GetResponse()){ //在这里对接收到的页面内容进行处理} 从上面的代码可以看出, POST 中文数据的时候,先使用 UrlEncode 方法将中文字符转换为编码后的 ASCII 码,然后提交到服务器,提交的时候可以说明编码的方式,用来使对方服务器能够正确的解析。 以上列出了客户端程序使用 HTTP 协议与服务器交互的情况,常用的是 GET 和 POST 方式。现在流行的 WebService 也是通过 HTTP 协议来交互的,使用的是 POST 方法。与以上稍有所不同的是, WebService 提交的数据内容和接收到的数据内容都是使用了 XML 方式编码。所以, HttpWebRequest 也可以使用在调用 WebService 的情况下。 转自:http://www.cnblogs.com/webman/archive/2006/11/17/564106.html
View Details1.Default.aspx
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="ScriptWebSerivce" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head id="Head1" runat="server"> <title></title> <script type="text/javascript"> function ShowResult(res) { alert(res);} </script> </head> <body> <form id="form1" runat="server"> <div> <asp:ScriptManager ID="ScriptManager1" runat="server"> <Services> <asp:ServiceReference Path="MyWebService.asmx" /> </Services> </asp:ScriptManager> <script type="text/javascript"> Ajax.MyWebService.GetTotal(5, 4, ShowResult, null, "abc"); </script> </div> </form> </body> </html> |
2.MyWebService.asmx.cs
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Services; using System.Web.Script.Services; namespace Ajax { /// <summary> /// MyWebService 的摘要说明 /// </summary> [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)] //[System.ComponentModel.ToolboxItem(false)] // 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。 [ScriptService] public class MyWebService : System.Web.Services.WebService { public MyWebService() { //Uncomment the following line if using designed components //InitializeComponent(); } [WebMethod] public int GetTotal(int x, int y) { return x + y; } } } |
注意:此方法只适合在同一个域下调用。
View DetailsSystem.Web.Caching 命名空间提供用于缓存服务器上常用数据的类。此命名空间包括 Cache 类,该类是一个字典,您可以在其中存储任意数据对象,如哈希表和数据集。它还为这些对象提供了失效功能,并为您提供了添加和移除这些对象的方法。您还可以添加依赖于其他文件或缓存项的对象,并在从 Cache对象中移除对象时执行回调以通知应用程序。
1 |
<div style="margin:0px;padding:0px;line-height:21px;"><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><summary></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"> 获取当前应用程序指定CacheKey的Cache对象值 <br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"></summary></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><param name="CacheKey"></span><span style="margin:0px;padding:0px;color:#008000;">索引键值</span><span style="margin:0px;padding:0px;color:#808080;"></param></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><returns></span><span style="margin:0px;padding:0px;color:#008000;">返回缓存对象</span><span style="margin:0px;padding:0px;color:#808080;"></returns></span><span style="margin:0px;padding:0px;color:#808080;"> </span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">public</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">static</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">object</span><span style="margin:0px;padding:0px;color:#000000;"> GetCache(</span><span style="margin:0px;padding:0px;color:#0000ff;">string</span><span style="margin:0px;padding:0px;color:#000000;"> CacheKey)<br style="margin:0px;padding:0px;line-height:10px;" />{<br style="margin:0px;padding:0px;line-height:10px;" /> System.Web.Caching.Cache objCache </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"> HttpRuntime.Cache;<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">return</span><span style="margin:0px;padding:0px;color:#000000;"> objCache[CacheKey];<br style="margin:0px;padding:0px;line-height:10px;" />}<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><summary></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"> 设置当前应用程序指定CacheKey的Cache对象值<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"></summary></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><param name="CacheKey"></span><span style="margin:0px;padding:0px;color:#008000;">索引键值</span><span style="margin:0px;padding:0px;color:#808080;"></param></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><param name="objObject"></span><span style="margin:0px;padding:0px;color:#008000;">缓存对象</span><span style="margin:0px;padding:0px;color:#808080;"></param></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">public</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">static</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">void</span><span style="margin:0px;padding:0px;color:#000000;"> SetCache(</span><span style="margin:0px;padding:0px;color:#0000ff;">string</span><span style="margin:0px;padding:0px;color:#000000;"> CacheKey, </span><span style="margin:0px;padding:0px;color:#0000ff;">object</span><span style="margin:0px;padding:0px;color:#000000;"> objObject)<br style="margin:0px;padding:0px;line-height:10px;" />{<br style="margin:0px;padding:0px;line-height:10px;" /> System.Web.Caching.Cache objCache </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"> HttpRuntime.Cache;<br style="margin:0px;padding:0px;line-height:10px;" /> objCache.Insert(CacheKey, objObject);<br style="margin:0px;padding:0px;line-height:10px;" />}<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><summary></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"> 设置当前应用程序指定CacheKey的Cache对象值<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"></summary></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><param name="CacheKey"></span><span style="margin:0px;padding:0px;color:#008000;">索引键值</span><span style="margin:0px;padding:0px;color:#808080;"></param></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><param name="objObject"></span><span style="margin:0px;padding:0px;color:#008000;">缓存对象</span><span style="margin:0px;padding:0px;color:#808080;"></param></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><param name="absoluteExpiration"></span><span style="margin:0px;padding:0px;color:#008000;">绝对过期时间</span><span style="margin:0px;padding:0px;color:#808080;"></param></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><param name="slidingExpiration"></span><span style="margin:0px;padding:0px;color:#008000;">最后一次访问所插入对象时与该对象过期时之间的时间间隔</span><span style="margin:0px;padding:0px;color:#808080;"></param></span><span style="margin:0px;padding:0px;color:#808080;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">public</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">static</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">void</span><span style="margin:0px;padding:0px;color:#000000;"> SetCache(</span><span style="margin:0px;padding:0px;color:#0000ff;">string</span><span style="margin:0px;padding:0px;color:#000000;"> CacheKey, </span><span style="margin:0px;padding:0px;color:#0000ff;">object</span><span style="margin:0px;padding:0px;color:#000000;"> objObject, DateTime absoluteExpiration, TimeSpan slidingExpiration)<br style="margin:0px;padding:0px;line-height:10px;" />{<br style="margin:0px;padding:0px;line-height:10px;" /> System.Web.Caching.Cache objCache </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"> HttpRuntime.Cache;<br style="margin:0px;padding:0px;line-height:10px;" /> objCache.Insert(CacheKey, objObject, </span><span style="margin:0px;padding:0px;color:#0000ff;">null</span><span style="margin:0px;padding:0px;color:#000000;">, absoluteExpiration, slidingExpiration);<br style="margin:0px;padding:0px;line-height:10px;" />} <br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">protected</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">void</span><span style="margin:0px;padding:0px;color:#000000;"> Page_Load(</span><span style="margin:0px;padding:0px;color:#0000ff;">object</span><span style="margin:0px;padding:0px;color:#000000;"> sender, EventArgs e)<br style="margin:0px;padding:0px;line-height:10px;" />{<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">string</span><span style="margin:0px;padding:0px;color:#000000;"> CacheKey </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#800000;">"</span><span style="margin:0px;padding:0px;color:#800000;">cachetest</span><span style="margin:0px;padding:0px;color:#800000;">"</span><span style="margin:0px;padding:0px;color:#000000;">;<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">object</span><span style="margin:0px;padding:0px;color:#000000;"> objModel </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"> GetCache(CacheKey);</span><span style="margin:0px;padding:0px;color:#008000;">//</span><span style="margin:0px;padding:0px;color:#008000;">从缓存中获取</span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">if</span><span style="margin:0px;padding:0px;color:#000000;"> (objModel </span><span style="margin:0px;padding:0px;color:#000000;">==</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">null</span><span style="margin:0px;padding:0px;color:#000000;">)</span><span style="margin:0px;padding:0px;color:#008000;">//</span><span style="margin:0px;padding:0px;color:#008000;">缓存里没有</span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#000000;"> {<br style="margin:0px;padding:0px;line-height:10px;" /> objModel </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"> DateTime.Now;</span><span style="margin:0px;padding:0px;color:#008000;">//</span><span style="margin:0px;padding:0px;color:#008000;">把当前时间进行缓存</span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">if</span><span style="margin:0px;padding:0px;color:#000000;"> (objModel </span><span style="margin:0px;padding:0px;color:#000000;">!=</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">null</span><span style="margin:0px;padding:0px;color:#000000;">)<br style="margin:0px;padding:0px;line-height:10px;" /> {<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">int</span><span style="margin:0px;padding:0px;color:#000000;"> CacheTime </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#800080;">30</span><span style="margin:0px;padding:0px;color:#000000;">;</span><span style="margin:0px;padding:0px;color:#008000;">//</span><span style="margin:0px;padding:0px;color:#008000;">缓存时间30秒</span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#000000;"> SetCache(CacheKey, objModel, DateTime.Now.AddSeconds(CacheTime), TimeSpan.Zero);</span><span style="margin:0px;padding:0px;color:#008000;">//</span><span style="margin:0px;padding:0px;color:#008000;">写入缓存</span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#000000;"> }<br style="margin:0px;padding:0px;line-height:10px;" /> }<br style="margin:0px;padding:0px;line-height:10px;" /> Label1.Text </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"> objModel.ToString();<br style="margin:0px;padding:0px;line-height:10px;" />}</span></div> |
以上几种方法都很好的解决了数据缓存的问题,但由一个最大的问题是当数据发生变化了,而缓存里还是过期的数据,只有等缓存过期后才会重新获取最新的数据,这样的话,很多时候用户获取的数据都是和实际数据不一致的过期数据。这同样给用户造成了比较大的麻烦,怎么办呢?接着往下看。 转自:http://kb.cnblogs.com/page/69725/
View Details更多的时候,我们的服务器性能损耗还是在查询数据库的时候,所以对数据库的缓存还是显得特别重要,上面几种方式都可以实现部分数据缓存功能。但问题是我们的数据有时候是在变化的,这样用户可能在缓存期间查询的数据就是老的数据,从而导致数据的不一致。那有没有办法做到,数据如果不变化,用户就一直从缓存中取数据,一旦数据变化,系统能自动更新缓存中的数据,从而让用户得到更好的用户体验。 答案是肯定的!.NET已经为我们提供了这样一种非常好的解决方法:SqlCacheDependency数据库缓存依赖。 实现步骤: 下面就让我们看一下如何实现数据库缓存依赖功能: 第一步: 修改web.config,让项目启用SqlCacheDependency 。 将下列代码加入web.config的<system.web>节:
1 |
<div style="margin:0px;padding:0px;line-height:21px;"><span style="margin:0px;padding:0px;color:#0000ff;"><?</span><span style="margin:0px;padding:0px;color:#ff00ff;">xml version="1.0"</span><span style="margin:0px;padding:0px;color:#0000ff;">?></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;"><</span><span style="margin:0px;padding:0px;color:#800000;">configuration</span><span style="margin:0px;padding:0px;color:#0000ff;">></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;"><</span><span style="margin:0px;padding:0px;color:#800000;">appSettings</span><span style="margin:0px;padding:0px;color:#0000ff;">/></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;"><</span><span style="margin:0px;padding:0px;color:#800000;">connectionStrings</span><span style="margin:0px;padding:0px;color:#0000ff;">></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;"><</span><span style="margin:0px;padding:0px;color:#800000;">add </span><span style="margin:0px;padding:0px;color:#ff0000;">name</span><span style="margin:0px;padding:0px;color:#0000ff;">="strcodematic"</span><span style="margin:0px;padding:0px;color:#ff0000;"> connectionString</span><span style="margin:0px;padding:0px;color:#0000ff;">="data source=127.0.0.1;initial catalog=codematic;user id=sa;password="</span><span style="margin:0px;padding:0px;color:#ff0000;"> providerName</span><span style="margin:0px;padding:0px;color:#0000ff;">="System.Data.SqlClient"</span><span style="margin:0px;padding:0px;color:#ff0000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">/></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;"></</span><span style="margin:0px;padding:0px;color:#800000;">connectionStrings</span><span style="margin:0px;padding:0px;color:#0000ff;">></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;"><</span><span style="margin:0px;padding:0px;color:#800000;">system.web</span><span style="margin:0px;padding:0px;color:#0000ff;">></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;"><</span><span style="margin:0px;padding:0px;color:#800000;">caching</span><span style="margin:0px;padding:0px;color:#0000ff;">></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;"><</span><span style="margin:0px;padding:0px;color:#800000;">sqlCacheDependency </span><span style="margin:0px;padding:0px;color:#ff0000;">enabled</span><span style="margin:0px;padding:0px;color:#0000ff;">="true"</span><span style="margin:0px;padding:0px;color:#ff0000;"> pollTime</span><span style="margin:0px;padding:0px;color:#0000ff;">="6000"</span><span style="margin:0px;padding:0px;color:#0000ff;">></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;"><</span><span style="margin:0px;padding:0px;color:#800000;">databases</span><span style="margin:0px;padding:0px;color:#0000ff;">></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /> </span><span style="margin:0px;padding:0px;color:#0000ff;"><</span><span style="margin:0px;padding:0px;color:#800000;">add </span><span style="margin:0px;padding:0px;color:#ff0000;">name</span><span style="margin:0px;padding:0px;color:#0000ff;">="codematic"</span><span style="margin:0px;padding:0px;color:#ff0000;"> connectionStringName</span><span style="margin:0px;padding:0px;color:#0000ff;">="strcodematic"</span><span style="margin:0px;padding:0px;color:#ff0000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">/></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;"></</span><span style="margin:0px;padding:0px;color:#800000;">databases</span><span style="margin:0px;padding:0px;color:#0000ff;">></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;"></</span><span style="margin:0px;padding:0px;color:#800000;">sqlCacheDependency</span><span style="margin:0px;padding:0px;color:#0000ff;">></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;"></</span><span style="margin:0px;padding:0px;color:#800000;">caching</span><span style="margin:0px;padding:0px;color:#0000ff;">></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;"><</span><span style="margin:0px;padding:0px;color:#800000;">compilation </span><span style="margin:0px;padding:0px;color:#ff0000;">debug</span><span style="margin:0px;padding:0px;color:#0000ff;">="true"</span><span style="margin:0px;padding:0px;color:#0000ff;">></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;"></</span><span style="margin:0px;padding:0px;color:#800000;">compilation</span><span style="margin:0px;padding:0px;color:#0000ff;">></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;"><</span><span style="margin:0px;padding:0px;color:#800000;">authentication </span><span style="margin:0px;padding:0px;color:#ff0000;">mode</span><span style="margin:0px;padding:0px;color:#0000ff;">="Windows"</span><span style="margin:0px;padding:0px;color:#0000ff;">/></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;"></</span><span style="margin:0px;padding:0px;color:#800000;">system.web</span><span style="margin:0px;padding:0px;color:#0000ff;">></span><span style="margin:0px;padding:0px;color:#000000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;"></</span><span style="margin:0px;padding:0px;color:#800000;">configuration</span><span style="margin:0px;padding:0px;color:#0000ff;">></span></div> |
这里的connectionStringName指定了在<connectionStrings>中添加的某一个连接字符串。name则是为该SqlCacheDependency起的名字,这个名字将在第3步中用到。 SqlCacheDependency类会自动完成对此配置节信息的读取以建立和数据库之间的联系。 注意:在<databases>节的<add name="codematic" connectionStringName="strcodematic"/>中的name属性值必须和第三步的Page_Load代码中System.Web.Caching.SqlCacheDependency("codematic","P_Product"); 中的第一个参数(数据库名称)相一致。 第二步:执行下述命令,为 数据库启用缓存依赖。 如果要配置SqlCacheDependency,则需要以命令行的方式执行。 aspnet_regsql.exe工具位于Windows\\Microsoft.NET\\Framework\\[版本]文件夹中。 aspnet_regsql -C "data source=127.0.0.1;initial catalog=codematic;user id=sa;password=" -ed -et -t "P_Product" 参数-C后面的字符串是连接字符串(请替换成自己所需要的值), 参数-t后面的字符串是数据表的名字。 运行结果如图15-3所示: 图15-3 启用数据库缓存依赖 命令执行后,在指定的数据库中会多出一个AspNet_SqlCacheTablesForChangeNotification表。 注意: 要使得7.0或者2000版本以上的SQLServer支持SqlCacheDependency特性,需要对数据库服务器执行相关的配置。 有两种方法配置SQLServer: 一使用aspnet_regsql命令行工具, 二使用SqlCacheDependencyAdmin类。 例如: aspnet_regsql -S "server"-E -d "database"–ed 或者 aspnet_regsql -S "server"-E -d "database"-et -t "table" 如果是Sql验证的话要把-E换成,-U (用户名),-P (密码) 以下是该工具的命令参数说明: -? 显示该工具的帮助功能; -S 后接的参数为数据库服务器的名称或者IP地址; -U 后接的参数为数据库的登陆用户名; -P 后接的参数为数据库的登陆密码; -E 使用当前登录用户的 Windows 集成认证进行身份验证。 -d 后接参数为对哪一个数据库采用SqlCacheDependency功能; -C 连接数据库的连接字符串。如果您指定服务器(-S)和登录(-U和-P,或 -E)信息,则此选项不是必需的,因为连接字符串已经包含这些信息。 -t 后接参数为对哪一个表采用SqlCacheDependency功能; -ed 允许对数据库使用SqlCacheDependency功能; -dd 禁止对数据库采用SqlCacheDependency功能; -et 允许对数据表采用SqlCacheDependency功能; -dt 禁止对数据表采用SqlCacheDependency功能; -lt 列出当前数据库中有哪些表已经采用sqlcachedependency功能。 第三步:在代码中使用缓存,并为其设置SqlCacheDependency依赖:
1 |
<div style="margin:0px;padding:0px;line-height:21px;"><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><summary></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"> 获取当前应用程序指定CacheKey的Cache对象值<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"></summary></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><param name="CacheKey"></span><span style="margin:0px;padding:0px;color:#008000;">索引键值</span><span style="margin:0px;padding:0px;color:#808080;"></param></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><returns></span><span style="margin:0px;padding:0px;color:#008000;">返回缓存对象</span><span style="margin:0px;padding:0px;color:#808080;"></returns></span><span style="margin:0px;padding:0px;color:#808080;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">public</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">static</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">object</span><span style="margin:0px;padding:0px;color:#000000;"> GetCache(</span><span style="margin:0px;padding:0px;color:#0000ff;">string</span><span style="margin:0px;padding:0px;color:#000000;"> CacheKey)<br style="margin:0px;padding:0px;line-height:10px;" />{<br style="margin:0px;padding:0px;line-height:10px;" /> System.Web.Caching.Cache objCache </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"> HttpRuntime.Cache;<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">return</span><span style="margin:0px;padding:0px;color:#000000;"> objCache[CacheKey];<br style="margin:0px;padding:0px;line-height:10px;" />}<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><summary></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"> 设置以缓存依赖的方式缓存数据<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"></summary></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><param name="CacheKey"></span><span style="margin:0px;padding:0px;color:#008000;">索引键值</span><span style="margin:0px;padding:0px;color:#808080;"></param></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><param name="objObject"></span><span style="margin:0px;padding:0px;color:#008000;">缓存对象</span><span style="margin:0px;padding:0px;color:#808080;"></param></span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#808080;">///</span><span style="margin:0px;padding:0px;color:#008000;"></span><span style="margin:0px;padding:0px;color:#808080;"><param name="cacheDepen"></span><span style="margin:0px;padding:0px;color:#008000;">依赖对象</span><span style="margin:0px;padding:0px;color:#808080;"></param></span><span style="margin:0px;padding:0px;color:#808080;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">public</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">static</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">void</span><span style="margin:0px;padding:0px;color:#000000;"> SetCache(</span><span style="margin:0px;padding:0px;color:#0000ff;">string</span><span style="margin:0px;padding:0px;color:#000000;"> CacheKey, </span><span style="margin:0px;padding:0px;color:#0000ff;">object</span><span style="margin:0px;padding:0px;color:#000000;"> objObject, System.Web.Caching.CacheDependency dep)<br style="margin:0px;padding:0px;line-height:10px;" />{<br style="margin:0px;padding:0px;line-height:10px;" /> System.Web.Caching.Cache objCache </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"> HttpRuntime.Cache;<br style="margin:0px;padding:0px;line-height:10px;" /> objCache.Insert(<br style="margin:0px;padding:0px;line-height:10px;" /> CacheKey,<br style="margin:0px;padding:0px;line-height:10px;" /> objObject,<br style="margin:0px;padding:0px;line-height:10px;" /> dep,<br style="margin:0px;padding:0px;line-height:10px;" /> System.Web.Caching.Cache.NoAbsoluteExpiration,</span><span style="margin:0px;padding:0px;color:#008000;">//</span><span style="margin:0px;padding:0px;color:#008000;">从不过期</span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#000000;"> System.Web.Caching.Cache.NoSlidingExpiration,</span><span style="margin:0px;padding:0px;color:#008000;">//</span><span style="margin:0px;padding:0px;color:#008000;">禁用可调过期</span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#000000;"> System.Web.Caching.CacheItemPriority.Default,<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">null</span><span style="margin:0px;padding:0px;color:#000000;">);<br style="margin:0px;padding:0px;line-height:10px;" />}<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">protected</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">void</span><span style="margin:0px;padding:0px;color:#000000;"> Page_Load(</span><span style="margin:0px;padding:0px;color:#0000ff;">object</span><span style="margin:0px;padding:0px;color:#000000;"> sender, EventArgs e)<br style="margin:0px;padding:0px;line-height:10px;" />{<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">string</span><span style="margin:0px;padding:0px;color:#000000;"> CacheKey </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#800000;">"</span><span style="margin:0px;padding:0px;color:#800000;">cachetest</span><span style="margin:0px;padding:0px;color:#800000;">"</span><span style="margin:0px;padding:0px;color:#000000;">;<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">object</span><span style="margin:0px;padding:0px;color:#000000;"> objModel </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"> GetCache(CacheKey);</span><span style="margin:0px;padding:0px;color:#008000;">//</span><span style="margin:0px;padding:0px;color:#008000;">从缓存中获取</span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">if</span><span style="margin:0px;padding:0px;color:#000000;"> (objModel </span><span style="margin:0px;padding:0px;color:#000000;">==</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">null</span><span style="margin:0px;padding:0px;color:#000000;">)</span><span style="margin:0px;padding:0px;color:#008000;">//</span><span style="margin:0px;padding:0px;color:#008000;">缓存里没有</span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#000000;"> {<br style="margin:0px;padding:0px;line-height:10px;" /> objModel </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"> GetData();</span><span style="margin:0px;padding:0px;color:#008000;">//</span><span style="margin:0px;padding:0px;color:#008000;">把当前时间进行缓存</span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">if</span><span style="margin:0px;padding:0px;color:#000000;"> (objModel </span><span style="margin:0px;padding:0px;color:#000000;">!=</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">null</span><span style="margin:0px;padding:0px;color:#000000;">)<br style="margin:0px;padding:0px;line-height:10px;" /> {<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#008000;">//</span><span style="margin:0px;padding:0px;color:#008000;">依赖数据库codematic中的P_Product表变化 来更新缓存</span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#000000;"> System.Web.Caching.SqlCacheDependency dep </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">new</span><span style="margin:0px;padding:0px;color:#000000;"> System.Web.Caching.SqlCacheDependency(</span><span style="margin:0px;padding:0px;color:#800000;">"</span><span style="margin:0px;padding:0px;color:#800000;">codematic</span><span style="margin:0px;padding:0px;color:#800000;">"</span><span style="margin:0px;padding:0px;color:#000000;">, </span><span style="margin:0px;padding:0px;color:#800000;">"</span><span style="margin:0px;padding:0px;color:#800000;">P_Product</span><span style="margin:0px;padding:0px;color:#800000;">"</span><span style="margin:0px;padding:0px;color:#000000;">);<br style="margin:0px;padding:0px;line-height:10px;" /> SetCache(CacheKey, objModel, dep);</span><span style="margin:0px;padding:0px;color:#008000;">//</span><span style="margin:0px;padding:0px;color:#008000;">写入缓存</span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#000000;"> }<br style="margin:0px;padding:0px;line-height:10px;" /> }<br style="margin:0px;padding:0px;line-height:10px;" /><br style="margin:0px;padding:0px;line-height:10px;" /> GridView1.DataSource </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"> (DataSet)objModel;<br style="margin:0px;padding:0px;line-height:10px;" /> GridView1.DataBind();<br style="margin:0px;padding:0px;line-height:10px;" />}<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#008000;">//</span><span style="margin:0px;padding:0px;color:#008000;">查询数据</span><span style="margin:0px;padding:0px;color:#008000;"><br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">private</span><span style="margin:0px;padding:0px;color:#000000;"> DataSet GetData()<br style="margin:0px;padding:0px;line-height:10px;" />{<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">string</span><span style="margin:0px;padding:0px;color:#000000;"> conString </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#800000;">"</span><span style="margin:0px;padding:0px;color:#800000;">data source=127.0.0.1;initial catalog=codematic;user id=sa;password=</span><span style="margin:0px;padding:0px;color:#800000;">"</span><span style="margin:0px;padding:0px;color:#000000;">;<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">string</span><span style="margin:0px;padding:0px;color:#000000;"> strSQL </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#800000;">"</span><span style="margin:0px;padding:0px;color:#800000;">SELECT * FROM P_Product</span><span style="margin:0px;padding:0px;color:#800000;">"</span><span style="margin:0px;padding:0px;color:#000000;">;<br style="margin:0px;padding:0px;line-height:10px;" /> SqlConnection myConnection </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">new</span><span style="margin:0px;padding:0px;color:#000000;"> SqlConnection(conString);<br style="margin:0px;padding:0px;line-height:10px;" /> DataSet ds </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">new</span><span style="margin:0px;padding:0px;color:#000000;"> DataSet();<br style="margin:0px;padding:0px;line-height:10px;" /> myConnection.Open();<br style="margin:0px;padding:0px;line-height:10px;" /> SqlDataAdapter adapter </span><span style="margin:0px;padding:0px;color:#000000;">=</span><span style="margin:0px;padding:0px;color:#000000;"></span><span style="margin:0px;padding:0px;color:#0000ff;">new</span><span style="margin:0px;padding:0px;color:#000000;"> SqlDataAdapter(strSQL, myConnection);<br style="margin:0px;padding:0px;line-height:10px;" /> adapter.Fill(ds, </span><span style="margin:0px;padding:0px;color:#800000;">"</span><span style="margin:0px;padding:0px;color:#800000;">Product</span><span style="margin:0px;padding:0px;color:#800000;">"</span><span style="margin:0px;padding:0px;color:#000000;">);<br style="margin:0px;padding:0px;line-height:10px;" /> myConnection.Close();<br style="margin:0px;padding:0px;line-height:10px;" /></span><span style="margin:0px;padding:0px;color:#0000ff;">return</span><span style="margin:0px;padding:0px;color:#000000;"> ds;<br style="margin:0px;padding:0px;line-height:10px;" />}</span></div> |
[…]
View Details