十二、EnterpriseFrameWork框架核心类库之与EntLib结合

从本章开始对框架的讲叙开始进入核心类库的讲解,前面都是对框架外在功能讲解,让人有个整体的概念,知道包含哪些功能与对系统开发有什么帮助。以后多章都是讲解核心类库的,讲解的方式基本按照代码的目录结构,这样阅读代码的时候也可以针对性看;还有就是为了更好理解文章中的内容把目前还不够完善的源代码发布,这个版本Winform部分基本可以直接运行,而Web部分与WCF部分的控制器代码没有完成,所以暂时还运行不起来,不过这并不影响学习核心类库,再就是尽快在下个版本发布一个完整版本给大家;

EnterpriseFrameWork框架源代码V1.0下载http://pan.baidu.com/s/1pJsMLlx

核心类库EFWCoreLib目录结构

EnterpriseFrameWork框架的底层功能是使用微软企业库(EntLib)来实现的,包括使用EntLib的The Data Access Application Block实现数据库访问,The Caching Application Block进行缓存管理,The Exception Handling Application Block进行异常处理,The Logging Application Block进行日志记录,Unity Dependency Injection and Interception依赖注入容器进行对象映射;在这些功能之上再进行了一次封装,让我们再编写代码过程中更简单的运用,还有就算EntLib以后升级也不需要修改系统中的代码;

微软企业库的一些学习资料:

Enterprise Library 5.0.msi安装包:http://pan.baidu.com/s/1gdnDz7l

Enterprise Library 5.0说明文档:http://pan.baidu.com/s/1pJjtvCZ

CHM版说明文档:http://pan.baidu.com/s/1c0rhtba

学习实例代码:http://pan.baidu.com/s/1dDthk3Z

Enterprise Library 5.0源代码:http://pan.baidu.com/s/1mgKDot6

黄聪:Enterprise Library 5.0 系列教程:http://www.cnblogs.com/huangcong/archive/2010/06/08/1753988.html

一、EntLib配置文件

我们先看web项目Web.config中对EntLib的配置,Winform项目中的是App.config

其中标记的红色部分指定了EntLib的完整配置文件Entlib.config,

<configuration>
  <configSections>
    <section name="exceptionHandling" type="Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Configuration.ExceptionHandlingSettings, Microsoft.Practices.EnterpriseLibrary.ExceptionHandling, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
    <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" />
    <section name="loggingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.LoggingSettings, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
    <section name="cachingConfiguration" type="Microsoft.Practices.EnterpriseLibrary.Caching.Configuration.CacheManagerSettings, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" requirePermission="true" />
  </configSections>

  <dataConfiguration defaultDatabase="SQL2005" />

  <connectionStrings>
    <add name="SQL2005" connectionString="Data Source=.;Initial Catalog=3yxx_Cssd;User ID=sa;pwd=1;"
     providerName="System.Data.SqlClient" />
  </connectionStrings>
  <exceptionHandling>
    <exceptionPolicies>
      <add name="HISPolicy">
        <exceptionTypes>
          <add name="All Exceptions" type="System.Exception, mscorlib, Version=2.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="FileLog" 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>
  <loggingConfiguration name="" tracingEnabled="true" defaultCategory="ConsoleLog">
    <listeners>
      <add listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.CustomTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
          type="EFWCoreLib.CoreFrame.EntLib.Log.TraceListeners.ConsoleTraceListener, EFWCoreLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
          traceOutputOptions="None" name="ConsoleTraceListener" />
      <add listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.CustomTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
          type="EFWCoreLib.CoreFrame.EntLib.Log.TraceListeners.FileTraceListener, EFWCoreLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
          name="FileTraceListener" />
      <add listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.CustomTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
          type="EFWCoreLib.CoreFrame.EntLib.Log.TraceListeners.DatabaseTraceListener, EFWCoreLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
          name="DatabaseTraceListener" />
      <add name="Email Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.EmailTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
          listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.EmailTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
          toAddress="[email protected]" fromAddress="[email protected]"
          filter="Off" />
      <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" filter="Error" />
      <add name="Flat File Trace Listener" type="Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
          listenerDataType="Microsoft.Practices.EnterpriseLibrary.Logging.Configuration.FlatFileTraceListenerData, Microsoft.Practices.EnterpriseLibrary.Logging, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
          fileName="trace.log" formatter="Text Formatter" />
    </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}
