当前位置: 首页 > 编程日记 > 正文

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

效果很好的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 > 0this.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 <= 0throw 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 <= 0throw 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

相关文章:

【技巧——windows】直接登陆到桌面,免去输入密码

关于这个问题其实我很早之前就研究过&#xff0c;只是一直都是弄一次就不管了&#xff0c;下次就忘记怎么弄了&#xff0c;又去查&#xff0c;现在就写个笔记吧。 win8/8.1 在开始的界面输入netplwiz&#xff0c;或者点击winr打开运行&#xff0c;输入netplwiz&#xff0c;然后…

虚商烦恼多?不在怕的!你距离享受高效虚商控制台只差一步的距离

摘要&#xff1a;虚商烦恼多&#xff1f;不在怕的&#xff01;你距离享受高效虚商控制台只差一步的距离虚商自助服务平台 vco.console.aliyun.com/原文链接本文为云栖社区原创内容&#xff0c;未经允许不得转载

Shark Hive Spark Hadoop2 进行整合的测试。

本文目的是测试将shark和hadoop2进行整合。 本来打算使用Shark 最新版0.9.0 &#xff0c;但是官方好像还没有针对与Hadoop2的正式下载地址。&#xff08;这个要说明一下&#xff0c;官方只提供了源码&#xff0c;并没有找到编译好的0.9.0 for hadoop2 &#xff0c;也许需要自己…

nginx反向代理-多端口映射

2019独角兽企业重金招聘Python工程师标准>>> 代码解释 1.1 http:www.baidu.test.com默认是80&#xff0c;访问“/”利用反向代理&#xff0c;然后访问本地8083&#xff1b; 1.2 8083代表本地的前端工程访问地址&#xff0c;前端需要访问后台数据&#xff0c;”/”…

程序员期末试卷_第三部分复习提纲.doc下载

程序员期末试卷_第三部分复习提纲.doc下载 转载于:https://www.cnblogs.com/dtdnh520/archive/2007/01/20/625390.html

IDEA IntelliJ 如何新建一个不用任何框架的web项目

step 1 step 2 step 3 step 4 step 5 step 6 结果&#xff1a; 导包 找到jsp-api.jar和servlet-api.jar 建包&#xff08;web项目不建议直接在src目录下新建类&#xff09;

坑爹系列1--Log

今天的Log信息有的能打有的不能打&#xff0c;甚是奇怪&#xff0c;高了半天明白了&#xff0c;常见的几个问题就不说了&#xff0c;说我这个奇怪的。看下面的内容&#xff0c;那个能打印呢&#xff1f; 1 2 3 4 5 Log.v("交易返回码:log", " "); Log.v(&q…

避免资源死锁:识别已打开的事务

死锁往往由于以下原因引起&#xff1a;1、程序错误&#xff0c;比如一个事务需要操作两个表&#xff0c;由于程序错误在有时是先操作a表后操作b表&#xff0c;有时是先操作b表后操作a表&#xff0c;就有机会互相等待而造成死锁。2、事务太大&#xff0c;大事务操作的表多&#…

【vivado】debug hub时钟不匹配

报错&#xff0c;没有debug core&#xff01; the clock connected to the debug hub (dbg_hub) core 根因是在调试中&#xff0c;这个debug hub没有工作。 下图两个ila_0&#xff0c;ila_1&#xff0c;分别对应两个时钟clk_out1, clk_out2&#xff0c;然后连到一个hub上。 默认…

IDEA IntelliJ 如何给web项目配置tomcat

step 1 step 2 step 3(重复step 1) step 4 step 5 step 6 结果

使用 spring boot 开发通用程序

2019独角兽企业重金招聘Python工程师标准>>> tag: spring 学习笔记date: 2018-03spring 是什么&#xff1f;spring 核心是应用组件容器&#xff0c;管理组件生命周期&#xff0c;依赖关系&#xff0c;并提倡面向接口编程实现模块间松耦合。 spring boot 是什么&…

java.utilDate和java.sql.Date

java.utilDate和java.sql.Date由广州疯狂软件教育java培训分享&#xff1a; java程序中的时间类型有java.util.Date和java.sql.Date两种。两者之间的关系和转化如下&#xff1a; java.sql.Date是java.util.Date的子类&#xff0c;所以可以直接将java.sql.Date类型的对象赋值给j…

Oracle 10G重建EM DB Control.

Oracle 10G R2重建EM DB Control.如果安装后没有修改过IP地址或机器名字,可以跳过下面1和2两步。1.drop configuration files and repository run :emca -deconfig dbcontrol db -repos drop 2. Logon SQLPLUS as user SYS or SYSTEM, and drop the sysman account and mangem…

IDEA IntelliJ 如何快速查看一个类里面包含哪些方法

主页面停留在那个类上 点击屏幕左侧的Structure

ACM 关于521

关于521 时间限制&#xff1a;1000 ms | 内存限制&#xff1a;65535 KB难度&#xff1a;2描述Acm队的流年对数学的研究不是很透彻&#xff0c;但是固执的他还是想一头扎进去。 浏览网页的流年忽然看到了网上有人用玫瑰花瓣拼成了521三个数字&#xff0c;顿时觉得好浪漫&#…

