ADO.Net 缓冲 插入大型数据
Database, C#, ASP.NET

2004-8-9 | 16:58

通过插入或更新带有字符串值或字节数组(取决于数据库中的字段类型)的字段,可以将二进制大对象 (BLOB) 写入数据库。但是,BLOB 可能相当大,因此在作为单个值写入时可能要使用大量的系统内存,从而降低应用程序的性能。

为减少写入 BLOB 值时使用的内存量,通常是将 BLOB 以“块区”的形式写入数据库。以此方法将 BLOB 写入数据库的过程依赖于数据库的功能。

以下示例演示如何将 BLOB 以块区形式写入 SQL Server。该示例向 Northwind 数据库的 Employees 表添加了一个包含员工图像的新记录,该图像就是一个 BLOB。该示例使用 SQL Server 的 UPDATETEXT 函数将新添加的员工的图像以指定大小的块区写入 Photo 字段。

UPDATETEXT 函数要求一个指向所更新的 BLOB 字段的指针。在此示例中,在添加新员工的记录后,将调用 SQL Server TEXTPTR 函数以返回一个指向新记录的 Photo 字段的指针。返回的指针值将作为输出参数传递回去。示例中的代码保留此指针,并在追加数据块区时将其传递到 UPDATETEXT。

用于插入新员工记录和保留指向 Photo 字段的指针的 Transact-SQL 将在下例中显示(其中 @Identity@Pointer 被标识为 SqlCommand 的输出参数)。

请注意,在 Photo 字段中插入了初始值 0x0(空)。这确保可以检索到新插入记录的 Photo 字段的指针值。但是,空值不会影响追加的数据块区。

在保留指向新插入记录中的 Photo 字段的指针后,示例可以接着使用 SQL Server 的 UPDATETEXT 函数向 BLOB 字段追加数据块区。UPDATETEXT 函数接受以下对象作为输入:字段标识符 (Employees.Photo)、指向 BLOB 字段的指针、表示 BLOB 中写入当前块区的位置的偏移量值,以及要追加的数据块区。以下代码示例显示 UPDATETEXT 函数的语法(其中 @Pointer@Offset@Bytes 被标识为 SqlCommand 的输入参数)。

偏移量值由内存缓冲区的大小确定,而该大小取决于应用程序的需要。大的缓冲区写入 BLOB 的速度较快,但会使用更多的系统内存。此示例使用的缓冲区相当小,只有 128 字节。为第一个数据块区分配的偏移量值为 0,然后偏移量值按每个连续块区的缓冲区大小递增。

该示例按块区从提供的文件路径中检索员工相片。它根据指定的缓冲区大小,将每个块区读入一个字节数组。然后,将字节数组设置为 SqlCommand@Bytes 输入参数的值。更新 @Offset 参数值并执行 SqlCommand 后,当前的字节块区追加到员工记录的 Photo 字段中。