Message: {message}{newline}
Category: {category}{newline}
Priority: {priority}{newline}
EventId: {eventid}{newline}
Severity: {severity}{newline}
Title:{title}{newline}
Machine: {localMachine}{newline}
App Domain: {localAppDomain}{newline}
ProcessId: {localProcessId}{newline}
Process Name: {localProcessName}{newline}
Thread Name: {threadName}{newline}
Win32 ThreadId:{win32ThreadId}{newline}
Extended Properties: {dictionary({key} - {value}{newline})}"
          name="Text Formatter" />
      <add type="EFWCoreLib.CoreFrame.EntLib.Log.Formatters.ZhyTextFormatter, EFWCoreLib, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
          name="ZhyTextFormatter" />
    </formatters>
    <categorySources>
      <add switchValue="All" name="ConsoleLog">
        <listeners>
          <add name="ConsoleTraceListener" />
        </listeners>
      </add>
      <add switchValue="All" name="FileLog">
        <listeners>
          <add name="Flat File Trace Listener" />
        </listeners>
      </add>
      <add switchValue="All" name="DatabaseLog">
        <listeners>
          <add name="DatabaseTraceListener" />
        </listeners>
      </add>
      <add switchValue="All" name="EmailLog">
        <listeners>
          <add name="Email 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" />
        </listeners>
      </errors>
    </specialSources>
  </loggingConfiguration>
  <cachingConfiguration defaultCacheManager="Cache Manager">
    <cacheManagers>
      <add name="Cache Manager" type="Microsoft.Practices.EnterpriseLibrary.Caching.CacheManager, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
          expirationPollFrequencyInSeconds="60" maximumElementsInCacheBeforeScavenging="1000"
          numberToRemoveWhenScavenging="10" backingStoreName="NullBackingStore" />
    </cacheManagers>
    <backingStores>
      <add type="Microsoft.Practices.EnterpriseLibrary.Caching.BackingStoreImplementations.NullBackingStore, Microsoft.Practices.EnterpriseLibrary.Caching, Version=5.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
          name="NullBackingStore" />
    </backingStores>
  </cachingConfiguration>
</configuration>

Entlib.config包含了四个节点exceptionHandling、dataConfiguration、loggingConfiguration和cachingConfiguration,分别是对异常的配置、数据库的配置、日志的配置和缓存的配置;其实EntLib.Config配置文件的内容可以集成在Web.config和App.Config的配置文件中,就不需要配置filePath路径,但是分成独立的文件维护起来肯定更方便;

这里有个问题,就是那个filePath指定路径,Web项目一定要指定绝对路径,而Winform项目指定相对路径又可以,绝对路径太麻烦了代码换个地方又要修改此路径;有人解决过的请告诉我一声;

除了上面两处配置,还有一个配置文件EFWUnity.config,涉及到依赖注入的对象需要在此文件中添加配置;

<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration, Version=2.0.414.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
  </configSections>
  <unity>
    <assembly name="Books"/>
    <namespace name="Books.Dao"/>
    <container>
      <register type="IBookDao" mapTo="SqlBookDao"></register>
    </container>
  </unity>
</configuration>

其中EntLib配置文件除了手工修改,企业库还提供了可视化工具进行配置,基本上在项目中这些配置都不需要修改;如果是Winform版针对数据库连接字符串需要加密的话,可能需要工具配置一下,EntLib工具提供了加密的功能;

二、对EntLib进行封装

为了使调用EntLib的更方便,还有就是以后EntLib升级的话不需要修改太多地方,所以对EntiLib进一步封装;

所有EntLib对象创建都通过ZhyContainer对象

