效果很好的asp.net的数据库访问模型(优化,封装一体化)

非常有效的数据库/配置文件访问模型。成功使用在几万流量的网站上。任何建议欢迎大家交流。

在使用SqlCommand对象过程中,我们需要分配Connection对象。 通常,对于大型的Entity业务模型来说分配新的SqlConnection的操作非常频繁。要利用Pool的优化功能,就要想到保持Connection对象。由此想到可以把Connection和Transaction都保存到ConnectionProxy对象中。而此对象继承IDisposable仅仅存在于一个Request过程中。作为一个适用广泛的模型,我们建立ExecutionContext对象来封装对ConnectionProxy操作。

以下是ConnectionProxy代码:

    internal class ConnectionProxy : IDisposable
    ...{
        private string _connectionString = null;
        private SqlConnection _connection;
        private SqlTransaction _transaction;
        private int _tranCount = 0;

        /**//// <summary>
        /// Constructs a new ConnectionProxy instance, setting the connection string
        /// </summary>
        /// <param name="ConnectionString">A valid database connection string</param>
        internal ConnectionProxy(string connectionString)
        ...{
            _connectionString = connectionString;
        }

        /**//// <summary>
        /// Frees any connection related resources
        /// </summary>
        public void Dispose()
        ...{
            // ensure that the connection does not have a pending transaction
            if (_tranCount != 0)
            ...{
                // rollback the transaction stack until the rollback already occurs
                while (_tranCount > 0) this.RollbackTransaction();

                throw new DataAccessException("Dispose was called on a connection with a pending transaction. The transaction will be aborted.");
            }

            // close the connection if it is open
            if ((_connection != null) && (_connection.State == ConnectionState.Open))
            ...{
                _connection.Close();
            }

            _connection = null;
        }

        /**//// <summary>
        /// Gets the current connection object
        /// </summary>
        internal SqlConnection Connection
        ...{
            get
            ...{
                // check that the connection string property has been set
                if (_connectionString == null)
                ...{
                    //throw new DataAccessException("Connection string has not been set.");
                }

                // create new connection and open if one does not yet exist
                if (_connection == null)
                ...{
                    _connection = new SqlConnection(_connectionString);
                    _connection.Open();
                    //while (_connection.State == ConnectionState.Open) ;
                }

                return _connection;
            }
        }

        /**//// <summary>
        /// Gets the current transaction context object
        /// </summary>
        internal SqlTransaction Transaction
        ...{
            get
            ...{
                return _transaction;
            }
        }

        /**//// <summary>
        /// Begins a new transaction
        /// </summary>
        internal void BeginTransaction()
        ...{
            // only actually begin a new transaction if a transaction context does not yet exist
            if (_tranCount == 0)
            ...{
                // create new transaction context at the specified isolation level
                _transaction = Connection.BeginTransaction(IsolationLevel.Serializable);
            }

            _tranCount++;
        }

        /**//// <summary>
        /// Commits a pending transaction
        /// </summary>
        internal void CommitTransaction()
        ...{
            // check that a transaction context actually exists
            if (_tranCount <= 0) throw new DataAccessException("No transaction is pending");

            _tranCount--;

            // check if an actual commit should occur
            if (_tranCount == 0)
            ...{
                // if trancount is zero, but we don't have a transaction then something is wrong
                if (_transaction == null)
                ...{
                    throw (new DataAccessException("Transaction stack indicated a commit but no transaction exists!"));
                }

                // actually commit the transaction
                _transaction.Commit();
                _transaction = null;
            }
        }

        /**//// <summary>
        /// Rolls back a pending transaction
        /// </summary>
        internal void RollbackTransaction()
        ...{
            // check that a transaction context actually exists
            if (_tranCount <= 0) throw new DataAccessException("No transaction is pending");

            _tranCount--;

            // check if an actual rollback should occur
            if (_tranCount == 0)
            ...{
                // if trancount is zero, but we don't have a transaction then something is wrong
                if (_transaction == null)
                ...{
                    throw (new DataAccessException("Transaction stack indicated a rollback but no transaction exists!"));
                }

                // actually rollback the transaction
                _transaction.Rollback();
                _transaction = null;
            }
        }
    }

