写入:
这段摘至MSDN,一看就是翻译的,不是很通顺,但方法没有问题:)
将 BLOB 值写入 SQL Server 时节省资源
通过插入或更新带有字符串值或字节数组(取决于数据库中的字段类型)的字段,可以将二进制大对象 (BLOB) 写入数据库(请参见将 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 的输出参数)。
复制代码
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
请注意,在 Photo 字段中插入了初始值 0x0(空)。这确保可以检索到新插入记录的 Photo 字段的指针值。但是,空值不会影响追加的数据块。
在保留指向新插入记录中的 Photo 字段的指针后,示例可以接着使用 SQL Server 的 UPDATETEXT 函数向 BLOB 字段追加数据块。UPDATETEXT 函数接受以下对象作为输入:字段标识符 (Employees.Photo)、指向 BLOB 字段的指针、表示 BLOB 中写入当前块的位置的偏移量值,以及要追加的数据块。以下代码示例显示 UPDATETEXT 函数的语法(其中 @Pointer、@Offset, 和 @Bytes 被标识为 SqlCommand 的输入参数)。
复制代码
UPDATETEXT Employees.Photo @Pointer @Offset 0 @Bytes
偏移量值由内存缓冲区的大小确定,而该大小取决于应用程序的需要。大的缓冲区写入 BLOB 的速度较快,但会使用更多的系统内存。此示例使用的缓冲区相当小,只有 128 字节。为第一个数据块分配的偏移量值为 0,然后偏移量值对每个连续块按缓冲区大小递增。
该示例按块从提供的文件路径中检索员工照片。它根据指定的缓冲区大小,将每个块读入一个字节数组。然后,将字节数组设置为 SqlCommand 的 @Bytes 输入参数的值。更新 @Offset 参数值并执行 SqlCommand 后,当前的字节块追加到员工记录的 Photo 字段中。
usingSystem;
usingSystem.Data;
usingSystem.Data.SqlClient;
usingSystem.IO;
publicclassEmployeeData
...{
publicstaticvoidMain()
...{
DateTimehireDate=DateTime.Parse("4/27/98");
intnewID=AddEmployee("Smith","John","SalesRepresentative",hireDate,5,"smith.bmp");
Console.WriteLine("NewEmployeeadded.EmployeeID="+newID);
}
publicstaticintAddEmployee(stringlastName,stringfirstName,stringtitle,DateTimehireDate,intreportsTo,stringphotoFilePath)
...{
SqlConnectionconnection=newSqlConnection("DataSource=localhost;IntegratedSecurity=SSPI;InitialCatalog=Northwind;");
SqlCommandaddEmp=newSqlCommand("INSERTINTOEmployees(LastName,FirstName,Title,HireDate,ReportsTo,Photo)"+
"Values(@LastName,@FirstName,@Title,@HireDate,@ReportsTo,0x0);"+
"SELECT@Identity=SCOPE_IDENTITY();"+
"SELECT@Pointer=TEXTPTR(Photo)FROMEmployeesWHEREEmployeeID=@Identity",connection);
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;
SqlParameteridParm=addEmp.Parameters.Add("@Identity",SqlDbType.Int);
idParm.Direction=ParameterDirection.Output;
SqlParameterptrParm=addEmp.Parameters.Add("@Pointer",SqlDbType.Binary,16);
ptrParm.Direction=ParameterDirection.Output;
connection.Open();
addEmp.ExecuteNonQuery();
intnewEmpID=(int)idParm.Value;
StorePhoto(photoFilePath,(byte[])ptrParm.Value,connection);
connection.Close();
returnnewEmpID;
}
publicstaticvoidStorePhoto(stringfileName,byte[]pointer,SqlConnectionconnection)
...{
intbufferLen=128;//Thesizeofthe"chunks"oftheimage.
SqlCommandappendToPhoto=newSqlCommand("UPDATETEXTEmployees.Photo@Pointer@Offset0@Bytes",connection);
SqlParameterptrParm=appendToPhoto.Parameters.Add("@Pointer",SqlDbType.Binary,16);
ptrParm.Value=pointer;
SqlParameterphotoParm=appendToPhoto.Parameters.Add("@Bytes",SqlDbType.Image,bufferLen);
SqlParameteroffsetParm=appendToPhoto.Parameters.Add("@Offset",SqlDbType.Int);
offsetParm.Value=0;
//''''''''''''''''''''''''''''''''''
//Readtheimageinandwriteittothedatabase128(bufferLen)bytesatatime.
//TunebufferLenforbestperformance.Largervalueswritefaster,but
//usemoresystemresources.
FileStreamfs=newFileStream(fileName,FileMode.Open,FileAccess.Read);
BinaryReaderbr=newBinaryReader(fs);
byte[]buffer=br.ReadBytes(bufferLen);
intoffset_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();
}
}
读取:
这是我自己写的读取的例子:)
/**////<summary>
///根据图片的Id获取图片的内容
///</summary>
///<paramname="photoId"></param>
///<returns></returns>publicImageGetPhotoContentById(stringphotoId)
...{
SqlConnectionconn=null;
SqlCommandcomm=null;
SqlDataReaderreader=null;
Imageimage=null;
try
...{
conn=newSqlConnection(_connectionString);
conn.Open();
comm=conn.CreateCommand();
comm.CommandText=_selectPhotoSQL;
comm.Parameters.Add("@id",SqlDbType.Int,4).Value=photoId;
//reader=comm.ExecuteReader();
reader=comm.ExecuteReader(CommandBehavior.SequentialAccess);
//Streamstream=null;
MemoryStreamstream=newMemoryStream();
if(reader.Read())
...{
//直接行读取
//stream=reader.GetSqlBytes(reader.GetOrdinal("photocontent")).Stream;
//byte[]bytes=reader["photocontent"]asbyte[];
//stream=newMemoryStream(bytes);
//改为块儿读取,以节省内存资源
intiOrdinal=reader.GetOrdinal("photocontent");
longdataIndex=0;
intbufferSize=1024;
byte[]outBuffer=newbyte[bufferSize];
BinaryWriterwriter=newBinaryWriter(stream);
longretval=reader.GetBytes(iOrdinal,dataIndex,outBuffer,0,bufferSize);
while(retval==bufferSize)
...{
//stream.Write(outBuffer,0,bufferSize);
writer.Write(outBuffer);
writer.Flush();
dataIndex+=bufferSize;
retval=reader.GetBytes(iOrdinal,dataIndex,outBuffer,0,bufferSize);
}
writer.Write(outBuffer,0,bufferSize-1);
writer.Flush();
//writer.Close();
}
try
...{
if(stream!=null)
image=Image.FromStream(stream,true,true);
}
catch(ArgumentExceptione)
...{
thrownewException(e.Message);
}
returnimage;
}
catch(SqlExceptionex)
...{
thrownewException(ex.Message);
}
finally
...{
if(reader!=null)...{
reader.Close();
reader.Dispose();
}
if(comm!=null)...{
comm.Parameters.Clear();
comm.Dispose();
}
if(conn!=null)...{
conn.Close();
conn.Dispose();
}
}
}
分享到:
相关推荐
Access数据库里二进制数据读取,并显示为图片
将文件保存到数据库 从数据库读取文件 可以重命名
通过二进制数据流的方式,读写图片,把图片存入数据库,再从数据库读取出来显示
JAVA读写二进制文件
ADO实现大型二进制数据在数据库中的存取(论文)
main2.cpp 生成1个二进制文件。 main3.c 读取二进制文件。 用fgets可以读取指定长度的字符串。 可用于读取格式化固定位址的二进制结构数据。
ACCESS数据库备注及二进制字段内容的读写示例 用SQL方式对ACCESS数据库备注字段和二机制字段进行修改
winform中读写二进制图片
C++,java读写二进制文件方法介绍.pdf java从第九页开始
"C++,java读写二进制文件方法介绍" 以下是从给定的文件中生成的知识点: C++读写二进制文件 * 在C++中,读写二进制文件需要包含 `<fstream>` 头文件。 * 使用 `fstream` 类可以对文件进行读写操作。 * 打开文件有...
ADO读写二进制图片可以读写任一一种二进制方式
Kotlin二进制读写方法.Kotlin二进制读写方法.Kotlin二进制读写方法.Kotlin二进制读写方法.Kotlin二进制读写方法.
该CPP使用了三种方式对于不同需求的二进制流文件进行读写
让FORTRAN也能随机读写二进制文件任意字节数
C# 读写二进制文件的一个示例,演示如何以二进制方式写入文件,以二进制方式读出文件,下方框主要用来显示读取出来的二进制文件。C#新手朋友朋友们可拿去研究文件操作,应该有用哦。
c#读写二进制文件, // button1 // this.button1.Location = new System.Drawing.Point(301, 61); this.button1.Name = "button1"; this.button1.Size = new System.Drawing.Size(75, 23); this.button1....
一种C#读写二进制文件的通用方法-转 可学习学习,不错的解决方法。
数据用二进制方式保存无疑是能减小数据文件体积!此类就是鉴此思想编写 类包括数据写入 读写(文件头(结构体)部分 记录数据基本参数和文件的数据块数量 正文部分为存数据(结构体))高效实现块写 块读 !
C语言读写二进制文件的使用
二进制读写工具 可以读写二进制文件,查看编辑