/// <summary>
    /// 封装企业库容器
    /// </summary>
    public class ZhyContainer
    {
        public static IUnityContainer container = null;
        /// <summary>
        /// 获取依赖注入容器
        /// </summary>
        /// <returns></returns>
        public static IUnityContainer CreateUnity()
        {
            container = new UnityContainer();
            return container;
        }

        public static void AddUnity(UnityConfigurationSection section)
        {
            if (container == null) CreateUnity();
            container.LoadConfiguration(section);
        }

        /// <summary>
        /// 获取数据库对象
        /// </summary>
        /// <returns>数据库对象</returns>
        public static Database CreateDataBase()
        {
            return EnterpriseLibraryContainer.Current.GetInstance<Database>();
        }
        /// <summary>
        /// 获取数据库对象
        /// </summary>
        /// <param name="name">数据库实例名(默认name为空,调用默认数据库实例)</param>
        /// <returns>数据库对象</returns>
        public static Database CreateDataBase(string name)
        {
            return EnterpriseLibraryContainer.Current.GetInstance<Database>(name);
        }
        /// <summary>
        /// 获取日志写入对象
        /// </summary>
        /// <returns></returns>
        public static LogWriter CreateLog()
        {
            return EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
        }

        public static LogWriter CreateLog(string name)
        {
            return EnterpriseLibraryContainer.Current.GetInstance<LogWriter>(name);
        }
        /// <summary>
        /// 获取日志跟踪对象
        /// </summary>
        /// <returns></returns>
        public static TraceManager CreateTrace()
        {
            return EnterpriseLibraryContainer.Current.GetInstance<TraceManager>();
        }
        /// <summary>
        /// 获取异常处理对象
        /// </summary>
        /// <returns></returns>
        public static ExceptionManager CreateException()
        {
            return EnterpriseLibraryContainer.Current.GetInstance<ExceptionManager>();
        }

        public static ICacheManager cacheManager = null;
        /// <summary>
        /// 获取缓存对象
        /// </summary>
        /// <returns></returns>
        public static ICacheManager CreateCache()
        {

            cacheManager = CacheFactory.GetCacheManager();
            return cacheManager;
        }

        public static ICacheManager CreateCache(string name)
        {
            cacheManager = EnterpriseLibraryContainer.Current.GetInstance<ICacheManager>(name);
            return cacheManager;
        }
    }

针对EntLib缓存对象ICacheManager的操作封装成CacheHelper对象

 /// <summary>
    /// 缓存操作类
    /// </summary>
    public static class CacheHelper
    {
        private static ICacheManager cache = ZhyContainer.CreateCache();
        /// <summary>
        /// 添加缓存
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        public static void Add(string key, object value)
        {
            cache.Add(key, value);
        }

        /// <summary>
        /// 添加缓存
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="value">值</param>
        /// <param name="isRefresh">是否刷新</param>
        public static void Add(string key, object value, bool isRefresh)
        {
            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 bool Contains(string key)
        {
            return cache.Contains(key);
        }

        /// <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);
        }
    }

针对EntLib日志跟踪记录操作封装成LogHelper对象

/// <summary>
    /// 日志操作类
    /// </summary>
    public static class LogHelper
    {
        private static LogWriter logw = ZhyContainer.CreateLog();
        private static TraceManager traceMgr = ZhyContainer.CreateTrace();
        private static LogEntry loge = new LogEntry();
        /// <summary>
        /// 开始跟踪
        /// </summary>
        /// <returns></returns>
        public static Tracer StartTrace()
        {
            return traceMgr.StartTrace(Category.FileLog);
        }
        /// <summary>
        /// 结束跟踪
        /// </summary>
        /// <param name="trace"></param>
        public static void EndTrace(Tracer trace)
        {
            trace.Dispose();
        }

    }

三、EntLib实现数据库访问

使用EntLib对数据库的访问非常简单,先创建一个数据库对象Database

public SqlServerDb(string key)
            : base()
        {

            database = ZhyContainer.CreateDataBase(key);
            _connString = database.ConnectionString;
          }

利用Database对象执行SQL语句

  public override int DoCommand(string commandtext)
        {
            if (isInTransaction)
            {
                command = database.GetSqlStringCommand(commandtext);
                command.Connection = connection;
                command.Transaction = transaction;
                command.CommandType = CommandType.Text;
                return database.ExecuteNonQuery(command,transaction);
            }
            else
            {
                return database.ExecuteNonQuery(CommandType.Text, commandtext);
            }
          }

当初让我使用EntLib的最重要的原因就是它支持多数据库访问与数据库连接池。数据库连接是有限资源,它们的妥善管理对可扩展的应用程序来说是非常重要的,传统的DbHelper都是在使用完后必须关闭和释放资源,而使用企业库中的Database对象操作数据库我们不用自己处理,企业库会自动处理。

EntLib数据访问程序块资料参考:http://www.cnblogs.com/shanyou/archive/2008/05/25/1206898.html

四、EntLib实现错误日志记录

程序中记录日志是很重要的,好的日志记录方式可以提供我们足够多定位问题的依据;如果只是单独需要日志功能个人推荐Log4net,使用起来更简单;

