您的位置:首页 > 数据库

向数据库写入500M的数据的方案

2006-03-22 23:54 211 查看
[align=center]向数据库写入500M的数据的方案[/align]
 
源代码下载地址:http://savefile.com/files/1941124
(注:本代码可以无偿使用,但希望您能发封邮件给我,至少让我知道你在使用它。另,对于程序中可能存在的BUG,我已经尽可能地减少,但我不对其造成的影响负责。如果您发现了BUG,请及时通知我,以便我改正它。)
 
有人说好象是不可能做到的,也是没有什么用处的。真的没有用么?那你当是解决一种变态的难题来看吧。我是用C#并基于MS SQL2000上开发,所以下面不比较其它数据库或平台上的解决办法。
一般而言,对于小的数据,比如图片,WORD文档,如果不是很大,比如说10M以内,我们都可以使用Microsoft Data Access Application Block for .NET(简称DAAB)这个由微软提供的程序块来简化我们的程序。事实上对于IMAGE/TEXT类型的字段,我们可以通过写参数变量来读写这个字段。比如下面的代码:
[align=left]string strSQL = " UPDATE DOC " +[/align]
[align=left]             " SET [IMAGE] = @PHOTO " +[/align]
[align=left]                " WHERE ID=1 ";[/align]
[align=left]byte[] PhotoByte;[/align]
[align=left] [/align]
[align=left]PhotoByte= SqlHelper.ImageToBytes(picBox.Image);[/align]
[align=left]SqlParameter p = new SqlParameter("@PHOTO",SqlDbType.Image,PhotoByte.Length);[/align]
[align=left]p.Value = PhotoByte;[/align]
[align=left]SqlHelper.ExecuteNonQuery(strConn,CommandType.Text,strSQL,p);[/align]
就是先将你的数据读入一个Byte型的数组,然后将其作为一个参数传给SQL语句或者是一个过程。为了简化使用,我对DAAB进行了修改,增加了五个公用函数
[align=left]public static byte[] ImageToBytes(System.Drawing.Image image);[/align]
[align=left]public static System.Drawing.Image BytesToImage(byte[] Bytes)[/align]
[align=left]public static byte[] StreamToBytes(System.IO.Stream stream)[/align]
[align=left]public static void BytesToStream(byte[] Bytes, System.IO.Stream stream)[/align]
[align=left]public static void DataReadToStream(SqlDataReader dataReader,System.IO.Stream stream)[/align]
[align=left] [/align]
它们的作用看名字就知道,用法也很简单,可以参考示例代码,不再一一阐述。使用它们你可以很方便地进行读写。接下来要说的是如何将超大型的数据写入数据库,当然你可以将数据分成很多小段,用上面的函数和SqlHelper固有的函数进行操作,虽然麻烦一点,但是是可以做到的。如果我想把它写到一个字段里,要如何做呢?你可以试试用上面的方法,一定会出现这样的问题,要么客户机的资源大大占用,要么数据库崩掉。而且在上传,下载期间什么都不能做
很显然,我们需要的是一个占用系统资源的方案。于是我想到了利用线程,并且分块进行读写。用事件来通知进行的情况。很快我写出了第一版,发现了一个问题,事件太占用时间了,因此我决定使用属性,主线程主动地读取该属性来了解情况,只保留了两个End事件。
在测试期间,发现上传500M的文件需要花费一定时间,因此又增加了一个中止线程的方法,如果你想放弃它可以用此方法。好了,费话少说,来看看这些东东
[align=left] [/align]
[align=left]namespace SmallStoneSoft.ExpertLib.Data[/align]
[align=left]{[/align]
[align=left]    public class SqlHelperBLOB[/align]
[align=left]{[/align]
[align=left]public void ExecuteReadBLOB(System.IO.Stream stream,[/align]
[align=left]string connectString,[/align]
[align=left]string TableName,[/align]
[align=left]string FieldName,[/align]
[align=left]string WhereSQL,[/align]
[align=left]params SqlParameter[] commandParams)[/align]
[align=left]public void ExecuteWriteBLOB(System.IO.Stream stream,[/align]
[align=left]string connectString,[/align]
[align=left]string TableName,[/align]
[align=left]string FieldName,[/align]
[align=left]string WhereSQL,[/align]
[align=left]params SqlParameter[] commandParams)[/align]
[align=left]public void ExitWorking()[/align]
[align=left]}[/align]
[align=left]}[/align]
它们的作用就和名字一样。需要说明的是WhereSQL这个参数,就是你的查询条件,比如  ID=@MYID
还用几个事件
[align=left]    public event System.EventHandler EndReadEvent;[/align]
[align=left]    public event System.EventHandler EndWriteEvent;[/align]
[align=left]    public event System.EventHandler ExitWorkingEvent;[/align]
它们是读写结束或者中断线程执行时发生。
我在我的机器上进行了测试,对一个564M的游戏安装包进行了读写,系统运行平稳,占用资源很少。
我的机器配置:
      CPU:C1.7
      内存:512M
  操作系统:Winxp
数据库:SQL 2000 个人版
对了,TestDB表的脚本是
[align=left]CREATE TABLE [dbo].[DOC] ([/align]
[align=left]    [ID] [int] IDENTITY (1, 1) NOT NULL ,[/align]
[align=left]    [IMAGE] [image] NULL ,[/align]
[align=left]    [DATA] [text] COLLATE Chinese_PRC_CI_AS NULL ,[/align]
[align=left]    [NDATA] [ntext] COLLATE Chinese_PRC_CI_AS NULL [/align]
[align=left]) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY][/align]
 
  经测试,不支持NTEXT格式的字段,只支持IMAGE及TEXT。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息