在数据库中存储 BLOB 数据的缺点
请认真考虑哪些资源存储在文件系统中可能比存储在数据库中更好。通常通过 HTTP HREF 引用的图像就是很好的例子。这是因为:
• |
从数据库中检索图像会导致比使用文件系统更大的开销。 |
• |
数据库 SAN 上的磁盘存储通常比 Web 服务器场中使用的磁盘上的存储更为昂贵。 注 通过精心设计元数据策略,可以消除在数据库中存储图像、电影甚至 Microsoft Office 文档之类资源的需要。元数据可以编入索引,并可以包含指向文件系统中存储的资源的指针。 |
将 BLOB 数据写入数据库
以下代码说明了如何使用 ADO.NET 将从文件中得到的二进制数据写入 SQL Server 中的 image 字段。
public void StorePicture( string filename ) { // Read the file into a byte array using(FileStream fs = new FileStream(filename, FileMode.Open, FileAccess.Read)) { byte[] imageData = new Byte[fs.Length]; fs.Read( imageData, 0, (int)fs.Length ); } using( SqlConnection conn = new SqlConnection(connectionString) ) { SqlCommand cmd = new SqlCommand("StorePicture", conn); cmd.CommandType = CommandType.StoredProcedure; cmd.Parameters.Add("@filename", filename ); cmd.Parameters["@filename"].Direction = ParameterDirection.Input; cmd.Parameters.Add("@blobdata", SqlDbType.Image); cmd.Parameters["@blobdata"].Direction = ParameterDirection.Input; // Store the byte array within the image field cmd.Parameters["@blobdata"].Value = imageData; conn.Open(); cmd.ExecuteNonQuery(); } }
从数据库中读取 BLOB 数据
在通过 ExecuteReader 方法创建 SqlDataReader 对象以读取包含 BLOB 数据的行时,请使用 CommandBehavior.SequentialAccess 枚举值。如果不使用该枚举值,读取器会每次一行地将数据从服务器提取到客户端。如果行中包含 BLOB 列,可能需要占用大量内存。通过使用枚举值,可以进行更精确的控制,因为仅在 BLOB 数据被引用(例如,通过 GetBytes 方法,该方法可用于控制所读取的字节数)时才会进行提取。以下代码片段对此进行了说明。
// Assume previously established command and connection // The command SELECTs the IMAGE column from the table conn.Open(); using(SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess)) { reader.Read(); // Get size of image dataa€“pass null as the byte array parameter long bytesize = reader.GetBytes(0, 0, null, 0, 0); // Allocate byte array to hold image data byte[] imageData = new byte[bytesize]; long bytesread = 0; int curpos = 0; while (bytesread < bytesize) { // chunkSize is an arbitrary application defined value bytesread += reader.GetBytes(0, curpos, imageData, curpos, chunkSize); curpos += chunkSize; } } // byte array 'imageData' now contains BLOB from database
注 使用 CommandBehavior.SequentialAccess 时,要求按照严格的顺序次序访问列数据。例如,如果 BLOB 数据位于第 3 列,并且您还需要第 1 列和第 2 列中的数据,则必须在读取第 3 列之前读取第 1 列和第 2 列。