C# 如何在插入时将BLOB流式传输到VARBINARY(MAX)

C# 如何在插入时将BLOB流式传输到VARBINARY(MAX),c#,sql-server-2008,C#,Sql Server 2008,我发现了很多关于如何使用CommandBehavior.SequentialAccess选择BLOB作为流的信息 我也希望在insert上对BLOB进行流式处理(以避免将BLOB缓存为内存中的字节数组),但我找不到任何示例。我发现一些文档提到了与VARBINARY(MAX)兼容的UPDATET-SQL语句中的.WRITE(expression,@Offset,@Length)语法。因此,我正在考虑编写一个类,它可以接受流,并使用连续的UPDATE(.WRITE)语句将其分块到数据库中。这是正确的

我发现了很多关于如何使用CommandBehavior.SequentialAccess选择BLOB作为流的信息

我也希望在insert上对BLOB进行流式处理(以避免将BLOB缓存为内存中的字节数组),但我找不到任何示例。我发现一些文档提到了与
VARBINARY(MAX)
兼容的
UPDATE
T-SQL语句中的
.WRITE(expression,@Offset,@Length)
语法。因此,我正在考虑编写一个类,它可以接受
,并使用连续的UPDATE(.WRITE)语句将其分块到数据库中。这是正确的方法,还是有更好的方法

UPDATE.WRITE的链接:

指向使用CommandBehavior.SequentialAccess选择Blob的链接:

下面是一个使用.Write语法的POC:

DDL:

C#:


您应该使用SQL Server的界面来处理blob。

谢谢@Hasan。这很有趣,但不能直接帮助我;为了满足我的需求,我希望将BLOB保存在数据库中。RBS团队博客确实提到,除了示例FileStoreLibrary BlobStore之外,他们还编写了一个FILESTREAM支持的BlobStore。我正在下载加载项和示例代码,以便检查它们是否流到文件流(我对此表示怀疑,因为我希望它们使用Win32直接访问文件流)。因此,我已经查看了用于文件流BlobStore的RBS代码和SQL,并且有一个选项可以内联存储数据(即以VARBINARY(MAX)而不是文件流)但是当设置为store_inline=true时,RBS不会将数据流化(这是我想要的)。奇怪的是,它们将BLOB分解为最多25个块,作为存储过程的单独参数,然后将存储过程中的数据(RBS_fs_sp_store_BLOB_参数)一起写入varbinary(max)并一次性插入。您希望将数据以行形式存储并流式传输。这两个要求并不协调。特别是在插入的情况下。为什么“特别是在插入的情况下”,即插入和选择之间的根本区别是什么?@DanielJamesBryars根本区别在于插入时,您在db中创建一行,而在读取时,该行已经存在。你可以用一年的时间按照你的意愿把它表达出来;这不会给数据库带来太多麻烦,但插入数据库时必须尽可能快。SqlFileStream具有更好的性能,SQL数据库上的负载更少,但需要SQL2008或更高版本。谢谢@Bengie,这很好,但我需要将数据内联存储在数据库中,而不是文件流中。
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)
)
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 https://stackoverflow.com/questions/5629991/how-can-i-generate-an-insert-script-for-a-table-with-a-varbinarymax-field

            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();
            }
        }
    }
}