二十四画生的Blog


        ——开始学习MVC框架
posts - 90, comments - 1221, trackbacks - 46, articles - 8
  博客园 :: 首页 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理

为数据访问层编写一个基类

Posted on 2005-04-12 08:20 二十四画生 阅读(7015) 评论(28)  编辑 收藏 网摘 所属分类: .NET文章
  编写数据访问层代码时,总要一边又一边的重复编写:读数据库连接字符串,建立数据库连接对象,打开连接,创建Command对象,创建数据适配器,创建数据集,填充数据集,关闭连接。这种重复的代码写一两次到还行,写多了就免不了有一些烦了。
  在总结以前的的代码以后,决定重构数据方法层的代码。数据访问层无非进行两种操作:查询返回DataTable,进行插入、更新、删除等无返回值的操作。只要增加一个数据访问层基类包含这些繁琐的代码,其余的数据访问层代码继承数据访问层基类,在调用基类函数时给出存储过程名称和存储过程参数即可。

数据访问层基类代码:
using System;
using System.Data;
using System.Collections; 
using System.Data.SqlClient;

namespace DAL
{
    
/// <summary>
    
/// DALBase 的摘要说明。
    
/// 数据层访问基类,定义数据层访问公共的变量,方法
    
/// </summary>

    public class DALBase
    
{
        
//定义该类共用变量
        private SqlConnection conn;        //
        private SqlCommand mycm;        //
        private DataSet myds;            //
        private SqlDataAdapter myda;    //
        
        
/// <summary>
        
/// 从web.config中读取数据库连接字符串
        
/// </summary>

        private string CONNSTR = System.Configuration.ConfigurationSettings.AppSettings["ConnectionString"];

        
public DALBase()
        
{
            
//构造函数,创建对象实例
            conn = new SqlConnection(CONNSTR);
            mycm 
= conn.CreateCommand();
            myds 
= new DataSet();
            myda 
= new SqlDataAdapter();
        }


        
/// <summary>
        
/// 通过存储过程返回查询表的信息
        
/// </summary>
        
/// <param name="sprocName">存储过程名称</param>
        
/// <returns>DataTable</returns>

        protected DataTable GetTable(string sprocName)
        
{
            conn.Open();
            
try
            
{
                mycm.CommandText 
= sprocName;
                mycm.CommandType 
= CommandType.StoredProcedure;
                myda.SelectCommand 
= mycm;
                myda.Fill(myds);
            }

            
finally
            
{
                
//无论语句执行正确与否,都关闭连接释放资源
                conn.Close();
            }

            
return myds.Tables[0];
        }


        
/// <summary>
        
/// 通过存储过程和参数返回查询表的信息
        
/// </summary>
        
/// <param name="sprocName"></param>
        
/// <param name="parameters"></param>
        
/// <returns></returns>

        protected DataTable GetTable(string sprocName, SqlParameter[] parameters)
        
{
            conn.Open();
            
try
            
{
                mycm.CommandText 
= sprocName;
                mycm.CommandType 
= CommandType.StoredProcedure;
                SqlParameterCollection sqlParams 
= mycm.Parameters;
                
//先清空原有的参数
                mycm.Parameters.Clear();
                
//给Command添加参数
                foreach ( SqlParameter parameter in parameters )
                
{
                    mycm.Parameters.Add( parameter );
                }

                myda.SelectCommand 
= mycm;
                myda.Fill(myds);
            }

            
finally
            
{
                
//无论语句执行正确与否,都关闭连接释放资源
                conn.Close();
            }

            
return myds.Tables[0];
        }



        
/// <summary>
        
/// 通过存储过程及存储过程参数执行对数据库无返回值的操作(如:新增,更新,删除等)
        
/// </summary>
        
/// <param name="sprocName">存储过程名称</param>
        
/// <param name="parameters">存储过程参数</param>

        protected void SaveTale(string sprocName, SqlParameter[] parameters)
        
{
            mycm.CommandText 
= sprocName; 
            mycm.CommandType 
= CommandType.StoredProcedure; 
            SqlParameterCollection sqlParams 
= mycm.Parameters;
            
//先清空原有的参数
            mycm.Parameters.Clear();
            
//给Command添加参数
            foreach ( SqlParameter parameter in parameters )
            
{
                mycm.Parameters.Add( parameter );
            }

            
//打开连接
            conn.Open();
            
try
            
{
                
//执行
                mycm.ExecuteNonQuery(); 
            }

            
finally
            
{
                
//关闭连接
                conn.Close();
            }

        }

    }

}



数据访问层代码:
using System;
using System.Data;
using System.Collections; 
using System.Data.SqlClient;

