Я нашел много информации о том, как выбрать большой двоичный объект в качестве потока с помощью CommandBehavior.SequentialAccess.
Я также хотел бы передать потоковый большой двоичный объект на вставку (чтобы избежать кэширования большого двоичного объекта какмассив байтов в памяти), и я не могу найти никаких примеров.Я нашел некоторую документацию, в которой упоминается синтаксис .WRITE (expression,@Offset, @Length)
в операторе UPDATE
T-SQL, который совместим с VARBINARY(MAX)
.Итак, я думаю о написании класса, который может взять Stream
и поместить его в базу данных, используя последовательные операторы UPDATE (.WRITE).Это правильный способ сделать это, или есть лучший способ?
Ссылки на UPDATE.WRITE:
http://msdn.microsoft.com/en-us/library/ms178158(SQL.100).aspx
http://msdn.microsoft.com/en-us/library/ms177523(v=SQL.100).aspx
Ссылки на выбор BLOB-объектов с помощью CommandBehavior.SequentialAccess:
http://msdn.microsoft.com/en-us/library/87z0hy49.aspx
Эффективный для памяти способ чтения BLOB-данных в C # / SQL 2005
Получение двоичных данных с использованием SqlDataReader
Как сделать потоки из больших двоичных объектов доступными в простых старых объектах C # при использовании SqlDataReader?
Потоковая передача VARBINARY данных из SQL Server в C #
ВотPOC с использованием синтаксиса .Write:
DDL:
create database BlobTest
go
use blobtest
go
create table Blob
(
Id bigint not null primary key identity(1,1),
Data varbinary(max) not null default(0x)
)
C #:
using System.Data;
using System.Data.SqlClient;
using System.IO;
using System.Linq;
namespace ConsoleApplication1
{
class Program
{
static void Main()
{
string pathToBigFile = "C:\\bigfile.big";
int optimumBufferSizeForSql = 8040; //See /5378615/kak-sozdat-stsenarii-insert-dlya-tablitsy-s-polem-varbinary-max
long newBlobId = InitialiseNewBlobInSqlServer();
using (Stream stream = new FileStream( pathToBigFile,
FileMode.Open,
FileAccess.Read,
FileShare.ReadWrite))
{
byte[] buffer = new byte[optimumBufferSizeForSql];
while(true)
{
int numberBytesRead = stream.Read(buffer, 0, optimumBufferSizeForSql);
if (numberBytesRead == 0)
{
//Done
break;
}
WriteBufferToSqlServer(
numberBytesRead == optimumBufferSizeForSql ? buffer : buffer.Take(numberBytesRead).ToArray(),
newBlobId);
}
}
}
static long InitialiseNewBlobInSqlServer()
{
using (SqlConnection conn = new SqlConnection("Data Source=localhost; Initial Catalog=BlobTest; Integrated Security=SSPI;"))
using (SqlCommand command = new SqlCommand())
{
command.Connection = conn;
command.CommandType = CommandType.Text;
command.CommandText = "Insert into blob (Data) values (0x); select convert(bigint,Scope_identity());";
conn.Open();
return (long) command.ExecuteScalar();
}
}
static void WriteBufferToSqlServer(byte[] data, long blobId)
{
using (SqlConnection conn = new SqlConnection("Data Source=localhost; Initial Catalog=BlobTest; Integrated Security=SSPI;"))
using (SqlCommand command = new SqlCommand())
{
command.Connection = conn;
command.CommandType = CommandType.Text;
command.Parameters.AddWithValue("@id", blobId);
command.Parameters.AddWithValue("@data", data);
command.CommandText = "Update Blob set Data.Write(@data, null, null) where Id = @id;";
conn.Open();
command.ExecuteNonQuery();
}
}
}
}