ADO.Net 缓冲 插入大型数据
| ADO.Net 緩沖 插入大型數(shù)據(jù) |
| Database, C#, ASP.NET |
2004-8-9 | 16:58
通過插入或更新帶有字符串值或字節(jié)數(shù)組(取決于數(shù)據(jù)庫中的字段類型)的字段,可以將二進(jìn)制大對象 (BLOB) 寫入數(shù)據(jù)庫。但是,BLOB 可能相當(dāng)大,因此在作為單個值寫入時可能要使用大量的系統(tǒng)內(nèi)存,從而降低應(yīng)用程序的性能。
為減少寫入 BLOB 值時使用的內(nèi)存量,通常是將 BLOB 以“塊區(qū)”的形式寫入數(shù)據(jù)庫。以此方法將 BLOB 寫入數(shù)據(jù)庫的過程依賴于數(shù)據(jù)庫的功能。
以下示例演示如何將 BLOB 以塊區(qū)形式寫入 SQL Server。該示例向 Northwind 數(shù)據(jù)庫的 Employees 表添加了一個包含員工圖像的新記錄,該圖像就是一個 BLOB。該示例使用 SQL Server 的 UPDATETEXT 函數(shù)將新添加的員工的圖像以指定大小的塊區(qū)寫入 Photo 字段。
UPDATETEXT 函數(shù)要求一個指向所更新的 BLOB 字段的指針。在此示例中,在添加新員工的記錄后,將調(diào)用 SQL Server TEXTPTR 函數(shù)以返回一個指向新記錄的 Photo 字段的指針。返回的指針值將作為輸出參數(shù)傳遞回去。示例中的代碼保留此指針,并在追加數(shù)據(jù)塊區(qū)時將其傳遞到 UPDATETEXT。
用于插入新員工記錄和保留指向 Photo 字段的指針的 Transact-SQL 將在下例中顯示(其中 @Identity 和 @Pointer 被標(biāo)識為 SqlCommand 的輸出參數(shù))。
請注意,在 Photo 字段中插入了初始值 0x0(空)。這確保可以檢索到新插入記錄的 Photo 字段的指針值。但是,空值不會影響追加的數(shù)據(jù)塊區(qū)。
在保留指向新插入記錄中的 Photo 字段的指針后,示例可以接著使用 SQL Server 的 UPDATETEXT 函數(shù)向 BLOB 字段追加數(shù)據(jù)塊區(qū)。UPDATETEXT 函數(shù)接受以下對象作為輸入:字段標(biāo)識符 (Employees.Photo)、指向 BLOB 字段的指針、表示 BLOB 中寫入當(dāng)前塊區(qū)的位置的偏移量值,以及要追加的數(shù)據(jù)塊區(qū)。以下代碼示例顯示 UPDATETEXT 函數(shù)的語法(其中 @Pointer、@Offset 和 @Bytes 被標(biāo)識為 SqlCommand 的輸入?yún)?shù))。
偏移量值由內(nèi)存緩沖區(qū)的大小確定,而該大小取決于應(yīng)用程序的需要。大的緩沖區(qū)寫入 BLOB 的速度較快,但會使用更多的系統(tǒng)內(nèi)存。此示例使用的緩沖區(qū)相當(dāng)小,只有 128 字節(jié)。為第一個數(shù)據(jù)塊區(qū)分配的偏移量值為 0,然后偏移量值按每個連續(xù)塊區(qū)的緩沖區(qū)大小遞增。
該示例按塊區(qū)從提供的文件路徑中檢索員工相片。它根據(jù)指定的緩沖區(qū)大小,將每個塊區(qū)讀入一個字節(jié)數(shù)組。然后,將字節(jié)數(shù)組設(shè)置為 SqlCommand 的 @Bytes 輸入?yún)?shù)的值。更新 @Offset 參數(shù)值并執(zhí)行 SqlCommand 后,當(dāng)前的字節(jié)塊區(qū)追加到員工記錄的 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();
? }
}
轉(zhuǎn)載于:https://www.cnblogs.com/stone/archive/2005/03/14/118145.html
總結(jié)
以上是生活随笔為你收集整理的ADO.Net 缓冲 插入大型数据的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [完整代码]创建不受数据库限制的报表 V
- 下一篇: asp.net ajax控件工具集 Au