namespace DAL
{
    
public class Test : DALBase
    
{
        
public Test()
        
{
        }


        
public DataTable GetTestTable()
        
{
          
return base.GetTable("存储过程名称");
        }


        
public DataTable GetTestTableByXName(string XName)
        
{
            SqlParameter[] parameters 
= new SqlParameter( "@XName",SqlDbType.NVarChar,10 ) };     
            
return base.GetTable("存储过程名称",parameters);
        }



        
public void AddTestTable(string XName, string Description)
        
{
            SqlParameter[] parameters 
= 
            
{
                
new SqlParameter( "@XName",SqlDbType.NVarChar,10 ),
                
new SqlParameter( "@Description",SqlDbType.NVarChar,100)
            }
;
    
            
//设置参数值
            parameters[0].Value = XName;
            parameters[
1].Value = Description;
            
base.SaveTale("存储过程名称",parameters);
        }

    }

}


  大家有兴趣还可以帮忙扩充一下这个基类,比如增加通过SQL语句返回DataTable,返回单值结果(如:查询合计)……
  注:使用该方法的一个坏处就是用久了以后就会忘记如何进行数据访问的具体方法只会调用基类方法,如果面试问起访问数据库的代码就……^-^。

Feedback

#1楼   回复  引用    

2005-04-12 08:51 by exhjw
 注:使用该方法的一个坏处就是用久了以后就会忘记如何进行数据访问的具体方法只会调用基类方法,如果面试问起访问数据库的代码就……^-^。

这句话说得对,我现在真的有点忘记了,呵呵..

#2楼   回复  引用    

2005-04-12 08:56 by hbifts
为什么不试试M$出的Data Access Block呢?

#3楼   回复  引用  查看    

2005-04-12 09:02 by AlleNny      
如果我要改为其他数据库访问呢?只有一个类是不够的,需要把操作抽象出来。

#4楼[楼主]   回复  引用  查看    

2005-04-12 09:08 by 二十四画生      
@hbifts
我编的算是他的一个简化版吧。他需要传入connectionString,这在多数据库连接时可能有用,单一的数据连接就用不上了。而且我觉得从基类继承的方式要好一些。

#5楼[楼主]   回复  引用  查看    

2005-04-12 09:12 by 二十四画生      
@AlleNny

Good idea!

#6楼   回复  引用  查看    

2005-04-12 09:25 by 强把忧郁再掩盖      
我的基类是直接采用DAAB的方法来完成自己的数据库访问方式
就可以既使用现有的成熟的数据访问代码,又可以符合自己的特殊需要
比如,都是单一数据库,那么给自己的基类指定一个ConnectionString,
所有数据库访问方法都采用这个string传递给DAAB.

这样是否好点啊

#7楼   回复  引用  查看    

2005-04-12 11:07 by 木野狐      
protected DataTable GetTable(string sprocName, SqlParameter[] parameters)

可以先设定参数再调用

protected DataTable GetTable(string sprocName)

嘛. 这样代码不是减少重复了吗.

#8楼   回复  引用  查看    

2005-04-12 11:09 by 木野狐      
还有一个就是你的 try 后面没有 catch. 发生了异常外面根本不知道到底发生了什么事情.

#9楼[楼主]   回复  引用  查看    

2005-04-12 11:12 by 二十四画生      
@木野狐

我的错误捕捉是在业务逻辑成完成的。这样可以简化数据访问层代码。在业务逻辑层可更灵活的处理错误。

#10楼   回复  引用    

2005-04-12 11:14 by 。。。
无语。。。 大概才开始学编程吧。

#11楼   回复  引用    

2005-04-12 11:31 by fadingflower
没必要非要自己这样做吧,自己做个proxy,Inject一个ConnectionProvide接口,然后在Proxy里调用Microsoft Data Access Application Block不就好了?

#12楼[楼主]   回复  引用  查看    

2005-04-12 11:35 by 二十四画生      
@fadingflower

这样也可以,反正方法很多。自己用着习惯就好。

#13楼   回复  引用  查看    

2005-04-12 11:59 by 常建昭      
还是觉的MS的DA Block更好点,更全面,安全性也高。。如果有朋友一定要建这一个类,建议用现成的好,因为你写的话也可以,不过要考虑方方面面,重用,安全性,对不同数据库的支持,不同数据类型的支持等等。。。如果是学习,自己写最好,否则。。。嘿嘿。。

#14楼   回复  引用  查看    

2005-04-12 11:59 by 常建昭      
还是觉的MS的DA Block更好点,更全面,安全性也高。。如果有朋友一定要建这一个类,建议用现成的好,因为你写的话也可以,不过要考虑方方面面,重用,安全性,对不同数据库的支持,不同数据类型的支持等等。。。如果是学习,自己写最好,否则。。。嘿嘿。。

#15楼   回复  引用  查看    

2005-04-12 12:55 by 木野狐      
"我的错误捕捉是在业务逻辑成完成的。这样可以简化数据访问层代码。在业务逻辑层可更灵活的处理错误。"

你是在这里完成异常的日志工作吗? 这样说来应该也一样, 呵呵.

#16楼   回复  引用    

2005-04-18 00:58 by upzone
数据访问层的Exception 可以直接throw到业务逻辑,由业务逻辑捕捉Exception,在业务逻辑层可更灵活的处理错误.或者有专门的Exception Manager

