ADO.Net 缓冲 插入大型数据
| 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 缓冲 插入大型数据的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [完整代码]创建不受数据库限制的报表 V
- 下一篇: 智能客户端架构