之后我们可以建立ExecutionContext.目的是使用这个Proxy.当然也可以保存和使用其他的实例化对象:

    public sealed class ExecutionContext
    ...{
        private static string ConnProxy = "ConnProxy";
        private static string ConfigProxy = "Config";

        private static ConnectionProxy _ConnProxy;
        private static Config _Config;


        /**//// <summary>
        /// This class cannot be instantiated
        /// </summary>
        private ExecutionContext()
        ...{
        }

        /**//// <summary>
        /// 
        /// </summary>
        private static ConnectionProxy ConnectionProxy
        ...{
            get
            ...{
                if (HttpContext.Current != null) //web app
                    return (ConnectionProxy)HttpContext.Current.Items[ConnProxy];
                else
                    return _ConnProxy;
            }
            set
            ...{
                if(HttpContext.Current != null) //web app
                    HttpContext.Current.Items.Add(ConnProxy, value);
                else
                    _ConnProxy = value;
            }
        }

        private static Config Config
        ...{
            get
            ...{
                if (HttpContext.Current != null) //web app
                    return (Config)HttpContext.Current.Items[ConfigProxy];
                else
                    return _Config;
            }
            set
            ...{
                if (HttpContext.Current != null) //web app
                    HttpContext.Current.Items.Add(ConfigProxy, value);
                else
                    _Config = value;
            }
        }

        /**//// <summary>
        /// Returns the connection object for the current execution context
        /// </summary>
        public static SqlConnection Connection
        ...{
            get
            ...{
                AssertInitialisation();
                return ConnectionProxy.Connection;
            }
        }

        /**//// <summary>
        /// Returns the current transaction object for the current execution context
        /// </summary>
        public static SqlTransaction Transaction
        ...{
            get
            ...{
                AssertInitialisation();
                return ConnectionProxy.Transaction;
            }
        }

        /**//// <summary>
        /// </summary>
        public static Config Configuration
        ...{
            get
            ...{
                if (Config == null)
                    throw new Exception("Config.xml cannot be loaded!");
                return Config;
            }
        }
        /**//// <summary>
        /// Begins a new execution context
        /// </summary>
        public static void Begin()
        ...{
            // cleanup from any previous Begin calls
            End();

            // create a configuration object
            Config = new Config();

            // create a new database connection proxy
            ConnectionProxy = new ConnectionProxy(Config.ConnectionString);
            
        }

        /**//// <summary>
        /// Ends the current execution context and cleans up any resources used
        /// </summary>
        public static void End()
        ...{
            // clean up any objects that have not been cleaned up since the last Begin call on the thread
            if (ConnectionProxy != null) ConnectionProxy.Dispose();

            if (HttpContext.Current != null) //web app
            ...{
                HttpContext.Current.Items.Remove(ConnProxy);
                HttpContext.Current.Items.Remove(ConfigProxy);
            }
        }

        /**//// <summary>
        /// Begins a new transaction
        /// </summary>
        public static void BeginTransaction()
        ...{
            AssertInitialisation();
            ConnectionProxy.BeginTransaction();
        }

        /**//// <summary>
        /// Commits the current transaction
        /// </summary>
        public static void CommitTransaction()
        ...{
            AssertInitialisation();
            ConnectionProxy.CommitTransaction();
        }

        /**//// <summary>
        /// Rolls back the current transaction
        /// </summary>
        public static void RollbackTransaction()
        ...{
            AssertInitialisation();
            ConnectionProxy.RollbackTransaction();
        }

        /**//// <summary>
        /// Asserts that the execution context has been correctly initialised
        /// </summary>
        private static void AssertInitialisation()
        ...{
            if (ConnectionProxy == null)
            ...{
                throw new ExecutionContextException("Execution Context has not been initialised.");
            }
        }
    }

使用的时候,要在Global.asax的Application_BeginRequest中加入:ExecutionContext.Begin();和Application_EndRequest中加入:ExecutionContext.End();也可以在WinForm程序的Application中加入这2行。

准备工作完成后我们就可以来测试了:

            ExecutionContext.BeginTransaction();
            try
            ...{
                cmd.Connection = ExecutionContext.Connection;
                cmd.Transaction = ExecutionContext.Transaction;
                cmd.ExecuteNonQuery();

                ExecutionContext.CommitTransaction();
            }
            catch
            ...{
                ExecutionContext.RollbackTransaction();
                throw;
            }

总结:
非常有效的数据库/配置文件访问模型。成功使用在几万流量的网站上。任何建议欢迎大家交流。

posted on 2007-01-12 17:44 LeeLin 阅读(...) 评论(...) 编辑 收藏

转载于:https://www.cnblogs.com/lilin617/archive/2007/01/12/619118.html