#17楼   回复  引用  查看    

2005-05-08 20:38 by 江(大|中|小)鱼      
MS的 Data Access Application Block 已经做得很好了,可以直接用。

#18楼   回复  引用    

2005-09-26 11:36 by je[未注册用户]
如果是对不同数据库访问呢?

#19楼[楼主]   回复  引用  查看    

2005-09-26 11:47 by 二十四画生      
@je
你可以看看我写的另外一篇文章:《利用反射工厂实现多数据库访问》http://www.cnblogs.com/esshs/archive/2005/09/01/227899.html">http://www.cnblogs.com/esshs/archive/2005/09/01/227899.html

#20楼   回复  引用    

2005-11-28 19:03 by Martin[未注册用户]
各位大侠,我是新手,看了楼主的文章有点问题不明白,我目前使用的方式是写一个类,这个类里面公开了几个静态方法,可以在需要的地方调用.并返回DATATABLE或者是DATAREADER或者是执行SQL代码,这种方式与基类继承的方法有什么不一样呢,请指教谢谢,下面贴上部分代码.

Imports System.Data.SqlClient
Public Class oclass
Public Shared conn As SqlConnection
Public Shared connStr As String = System.Configuration.ConfigurationSettings.AppSettings("connStr")

Public Shared Function ExeCuteSQL(ByVal sql As String) As String
conn = New SqlConnection(connStr)
Dim cmd As SqlCommand = New SqlCommand(sql, conn)
conn.Open()
cmd.ExecuteNonQuery()
conn.Close()
End Function
Public Shared Function ExeCuteDt(ByVal sql As String, ByRef dt As DataTable) As DataTable
conn = New SqlConnection(connStr)
Dim da As SqlDataAdapter = New SqlDataAdapter(sql, conn)
conn.Open()
da.Fill(dt)
conn.Close()
Return dt
End Function
End Class

#21楼[楼主]   回复  引用  查看    

2005-11-28 19:45 by 二十四画生      
@Martin
你的说列举的代码没什么不好,我以上的代码也不见得怎么好。我现在已经不用上面的代码了,直接用MS的Data Access Application Block了。的确是一个不错的东西,现在我已经基本忘记了DataAdapter 这个东西了。Data Access Application Block就是利用的静态方法。

#22楼   回复  引用    

2005-11-30 16:13 by Martin[未注册用户]
感谢楼主回复,MS Data Access Application Block 目前好象是不提供下载了,原因是发现了一些BUG,并建议用户去打补丁~~~~;(

#23楼[楼主]   回复  引用  查看    

2005-11-30 21:11 by 二十四画生      
@Martin
居然有Bug,不过我一直用的挺好。是什么样的Bug呢?
微软好像有个企业库,好像包括这个东西。不知道企业库中是否是最新的DAAB。

#24楼   回复  引用    

2007-01-18 11:09 by test[未注册用户]
好,我也这样写,但要加强.

#25楼   回复  引用    

2007-05-31 20:27 by kj;lk[未注册用户]
wedding8精致喜蛋是一家专注于精致、创意喜蛋生产和销售的企业。公司秉承喜蛋礼品化和喜蛋个性化的经营理念,致力于为客户提供引领时尚的精致、个性喜蛋。

选择wedding8精致喜蛋,

选择wedding8精致喜蛋,收获亲友的甜蜜惊喜,收藏你们的幸福回忆!

============================================================
官方网站:http://www.wedding8.net

#26楼   回复  引用    

2007-06-18 10:18 by pwhello[未注册用户]
FrameCountry是采用.Net的开发平台,专注于数据库访问层功能的架构系统,为用户提供便捷、规范、强大的功能,提升开发效率。

FrameCountry特点
◆便捷开发:封装、整合数据库操作方式,让开发人员摆脱数据库的约束;
◆规范开发:依据多层设计原理,明晰人员分工,提高程序可读性;
◆记录运行情况:开发人员依据记录了解系统详情,方便调试排错;
◆多样数据库连接:实现多种数据库连接方式,对开发人员透明化数据库连接,使其只关注上层程序,同时降低数据库转换、升级工作量,目前实现Access2000、SQLServer2000两种数据库,日后逐步增加关系型数据库连接配置;
◆整合有效函数:对开发中其它的有用的、常用的函数进行整理,简单调用实现;

访问http://blog.csdn.net/lizheng82

#27楼   回复  引用    

2007-11-30 20:00 by 寂寞的刺猬[未注册用户]
这是最原始的一种方式,请问您还在采用这种方式开发项目?

#28楼   回复  引用    

2008-01-01 19:36 by 敢死队[未注册用户]
路过!学习!



发表评论

昵称: [登录] [注册]

主页:

邮箱:(仅博主可见)

评论内容:

  登录  注册

[使用Ctrl+Enter键快速提交评论]

0 135883




相关文章:

相关链接: