我是这个月才开始接触.NET和数据库的,以前一直用的是C++  
所以眼界还比较狭窄,不知道这个类有没有硬伤  
比如在概念上就存在严重问题什么的。  
 
呵呵,请大家给点意见和评论,让我学点东西,谢谢。我会来结贴的。^_^  
 using System;
using System.Data;
using System.Data.OleDb;
using System.Data.SqlClient;namespace Liuzewei
{
    //
    // 类名:基于数据集的数据库操作类(通用于 Access、SQL 数据库)
    //
    // 作者:刘泽围 2007年4月14日
    //
    // 版权:在中国软件业不存在版权,可以随意使用 ^_^
    //
    // 说明:
    //
    //      本类将对源数据库的 查询、修改、删除、新增、更新与绑定 操作抽象为统一的对
    //      数据行引用的操作
    //
    //      而且本类是非静态的,所以使用时无须考虑多次不同数据库操作,彼此之间产生的影响
    //
    //      本类仅仅是对数据集类的一个简单包装,但鉴于以上两点,使用本类却可以大大减小
    //      项目期的复杂度
    //
    // 示例:
    //
    //      以Access数据库为例,如果同时要操作多个不同类型的数据库,只要对应实例化即可
    //
    //      1、实例化对象,必须有主键
    //         DataBase dataBase( "SELECT [ip], [date], [id] FROM [sitestat]", 
    //                            "C:\SiteStat.mdb", false );
    //
    //      2、查询数据行
    //         DataRow[] dataRows = dataBase.Select( "id > 10" );
    //
    //      3、显示数据行,dataRows来自于查询数据行时返回的引用
    //         for ( int i=0; i< dataRows.Length; i++ )
    //             Response.Write( dataRows[i]["ip"].ToString() );
    //
    //      4、修改数据行并更新到源数据库,dataRows来自于查询数据行时返回的引用
    //         dataRows[2]["ip"] = "127.0.0.1";
    //         dataBase.Update();
    //
    //      5、删除数据行并更新到源数据库,dataRows来自于查询数据行时返回的引用
    //         for ( int i=0; i< dataRows.Length; i++ )
    //             dataRows[i].Delete();
    //         dataBase.Update();
    //
    //      6、插入新数据行并更新到源数据库
    //         DataRow[] newDataRows = dataBase.NewDataRows( 2 );
    //         newDataRows[0]["ip"] = "127.0.0.2";
    //         newDataRows[1]["ip"] = "127.0.0.3";
    //         dataBase.Update();
    //
    //      7、绑定,这里是与分页数据源进行绑定
    //         PagedDataSource pagedDataSource = new PagedDataSource();
    //         pagedDataSource.DataSource = dataBase.DefaultView;
    //
    public class DataBase
    {
        // 本类实例映射自给定源数据库的公用数据集
        private DataSet dataSet;        // 源数据库与数据集之间的数据适配器
        private bool isSqlDataBase;
        private SqlDataAdapter sqlDataAdapter;
        private SqlCommandBuilder sqlCommandBuilder;
        private OleDbDataAdapter oleDbDataAdapter;
        private OleDbCommandBuilder oleDbCommandBuilder;        //
        // 在托管堆上分配内存实例化类本身以及 DataSet,DtaAdapter,CommandBuilder 对象 
        //
        public DataBase( string selectCommandText, string dataBasePath, bool isSqlDataBase )
        {
            dataSet = new DataSet();            if ( isSqlDataBase )
            {
                sqlDataAdapter = new SqlDataAdapter( selectCommandText, dataBasePath );                sqlCommandBuilder = new SqlCommandBuilder( sqlDataAdapter );
                sqlCommandBuilder.QuotePrefix = "[";
                sqlCommandBuilder.QuoteSuffix = "]";                sqlDataAdapter.Fill( dataSet );
            }
            else
            {
                oleDbDataAdapter = new OleDbDataAdapter( selectCommandText, 
                    "Provider=Microsoft.JET.OLEDB.4.0; Data Source = "+dataBasePath );                oleDbCommandBuilder = new OleDbCommandBuilder( oleDbDataAdapter );
                oleDbCommandBuilder.QuotePrefix = "[";
                oleDbCommandBuilder.QuoteSuffix = "]";                oleDbDataAdapter.Fill( dataSet );
            }            this.isSqlDataBase = isSqlDataBase;
        }
        
        //
        //  返回 DefaultView 用于调用者与本类实例公用数据集进行绑定
        //
        public DataView DefaultView
        {
            get { return dataSet.Tables[0].DefaultView; }
        }
        
        //
        //  将本类实例公用数据集中数据更新到源数据库中
        //
        public void Update()
        {
            if ( isSqlDataBase )
                sqlDataAdapter.Update( dataSet );
            else
                oleDbDataAdapter.Update( dataSet );            return;
        }
        
        //
        // 从本类实例公用数据集中查询现有数据行
        //
        // 调用者可以对返回数据行引用进行显示、修改和删除操作
        //
        // 操作完毕调用 Updata() 将操作更新到源数据库中
        //
        public DataRow[] Select( string expression )
        {
            DataRow[] dataRows;
            dataRows = dataSet.Tables[0].Select( expression );            return dataRows;
        }
        
        //
        // 从本类实例公用数据集中开辟新数据行
        //
        // 调用者可以对返回数据行引用进行填充、修改和删除操作
        //
        // 操作完毕调用 Updata() 将操作更新到源数据库中
        //
        public DataRow[] NewDataRows( int lenth )
        {
            DataRow[] dataRows = new DataRow[lenth];            for ( int i = 0; i < lenth; i++ )
            {
                dataRows[i] = dataSet.Tables[0].NewRow();
                dataSet.Tables[0].Rows.Add( dataRows[i] );
            }            return dataRows;
        }
    }
}