[C#]
using System;
using System.Data;
using System.Data.SqlClient;
using System.IO;

public class EmployeeData
{
  public static void Main()
  {
    DateTime hireDate = DateTime.Parse("4/27/98");
    int newID  = AddEmployee("Smith", "John", "Sales Representative", hireDate, 5, "smith.bmp");
    Console.WriteLine("New Employee added. EmployeeID = " + newID);
  }

public static int AddEmployee(string lastName, string firstName, string title, DateTime hireDate , int reportsTo, string photoFilePath)
  {
    SqlConnection nwindConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=Northwind;");

SqlCommand addEmp  = new SqlCommand("INSERT INTO Employees (LastName, FirstName, Title, HireDate, ReportsTo, Photo) " +
      "Values(@LastName, @FirstName, @Title, @HireDate, @ReportsTo, 0x0);" +
      "SELECT @Identity = SCOPE_IDENTITY();" +
      "SELECT @Pointer = TEXTPTR(Photo) FROM Employees WHERE EmployeeID = @Identity", nwindConn);

addEmp.Parameters.Add("@LastName",  SqlDbType.NVarChar, 20).Value = lastName;
    addEmp.Parameters.Add("@FirstName", SqlDbType.NVarChar, 10).Value = firstName;
    addEmp.Parameters.Add("@Title",     SqlDbType.NVarChar, 30).Value = title;
    addEmp.Parameters.Add("@HireDate",  SqlDbType.DateTime).Value     = hireDate;
    addEmp.Parameters.Add("@ReportsTo", SqlDbType.Int).Value          = reportsTo;

SqlParameter idParm = addEmp.Parameters.Add("@Identity", SqlDbType.Int);
    idParm.Direction = ParameterDirection.Output;
    SqlParameter ptrParm = addEmp.Parameters.Add("@Pointer", SqlDbType.Binary, 16);
    ptrParm.Direction = ParameterDirection.Output;

nwindConn.Open();

addEmp.ExecuteNonQuery();

int newEmpID = (int)idParm.Value;

StorePhoto(photoFilePath, (byte[])ptrParm.Value, nwindConn);

nwindConn.Close();

return newEmpID;
  }

public static void StorePhoto(string fileName, byte[] pointer,  SqlConnection nwindConn)
  {
    int bufferLen = 128;  // The size of the "chunks" of the image.

SqlCommand appendToPhoto = new SqlCommand("UPDATETEXT Employees.Photo @Pointer @Offset 0 @Bytes", nwindConn);

SqlParameter ptrParm  = appendToPhoto.Parameters.Add("@Pointer", SqlDbType.Binary, 16);
    ptrParm.Value = pointer;
    SqlParameter photoParm = appendToPhoto.Parameters.Add("@Bytes", SqlDbType.Image, bufferLen);
    SqlParameter offsetParm = appendToPhoto.Parameters.Add("@Offset", SqlDbType.Int);
    offsetParm.Value = 0;

//''''''''''''''''''''''''''''''''''
    // Read the image in and write it to the database 128 (bufferLen) bytes at a time.
    // Tune bufferLen for best performance. Larger values write faster, but
    // use more system resources.

FileStream fs = new FileStream(fileName, FileMode.Open, FileAccess.Read);
    BinaryReader br = new BinaryReader(fs);

byte[] buffer = br.ReadBytes(bufferLen);
    int offset_ctr = 0;

while (buffer.Length > 0)
    {
      photoParm.Value = buffer;
      appendToPhoto.ExecuteNonQuery();
      offset_ctr += bufferLen;
      offsetParm.Value = offset_ctr;
      buffer = br.ReadBytes(bufferLen);
    }

br.Close();
    fs.Close();
  }
}

转载于:https://www.cnblogs.com/stone/archive/2005/03/14/118145.html

ADO.Net 缓冲 插入大型数据相关推荐

  1. idea中连接mysql插入成功数据 在navicat中刷新表格没有数据_第九篇 数据分析的进阶学习-SQL入门...

    1.SQL的学习阶段 1.1 背景 随着互联网的不断发展,数据的不断累积,现在单单使用Excel已经不能满足数据分析的需求了,因此作为一个数据分析工作者,掌握Excel是基础,而SQL作为主流数据库查 ...

  2. oracle+循环插入sql,SQL server,Oracle循环插入百万数据

    SQL server,Oracle循环插入百万数据 SQL server,Oracle循环插入百万数据 压测时常需要往数据库插入大量数据,下面是我往两个数据库插入数据时用的脚本 declare @ma ...

  3. 浅析能耗监测系统在大型数据中心的应用

    摘要:本文根据大型数据中心能耗监测的具体需求,设计了一个大型数据中心能耗监测系统,实现了资产管理.环境监测.设备控制.能耗分析以及数据统计等功能,可以为节能减排提供重要依据,在大型数据中心能耗管理方面 ...

  4. 技术图文:如何利用 C# 向 Access 数据库插入大量数据?

    背景 通常我们在做数据分析与处理之前,需要把从网站爬取的数据或者从 甲方 系统中导出的数据存入到自己的数据库中.如果数据量小,直接利用 SQL的 Insert 语句逐条插入就好.可是数据量上万条之后, ...

  5. sqlserver 自增ID插入指定数据

    set identity_insert 表名 ON --允许对自增列Id插入指定数据 insert into table_name(Id,Name) values(1,'test') set iden ...

  6. oracle 数据有引号,oracle插入字符串数据时字符串中有'单引号问题

    使用insert into(field1,field2...) values('val1','val2'...)时,若值中有单引号时会报错. 处理方法:判断一下val1,val2中是否含有单引号,若含 ...

  7. 在SQL 2005中用T-SQL插入中文数据时出现的问号或乱码的解决方案[转]

    在SQL 2005中用T-SQL插入中文数据时出现的问号或乱码的解决方案 病症表现为:主要表现为用T-sql语句插入中文数据时数据库显示全是问号"???"  解决办法: 第一种办法 ...

  8. 验证ArrayList插入同样数据使用指定容量和默认容量的效率

    2019独角兽企业重金招聘Python工程师标准>>> 验证ArrayList插入同样数据使用指定容量和默认容量的效率 之前在研究ArrayList源码的时候看到过一篇文章Java ...

  9. php 插入 mysql_php插入mysql数据返回id的方法

    如下所示: $dbh = mysql_connect('localhost','root','root'); mysql_select_db('pkbk'); $query = "inser ...

最新文章

  1. classlist使用方法_如何通过使用HTML5的classList API在没有jQuery的情况下操作类
  2. Spring + Mybatis 集成原理分析
  3. SUSE11sp3 perf工具安装过程
  4. 国外计算机科学英语演讲,2014年暨大英语演讲大赛圆满落幕
  5. Spring5参考指南:组件扫描
  6. Qt工作笔记-undefined reference to `vtable for MyObject'及对moc文件的进一步理解
  7. 看完《复联4》想剧透怎么办?网店开始卖《复联4》讨论群了...
  8. 智慧城市助力城市管理 推动新兴产业升级
  9. Access在Win10连接失败的问题
  10. java+mysql中文乱码解决
  11. @Transactional注解的几个参数--事务传播控制--事务隔离级别--异常与回滚
  12. 回顾 | Apache Flink x TiDB Meetup · 北京站(附 PPT 下载)
  13. 基于JavaWeb的12306网络购票系统设计与实现 文档+项目源码+脚本文件
  14. win10 家庭版 升级专业版
  15. 嵌入式开发入门基础篇
  16. 玩转JS|解放双手,快手一键取消多个关注教程
  17. 论文笔记2:Combining Lexical, Syntactic, and Semantic Features with Maximum Entropy Models for Extracting
  18. 日升日落,总有黎明——暖色系原木风装修
  19. 利用snowfall.jquery.js实现爱心满屏飞或点点满屏飞
  20. 2022危险化学品生产单位主要负责人考试题库及模拟考试

热门文章

  1. javase_03作业
  2. 牛客假日团队赛2 A.买一送一
  3. 2006世界杯赛程表,不能错过:)
  4. Python工作记录
  5. 实现手电筒Flash Light 关键代码
  6. Elasticsearch2.x Breaking changes
  7. NSLog (Log信息的输出)
  8. 7. SQL -- 创建数据库(表,字段)
  9. Struts2中的ActionContext
  10. 參加microsoft主管信息論壇