数据库中存放十进制数的方案。(在某些情况下,完全可以取代关系表)

发表于:2007-05-25来源:作者:点击数: 标签:
相信你一定有过这样类似的案例(这里我将举一个软件上传的例子)。 下面我先说一下我们一般 开发 这样的项目的时候所采取的方案。 一、MRS: 1、上传软件的程序开发,首先要给软件分类,如:多媒体软件、系统软件、 网络 软件等; 2、这些分类一定会持续一段

相信你一定有过这样类似的案例(这里我将举一个软件上传的例子)。
下面我先说一下我们一般开发这样的项目的时候所采取的方案。
一、MRS:
    1、上传软件的程序开发,首先要给软件分类,如:多媒体软件、系统软件、网络软件等;
    2、这些分类一定会持续一段时间,或者说近期内不会有变动(这里的变动指去除软件的某一类别)。
二、PES:
    1、设计项目流程,制定开发时间;
    2、设计页面,最终完成效果。
三、PIS:
    1、数据库设计(一般我们首先会想到关联表来解决这样的问题)
        表1:Driver表 (驱动信息表)
            DriverID        INT            4    
            DriverName    NVarChar        100
            DriverDate    DateTime        8
        表2:DriverType表 (驱动类型信息表)
            DriverTypeID        INT            4
            DriverTypeName    NVarChar        100
            DriverTypeDate    DateTime        8
        表3:DriverAndDriverType (驱动和驱动类型的关系表)这个表显然是一个多对多的关系表
            DriverID            INT        4
            DriverTypeID        INT        4
    2、存储过程(略)
    3、主要类结构(略)
    4、文件结构(略)
    
    通过上面的设计,我们在提交一个驱动程序之后,便记录了该驱动的驱动类型,显然,实现这一功能需要一个
额外数据表的支持,即完成这项任务的工作全部交给了数据库。

    今天我要介绍的这种方法将是没有额外表支持的。即仅仅在上面的一个表中增添了一个INT类型的字段。我们来看看:
一、MRS:
    同上。这里注意:这些分类一定会持续一段时间,或者说近期内不会有变动(这里的变动指去除软件的某一类别)。
二、PES:
    同上。
三、1、数据库设计
        表1:Driver表 (驱动信息表)
            DriverID        INT            4    
            DriverName    NVarChar        100
            DriverDate    DateTime        8
            DriverType    INT            4        (这个就是新增加的字段)
        表2:DriverType表 (驱动类型信息表)
            DriverTypeID        INT            4
            DriverTypeName    NVarChar        100
            DriverTypeDate    DateTime        8
    2、存储过程(略)这里所有逻辑均在程序里实现
    3、主要类结构
        使用这种方法,代码是关键,因为它涉及到很多进制转换的问题,主要是二进制与十进制之间的转换。下面我将按照
    页面的流程作以说明。
        上传软件,给软件选择类型,一般软件可以属于两种或两种以上类型,则可以多选,这里,你可以用ListBox或CheckBoxList
    给用户提供选择,如:
        软件名称:[ IE6.0 ]
        软件类型:1、系统软件    2、网络软件    3、多媒体软件    (CheckBoxList形式)
        提交        取消
        这时假设用户选择1和2,则程序里可以这样处理:
        double k = 0;
        for (int i = 0; i < DriverType.Items.Count; i ++)
        {
            k += DriverType.Items[i].Selected ? Math.Pow(2,Convert.ToDouble(i)) : 0;
        }
        看懂了吧,我将选项看作一个反转的二进制数,选择第一个,就加2的0次方,选择第三个,就加2的2次方,最后存放到一个变量里。
    而这个变量,恰恰就是你要存放到数据库中Driver表的DriverType字段的值,怎么样,满容易吧!
        这里讲的是提交数据时如何获取十进制数,后面我将讲一下如何将取出的十进制数还原成一个反转的二进制数,并且根据0和1初始化
    CheckBoxList。同时还将讲道最复杂的地方:列表显示数据,如何根据一个十进制数反映出该驱动都属于哪些类型。
 下面我们继续说说如何将读取的十进制数付给CheckBoxList(初始化)。这里主要的就是一个小算法,我的这样:
        private string MakeBanaryNum2(string mynum)
        {
              string k = "";
              int num = Convert.ToInt16(mynum);
              while (num / 2 != 0)
               {
                  k += Convert.ToString(num % 2);
                  num = num / 2;
                }
               return k + "1";
        }
    之后将这个string类型的变量通过0和1判断初始化CheckBoxList:
        string driverNum = MakeBanaryNum2(dataFromDataBase);    //这里的入参就是数据库中存放的十进制数
        for (int i = 0; i<driverNum.Length;i++)
            {
                if (driverNum[i] == '1')
                    chklst_DriverType.Items[i].Selected = true;
            }
    这个也相对容易。
    最后我们来看看如何处理列表中的显示。在处理列表显示的问题时,因为你要将这个十进制数显转换成翻转二进制,之后还要根据0和1
以及他们的位置和书序对应DriverType表中的数据,转化成DriverName的内容。所以,最好是先将DriverType表中的数据取出,注意顺序
不能有变动(和插入的顺序相同),存放在一个集合里面。这里我恰好需要用到查询的DropDownList,里面恰好已经存放了所有的DriverTypeName,
所以,就直接利用了~~~不多说了,主要思想还是逐项比较,首先,将十进制数转换成反转二进制,之后,将这个反转二进制数与DropDownList
中的Value值求与,为真,则显示DropDownList中对应的Text值,否则不显示,这里我用到了DataGrid的Item_Bound方法。具体实现如下:
            string dir = e.Item.Cells[3].Text;    //获得显示该字段的单元格内容
            string banaryNum2 = test.MakeBanaryNum2(dir,20);        //将这个十进制数转换成翻转二进制
            
            banaryNum2 = "0" + banaryNum2;        
            dir = "";
            for (int i=0; i<drp_DriverType.Items.Count; i++)
            {
                if (banaryNum2[i] == '1')
                    dir += drp_DriverType.Items[i].Text + "/";
            }
            if (dir.Length != 0)
                dir = dir.Substring(0,dir.LastIndexOf("/"));
            e.Item.Cells[3].Text = dir;            //重新给该单元格负值
    现在,我们要做的工作就全部完成了,怎么样,有些收获吗??或许你很早就知道这种方法,或许你并不认为它是什么好的方案,我在这里只是
想和大家分享一下开发过程中的经验与收获,希望对你有些帮助,呵呵~~
    花絮:开发过程中曾遇到很多问题,因为首次尝试。如:C#中,对Int16进行与操作,可以返回正确结果,但是对于Int32或者Int64就不是求
与了,呵呵,为什么?看看帮助吧~~
    切记,使用该方法,一定不要删除任何的某一个类型(除了最后的没有用到的)!
    FAQ:
    1、为什么要用反转的二进制数?
    答:因为方便填充控件。DataBind()就好。

 

原文转自:http://www.ltesting.net