解决方案 »

  1.   

    一般不会直接操作dataset来进行数据的增删改,这种做法已经veryvery落伍了,一般是用三层架构的模式将数据取出存在dataset里,然后切断数据源从datatset里取出,在界面里进行体现,再直接把数据用传到逻辑层,再返回数据层。现在比较重视的主要在于SQL语句的优化,如果要通过编写方法达到减少劳动力,一般着重于界面层的数据导入和返回,呵呵,LZ的这个使用价值并不是很大。
      

  2.   

    可以参见我写的一个方法,直接利用一条sql语句或存储过程把一个数据集fill到datagridview里,并且可以在方法里直接绑定column的类型(combobox,datetimepicker,checkbox,image),另外我还写了三个配套的insert、update、execsql方法。http://blog.csdn.net/alldj/archive/2006/08/30/1145534.aspx
      

  3.   

    TO alldj(灵山妖姬)一般不会直接操作dataset来进行数据的增删改,这种做法已经veryvery落伍了,一般是用三层架构的模式将数据取出存在dataset里,然后切断数据源从datatset里取出,在界面里进行体现,再直接把数据用传到逻辑层,再返回数据层。现在比较重视的主要在于SQL语句的优化,如果要通过编写方法达到减少劳动力,一般着重于界面层的数据导入和返回,呵呵,LZ的这个使用价值并不是很大恩,谢谢你一针见血的指明这种方法已经非常落伍了。呵呵。另外,我也去了你的BLOG看了你的代码,可以看出来你的水平不错。虽然我看不懂:(当然拉,我也有个小小的疑问,你的代码是自说明(说明我菜看不懂你的代码)呢,还是注释不够详细呢。:)
    欢迎+期待各位继续回帖发表见解。谢谢
      

  4.   

    呵呵,这些代码是我以前写的,很仓促,没写什么注释,不好意思,以后有时间会补一下的。如果LZ要想学好c#,建议先从控件着手,绝大多数的控件和数据操作最好用代码来写,而不要使用界面赋值。毕竟winform最重视的就是界面编程这一块,还有smartclient和反射,多写多看多想,很快就能掌握的。
      

  5.   

    TO alldj(灵山妖姬)
    谢谢你的指点,我现在确实迷茫,看了本C#的书就开始乱搞ASP。NET,呵呵,这几天在论坛吹泡泡休息,过几天继续看书。
      

  6.   

    参考
    http://community.csdn.net/Expert/topic/5349/5349356.xml?temp=.7169001
    希望对你思想上转变有帮助.
      

  7.   

    我来说说几点吧,希望能给楼主一些 启发吧 第一点:数据库的连接地址问题
    DataBase dataBase( 一个sql语句,"C:\SiteStat.mdb", false );
    楼主把C:\SiteStat.mdb数据库地址传入不是一个好方法
    你可以在web.config里写上数据库连接地址 
    <appSettings>
    <add key="dataBasePath" value="C:\SiteStat.mdb"/>
    </appSettings>
    private string dataBasePath = 
    System.Configuration.ConfigurationSettings.AppSettings["dataBasePath"];
    就可以得到数据库的连接地址
      

  8.   

    第二点:static的用法,楼主学过c++应该知道了。
    既然写基类,这些操作不属于 某个具体的对象,就应该用static
    而不应该DataBase dataBase;来声明一个对象 再通过对象来调用就如
    class DataBase
    {
    public static void Update(string sql)
    {
    //通过传入sql语句,来执行更新的操作
    }
    }
    就可以直接 DataBase.Update(传入的sql语句)
    而不是先声明对象DataBase dataBase;dataBase.Update(传入的sql语句)
      

  9.   

    第二点:static的用法,楼主学过c++应该知道了。
    既然写基类,这些操作不属于 某个具体的对象,就应该用static
    而不应该DataBase dataBase;来声明一个对象 再通过对象来调用
    ---------------------------------------------
    如果是为了使用方便,大可以用工厂方法,而不是把功能类中所有方法写成静态方法。
    对于静态方法还要考虑到同步的问题,还要考虑并发时性能的问题。
    认真思考,多做实践。
      

  10.   

    C++转过来还需要点时间...UP
      

  11.   

    好东西
    自己也想写个来
    可苦于没抽象出来,放弃了
    upup
      

  12.   

    还可以抽象啊 直接用DBConnection,DBCommand,DBDataAdapter抽象类
    或者用接口IDBConnection,IDBCommand,IDBDataAdapter..........
      

  13.   

    mjpclab(有只大猫猫) 去看了你的网页,很不错哦~~
      

  14.   

    偶从不喜欢这么写。
    为什么要把Access和SqlServer写在一起呢?还有最好不要直接执行sql语句啦,建议都参数的形式来执行。
      

  15.   

    可以用XML注释/// <...>
    /// ******
    /// </...>
      

  16.   

    呵呵,学习一下。偶弄了 ASP.net近一年,最近才开始学这些数据与界面分离的东东....
      

  17.   

    大家好!本人现有两本新的<<计算机程序设计艺术>>第一卷,第三版.有意者与我联系.QQ:506990302  详情登陆http://auction1.taobao.com/auction/0/item_detail-0db2-6ca10a72e957e88fea2147780dbe0d1e.jhtml
      

  18.   

    那会用这种方式,一般都是用MVC设计模式的
      

  19.   

    好了,这个帖子要结贴了,谢谢所有回复过的朋友和给过点拨的朋友。通过朋友们的热心回复,我在原有基础上改进了这个类。请大家继续去支持。谢谢~:)链接:
    http://community.csdn.net/Expert/topic/5466/5466831.xml?temp=.6231348