先看记录的日志文件内容,日志文件是放在根目录的trace.log文件中

五、EntLib实现缓存管理

       在构建企业级分布式应用程序时,架构师和开发人员面临着许多难题。缓存可以帮助您克服其中的一些难题,包括:

性能:通过存储与数据使用者尽可能接近的相关数据,缓存可以提高应用程序的性能。这样可以避免重复进行数据创建、处理和传输。

可伸缩性:在缓存中存储信息有助于节省资源,并且可以随着应用程序需求的增加来提高可伸缩性

可用性:通过将数据存储在本地缓存中,应用程序可以承受系统的故障,例如网络等待时间、Web 服务问题以及硬件故障

其实我使用缓存想法很简单,就是全局访问的数据我都存入缓存中,不用缓存也能解决那你得定义很多静态公共变量,但这个代码实现起来比较麻烦;

1)框架中ORM模块对实体的自定义标签配置用到了缓存

cache.Add("entityAttributeList", entityAttributeList);

2)控制器中对配置的内容也用到了缓存

cache.Add("cmdWebController", cmdControllerList);

六、EntLib实现AOP与对象创建

框架中基于EntLib的AOP实现比较简单,先看如何使用AOP:

上面是数据库事务处理利用AOP拦截方法实现;

1)定义自定义标签AOPAttribute

/// <summary>
    /// AOP标签
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method | AttributeTargets.Property |AttributeTargets.Interface)]
    public class AOPAttribute : HandlerAttribute
    {
        private List<Type> _types;
        /// <summary>
        /// 创建AOPAttribute实例
        /// </summary>
        /// <param name="types">AOP操作类类型数组</param>
        public AOPAttribute(params Type[] types)
        {
            _types = types.ToList();
        }
        /// <summary>
        /// 创建AOP管理对象
        /// </summary>
        /// <param name="container">示例容器</param>
        /// <returns></returns>
        public override ICallHandler CreateHandler(Microsoft.Practices.Unity.IUnityContainer container)
        {
            if (_types.Count > 0)
            {
                return new AopCallHandler(_types);
            }

            return null;
        }
    }

2)AOP操作接口,包括前处理和后处理

  /// <summary>
    /// IAopOperator AOP操作符接口,包括前处理和后处理
    /// </summary>
    public interface IAopOperator
    {
        /// <summary>
        /// 前处理
        /// </summary>
        /// <param name="input"></param>
        void PreProcess(IMethodInvocation input);
        /// <summary>
        /// 后处理
        /// </summary>
        /// <param name="input"></param>
        /// <param name="result"></param>
        void PostProcess(IMethodInvocation input, IMethodReturn result);
    }

3)AOP调用管理类

/// <summary>
    /// AOP调用管理类
    /// </summary>
    public class AopCallHandler : ICallHandler
    {
        private List<IAopOperator> _list;  //AOP操作对象列表
        /// <summary>
        /// 创建AopCallHandler实例
        /// </summary>
        /// <param name="list">AOP操作类类型列表</param>
        public AopCallHandler(List<Type> list)
        {
            _list = new List<IAopOperator>();
            for (int i = 0; i < list.Count; i++)
            {
                _list.Add((IAopOperator)Activator.CreateInstance(list[i]));
            }
        }
        #region ICallHandler 成员
        /// <summary>
        /// 调用执行
        /// </summary>
        /// <param name="input"></param>
        /// <param name="getNext"></param>
        /// <returns></returns>
        public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
        {
            IMethodReturn result;
            for (int i = 0; i < _list.Count; i++)
            {
                _list[i].PreProcess(input);
            }
            //log
            result = getNext()(input, getNext);
            //if (result.Exception == null)
            //{
            //    Logger.Write("Action Done.");
            for (int i = _list.Count - 1; i >= 0; i--)
            {
                _list[i].PostProcess(input, result);
            }
            //}
            //log

            return result;
        }
        /// <summary>
        /// 执行顺序
        /// </summary>
        public int Order
        {
            get;
            set;
        }

        #endregion
    }

4)最后创建一个AOP事务处理类,继承接口IAopOperator功能在前处理和后处理两个方法中实现