搭建本地https

生成证书 1. 使用openssl生成密钥privkey.pem&#xff1a; openssl genrsa -out privkey.pem 1024/2038 2. 使用密钥生成证书server.pem&#xff1a; openssl req -new -x509 -key privkey.pem -out server.pem -days 365 证书信息可以随便填或者留空&#xff0c;只有Common Na…

(转载)新年——顺民的牢骚

我是一个顺民&#xff0c;顺的不能再顺的民&#xff01;相信很多人和我一样&#xff0c;即使心中有很多的不满&#xff0c;也只是偶尔发发牢骚&#xff0c;而且&#xff0c;大多时&#xff0c;还不敢在人多的时候发&#xff01;即使在昏暗的灯光下的某个角落写写BLOG&#xff0…

IDEA IntelliJ 如何设置网站的欢迎页面

网站的目录结构如下 在web>WEB-INF>web.xml 文件中设置login.html为欢迎页面&#xff08;运行跳出的第一个页面&#xff09;

nyoj19 全排列

http://acm.nyist.net/JudgeOnline/status.php?pid19 1 #include<stdio.h>2 #include<stdlib.h>3 int n,a[10];4 bool vis[10];//标示数字是否被用过 5 void f(int k,int m)//k用来给a中第k个元素赋值&#xff0c;m表示还需要寻找的数字个数 6 {7 for(int i1;…

vue中动态样式不起作用? scoped了解一下

vue中style标签使用属性scoped的注意事项 style上添加属性scoped可以实现样式私有化&#xff0c;但是在使用动态样式时&#xff0c;样式会不起作用。可以先去掉scoped转载于:https://www.cnblogs.com/zuojiayi/p/9364347.html

有关cmd.Parameters.Clear()

// detach the SqlParameters from the command object, so they can be used again.cmd.Parameters.Clear(); 这句话在某些时候非常有用,比如说你在一个事务中调用了2个以上的存储过程,而恰巧这两个存储过程又有同样的参数,(例如 p_Name) 这时不加cmd.Parameters.Clear() 就会…

IDEA IntelliJ 如何设置web项目的热部署

这里的热部署指不需要重启服务器&#xff0c;刷新页面就可以反应页面&#xff08;仅限html和JSP&#xff09;的改动 step1 step2 效果 原来的html页面 在IntelliJ中进行修改 回到Chrome&#xff0c;点击 结果

SQL Server 2012 OFFSET/FETCH NEXT分页示例

原文&#xff1a;http://beyondrelational.com/modules/29/presentations/483/scripts/12983/sql-server-2012-server-side-paging-demo-using-offsetfetch-next.aspx?utm_sourcebrnewsletter&utm_mediumemail&utm_campaign2012Apr SQL Server 2005 引入了 ROW_NUMBER…

python数据库学习--Mysql

摘要&#xff1a; Python使用mysql需要安装驱动&#xff0c;有两种1&#xff09;mysqldb 2&#xff09;umysql &#xff0c;两者都是开源&#xff0c;具体区别不详&#xff0c;umysql没用过 一、mysqldb 安装MySQL驱动--http://www.codegood.com/archives/129 提供下载…

master page頁面如何用js來做輸入驗證

問&#xff1a;在使用了master page後&#xff0c;內容頁就沒有html標識了&#xff0c;那麼取得內容頁面控件的cilentID地方法也不一樣&#xff0c;我不知道用js怎麼取得這個cilentID,請各位大大幫忙告知如何寫這個js,並對其進行驗證.答&#xff1a;你可以先浏览一下页面&#…

scanf与空格

1.scanf的%c格式可以读入空格和换行 例&#xff1a; #include<cstdio> int main(){int a;char c,str[10];scanf("%d%c%s",&a,&c,str);printf("a%d,c%c,str%s",a,c,str);return 0;}2.字符数组使用%s读入的时候以空格跟换行为读入结束的标识 …

java 读取文件,内容方置Person 并写到另外地址

a.txt 文本内容如下&#xff1a; nameuserage34imageaa.PNGurlE:\\ package cn.com.test05;import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.io.OutputStream;class Person{String name;int…

从网页模版切图到网页生成全攻略(转)

鉴于很多朋友问到如何切图这个问题&#xff0c;又鉴于这个问题可大可小&#xff0c;一两句话是绝对讲不清楚的&#xff0c;所以今天有空闲在家里就举一个简单的例子来说明这个问题吧!OK&#xff0c;让我们开始&#xff1a; step1:在Photoshop中打开设计稿&#xff0c;如下图 选…

紫书 习题 10-17 UVa 11105 (筛法)

类似于素数筛的思想去做&#xff0c;不然暴力会超时而且还要判重 #include<cstdio> #include<cstring> #include<vector> #define REP(i, a, b) for(int i (a); i < (b); i) using namespace std;const int MAXN 1123456; int vis[MAXN]; vector<int…