效果很好的asp.net的数据库访问模型(优化,封装一体化)相关推荐

  1. 面向程序员的数据库访问性能优化法则

    面向程序员的数据库访问性能优化法则 特别说明: 1.   本文只是面对数据库应用开发的程序员,不适合专业 DBA , DBA 在数据库性能优化方面需要了解更多的知识: 2.   本文许多示例及概念是基 ...

  2. 简单程序所需要的简单 asp.net通用数据库访问类

    简单程序不需要分层,各页面共用相同的通用数据库访问类即可 using System;  using System.Data;  using System.Data.SqlClient; namespa ...

  3. 「数据库系列杂谈」数据库访问性能优化

    为什么要优化 系统的吞吐量瓶颈往往出现在数据库的访问速度上 随着应用程序的运行,数据库的中的数据会越来越多,处理时间会相应变慢 数据是存放在磁盘上的,读写速度无法和内存相比 一.数据库访问优化法则简介 ...

  4. 基于SqlSugar的数据库访问处理的封装,支持多数据库并使之适应于实际业务开发中

    Python微信订餐小程序课程视频 https://edu.csdn.net/course/detail/36074 Python实战量化交易理财系统 https://edu.csdn.net/cou ...

  5. mysql部门人员排序设计_MySQL数据库访问性能优化

    MYSQL应该是最流行的WEB后端数据库.大量应用于PHP,Ruby,Python,Java 等Web语言开发项目中,无论NOSQL发展多么快,都不影响大部分架构师选择MYSQL作为数据存储. MYS ...

  6. 数据库访问性能优化法则

    特别说明: 1.  本文只是面对数据库应用开发的程序员,不适合专业DBA,DBA在数据库性能优化方面需要了解更多的知识: 2.  本文许多示例及概念是基于Oracle数据库描述,对于其它关系型数据库也 ...

  7. 【转】面向程序员的数据库访问性能优化法则

    特别说明: 1.  本文只是面对数据库应用开发的程序员,不适合专业DBA,DBA在数据库性能优化方面需要了解更多的知识: 2.  本文许多示例及概念是基于Oracle数据库描述,对于其它关系型数据库也 ...

  8. Oracle数据库访问性能优化

    一.百万级数据库优化方案 1.对查询进行优化,要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断 ...

  9. 数据库访问性能优化(转)

    特别说明: 1.  本文只是面对数据库应用开发的程序员,不适合专业DBA,DBA在数据库性能优化方面需要了解更多的知识: 2.  本文许多示例及概念是基于Oracle数据库描述,对于其它关系型数据库也 ...

最新文章

  1. Tengine Web服务器概述
  2. displaytag 导出
  3. 从计算机视觉(slam)和摄影测量两个维度进行BA算法原理推导
  4. python学习之-- mysql模块和sqlalchemy模块
  5. 【转】MyBatis缓存机制
  6. javascript中的undefined 和 not defined
  7. linux java heap space_Linux tomcat9 java.lang.OutOfMemoryError: Java heap space 解决方法
  8. iphonexr电池容量_iPhone12mini电池容量多少毫安能用多久 iPhone12mini适合打游戏王者吗...
  9. C. Oh Those Palindromes
  10. el表达式里面fn的用法
  11. 不懂代码也想学会深度学习?这本书告诉你真的很简单
  12. 基于nvidia的ffmpeg编解码加速
  13. MAC地址了解(根据设备MAC地址查询生产厂商信息)
  14. [翻译] LaTeX Error: Can be used only in preamble
  15. 只要 Github 域名指向任意 IP,该 IP 的 443 端口就会超时 3 分钟(TCPing, 80 端口正常)
  16. 《从零开始做运营(张亮)》读书笔记
  17. 未找到beta版怎么解决_Chrome这设计硬伤实在太难用!用它完美解决
  18. 为什么一提到苹果就想到乔布斯,蒂姆·库克的事迹你知道多少?
  19. 【转载】【常见缺陷分析技术】基于ODC的软件缺陷度量研究
  20. Relative Orientation 与fundamental essential matrix

热门文章

  1. UI设计培训之UI设计系统知识
  2. unity加载ab后,场景shader不起效问题(物件表现黑色)
  3. 无法访问D盘,执行页内操作时的错误
  4. 【开源】博客园文章编辑器4.0版发布
  5. UVA 1482 - Playing With Stones(SG打表规律)
  6. 哪些听起来像段子一样的故事?
  7. Vue从Hello World到打包(后端适读)
  8. CentOS 6.4下PXE+Kickstart无人值守安装操作系统
  9. 【Stage3D学习笔记续】山寨Starling(八):核心优化(批处理)的实现
  10. Linux之bash编程基本语法