public class AopTransaction : IAopOperator
    {
        public AopTransaction()
        {
        }

        #region IAopOperator 成员

        public void PreProcess(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation input)
        {
            List<AbstractDatabase> _RdbList = ((IbindDb)input.Target).GetMoreDb();
            AbstractDatabase Rdb = ((IbindDb)input.Target).GetDb();
            if (_RdbList == null)
            {
                Rdb.BeginTransaction();
            }
            else
            {
                foreach (AbstractDatabase db in _RdbList)
                {
                    db.BeginTransaction();
                }
            }
        }

        public void PostProcess(Microsoft.Practices.Unity.InterceptionExtension.IMethodInvocation input, Microsoft.Practices.Unity.InterceptionExtension.IMethodReturn result)
        {
            List<AbstractDatabase> _RdbList = ((IbindDb)input.Target).GetMoreDb();
            AbstractDatabase Rdb = ((IbindDb)input.Target).GetDb();
            if (_RdbList == null)
            {
                if (result.Exception == null)
                {
                    Rdb.CommitTransaction();
                }
                else
                {
                    Rdb.RollbackTransaction();
                }
            }
            else
            {
                List<AbstractDatabase> RdbList = new List<AbstractDatabase>();
                foreach (AbstractDatabase db in _RdbList)
                {
                    RdbList.Add(db);
                }
                RdbList.Reverse();//反序

                if (result.Exception == null)
                {
                    foreach (AbstractDatabase db in RdbList)
                    {
                        db.CommitTransaction();
                    }
                }
                else
                {
                    foreach (AbstractDatabase db in RdbList)
                    {
                        db.RollbackTransaction();
                    }
                }
            }
        }

        #endregion
    }

EntLib实现AOP学习参考:http://www.cnblogs.com/artech/archive/2008/11/27/1342309.html

利用EntLib的Unity创建逻辑层对象,比如Dao对象、ObjectModel对象,这些对象都不能用new关键字来创建;

Book book = NewObject<Book>();
public T NewObject<T>()
        {
            T t = FactoryModel.GetObject<T>(_oleDb,_container, null);
            return t;
        }
public static T GetObject<T>(AbstractDatabase Db,IUnityContainer _container, string unityname)
        {
            if (Db == null)
            {
                EFWCoreLib.CoreFrame.DbProvider.AbstractDatabase Rdb = EFWCoreLib.CoreFrame.DbProvider.FactoryDatabase.GetDatabase();
                //SysLoginRight currLoginUser = (SysLoginRight)EFWCoreLib.CoreFrame.Init.AppGlobal.cache.GetData("RoleUser");
                //Rdb.WorkId = currLoginUser.WorkId;
                Db = Rdb;
                _container = EFWCoreLib.CoreFrame.Init.AppGlobal.container;
            }

            //读unity配置文件把类注入到接口得到对象实例
            IUnityContainer container = _container;

            T t = default(T);
            if (unityname == null)
                t = container.Resolve<T>();
            else
                t = container.Resolve<T>(unityname);

            IbindDb ibind = (IbindDb)t;
            ibind.BindDb(Db,container);

            //给对象加上代理
            t = (T)PolicyInjection.Wrap(t.GetType(), t);
            return t;
        }
时间: 2024-10-19 04:21:41

十二、EnterpriseFrameWork框架核心类库之与EntLib结合的相关文章

十八、EnterpriseFrameWork框架核心类库之Winform控制器

回<[开源]EnterpriseFrameWork框架系列文章索引> EFW框架源代码下载:http://pan.baidu.com/s/1qWJjo3U EFW框架中的WinController控制器可以说是整个Winform版中最具有价值的地方,能够熟练使用它的话,可以让你写得代码结构清晰不知多少倍,真正的做到了CS开发的界面层与逻辑层的完全隔离:更重要的是改变了你写界面代码的思维,让你一次性写出功能完善的代码,真的,传统的那种事件驱动的方式编码会让你的代码变得越来越臃肿,就算你懂得不断重

十六、【适合中小企业的.Net轻量级开源框架】EnterpriseFrameWork框架核心类库之单点登录SSO

回<[开源]EnterpriseFrameWork框架系列文章索引> EFW框架源代码下载:http://pan.baidu.com/s/1qWJjo3U 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一.SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统. 如上图,当用户第一次访问应用系统1的时候,因为还没有登录,会被引导到认证系统中进行登录:根据用户提供的登录信息,认证系统进行身份校验,如果通过校验,应该返

十七、EnterpriseFrameWork框架核心类库之Web控制器

回<[开源]EnterpriseFrameWork框架系列文章索引> EFW框架源代码下载:http://pan.baidu.com/s/1qWJjo3U EFW框架中的WebController就是解决JqueryEasyUI与逻辑层的交互,之间的数据是通过Json字符串来传递:值得注意的是WebController的代码一定不要和EFWWeb项目放在一起,你可以单独建一个项目类库,也可以和逻辑层项目放一起:在EFWWeb项目不要编写任何C#代码,这个在前面的文章中就提过,可以让你的Web项

十五、EnterpriseFrameWork框架核心类库之系统启动入口与初始化

本章内容是讲三种开发模式,web模式.Winform模式和Wcf模式的系统启动入口有什么区别,以及启动后系统初始化的内容:为什么要把这些单独提出来讲一章,因为我觉得本章非常重要,我们都知道程序中的main()函数,称之为主函数,是所有程序运行的入口:当你拿着一个程序肯定是从这个函数开始阅读,慢慢的深入了解整个程序的运行流程:而光看那些功能代码块是掌握不了系统运行时的一些机制的: 只有掌握本章的内容后,那么在以后项目中遇到的问题基本上都能直接定位,并找到产生的原因,不然你会觉得所有产生的问题都莫名

十四、EnterpriseFrameWork框架核心类库之简易ORM

在写本章前先去网上找了一下关于ORM的相关资料,以为本章做准备,发现很多东西今天才了解,所以在这里也对ORM做不了太深入的分析,但还是浅谈一下EFW框架中的设计的简易ORM:文中有一点讲得很有道理,Dao与ORM的区别,Dao是对数据库操作的封装,编写的代码方式像一种设计方法,而ORM支持对象与数据结构的映射,更像一种代码开发工具,有了这个工具会让我们开发代码更简单方便:但是同一类工具有简单的也有复杂的,比如文字工具有简单的Notepad,也有复杂的Word,不是说有了复杂的简单的工具就不需要了

十三、EnterpriseFrameWork框架核心类库之数据库操作(多数据库事务处理)

本章介绍框架中封装的数据库操作的一些功能,在实现的过程中费了不少心思,针对不同数据库的操作(SQLServer.Oracle.DB2)这方面还是比较简单的,用工厂模式就能很好解决,反而是在多数据库同时操作方面走了不少弯路:现在从以下几个方面进行说明: 一.不同数据库操作 此处用到了工厂模式来实现不同数据库操作,看下图 AbstractDatabase是一个抽象类,定义了所有对数据库的操作抽象方法,包括执行一个SQL语句.执行存储过程.事务操作等 [Serializable] public abs

十、EnterpriseFrameWork框架的分层架构及意义(控制器、业务对象、实体、Dao之间关系)

本章内容主要包括两个方面,一是框架分层(控制器.业务对象.实体.Dao)的详细说明,二是对比常用三层结构的区别和优势: 我们先看一下前面实例中的解决方案目录: 我们再看各层之间的调用关系: 上图描叙的控制器有四种方式来操作数据库, 1)控制器调用实体,通过框架中的ORM来实现单表的操作 2)控制器直接操作数据库对象(oleDB),通过编写SQL语句访问数据库 3)控制器通过调用Dao操作数据库 4)控制器调用业务对象,业务对象再调用Dao操作数据库 还有就是每一层在程序结构中承担的角色: 一.D

二十、【.Net开源】EFW框架核心类库之WebService服务

回<[开源]EFW框架系列文章索引> EFW框架源代码下载V1.1:http://pan.baidu.com/s/1qWJjo3U EFW框架实例源代码下载:http://pan.baidu.com/s/1o6MAKCa EFW框架中的WebService服务开发方式与传统的net项目中开发不太一样,传统的开发方式虽然也挺简单但在后面的发布部署还是挺麻烦的,而在EFW框架中开发Webservice就跟编写普通的C#代码一样,并不需要单独建WebService服务项目,不需要Asmx文件:所以发

十九、【.Net开源】EFW框架核心类库之WCF控制器

回<[开源]EFW框架系列文章索引> EFW框架源代码下载V1.1:http://pan.baidu.com/s/1qWJjo3U EFW框架实例源代码下载:http://pan.baidu.com/s/1o6MAKCa 只有当你需要开发三层架构的系统并利用WCF作为系统的中间件,那么就需要使用WCF控制器.EFW框架中的Wcf控制器分为两个部分WcfClientController和WcfController,两者利用Wcf服务进行通讯,其中WcfClientController的功能与上章