C# SQL:按顺序执行更新。在VarBinary列上写入

C# SQL:按顺序执行更新。在VarBinary列上写入,c#,sql,sql-update,varbinary,C#,Sql,Sql Update,Varbinary,我正在尝试创建一个小测试应用程序,它读取文件流的块并将其附加到SQLServer2005Express上的VarBinary(max)列 每件事都能正常工作——专栏按预期的方式被填满,但我的机器似乎仍能将所有内容缓冲到内存中,我就是不明白为什么 我正在使用以下代码(C#): 有人能告诉我为什么它会将文件缓冲到内存中吗?我使用的byte[]缓冲区的大小几乎只有2MB 我可以为每个块创建一个新的缓冲区,但这似乎也是对CPU/内存的浪费…它会对其进行缓冲,因为当您将其保存到varbinary列时,它会

我正在尝试创建一个小测试应用程序,它读取文件流的块并将其附加到SQLServer2005Express上的VarBinary(max)列

每件事都能正常工作——专栏按预期的方式被填满,但我的机器似乎仍能将所有内容缓冲到内存中,我就是不明白为什么

我正在使用以下代码(C#):

有人能告诉我为什么它会将文件缓冲到内存中吗?我使用的
byte[]
缓冲区的大小几乎只有2MB


我可以为每个块创建一个新的缓冲区,但这似乎也是对CPU/内存的浪费…

它会对其进行缓冲,因为当您将其保存到varbinary列时,它会成为sql server中LOB数据缓存的一部分。这就是它的工作原理


还是说它在其他地方被缓冲?

FileStream类缓冲输入和输出。您可以在每次更新后调用Flush()方法来清除内部缓冲区

要明确的是,它将只缓冲到缓冲区大小(4KB)


在这种情况下,我认为你的罪魁祸首是SqlExpress。当我执行您的代码并写入SqlExpress的本地副本时,sqlsrvr进程的内存使用量增加了大约1GB。当我写入非本地数据库时,我的内存使用率保持不变。

我的意思是,它会将其缓冲到我的机器内存中。如果我试图将一个1GB的文件保存到列中,它最终将使用1GB的物理内存。由于SQL server并没有将其所有内容保存在RAM中,我猜我的代码一定出了问题……SQL server在RAM中保存了尽可能多的数据。因此,如果可以,它将在内存中保留1Gb Lob。要测试这一点,只需重新启动sql server服务,检查mem,重新读取varbinary列,然后再次检查mem。在我的端没有缓冲,但有时在服务器上有一点缓冲。谢谢你的帮助!这似乎有点帮助。然而,看起来它仍然将50%到80%的文件大小添加到内存中…:(此处相同,当使用非本地SQL server时。谢谢。请尝试GC.Collect(),它们可能是等待收集的依赖项。
using (IDbConnection connection = new SqlConnection(ConfigurationManager.ConnectionStrings[1].ConnectionString))
{
    connection.Open();

    string id = Guid.NewGuid().ToString();

    using (IDbCommand command = connection.CreateCommand())
    {
        command.CommandText = "INSERT INTO [BLOB] ([Id],[Data]) VALUES (@p1,0x0)";

        SqlParameter param = new SqlParameter("@p1", SqlDbType.VarChar);
        param.Value = id;
        command.Parameters.Add(param);

        command.ExecuteNonQuery();
    }

    if (File.Exists(textBox1.Text))
    {
        using (IDbCommand command = connection.CreateCommand())
        {
            command.CommandText = "UPDATE [BLOB] SET [Data].WRITE(@data, @offset, @len) WHERE [Id]=@id";

            SqlParameter dataParam = new SqlParameter("@data", SqlDbType.VarBinary);
            command.Parameters.Add(dataParam);

            SqlParameter offsetParam = new SqlParameter("@offset", SqlDbType.BigInt);
            command.Parameters.Add(offsetParam);

            SqlParameter lengthParam = new SqlParameter("@len", SqlDbType.BigInt);
            command.Parameters.Add(lengthParam);

            SqlParameter idParam = new SqlParameter("@id", SqlDbType.VarChar);
            command.Parameters.Add(idParam);
            idParam.Value = id;

            using (FileStream fs = new FileStream(textBox1.Text, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                byte[] buffer = new byte[2090400]; //chunk sizes that are multiples of 8040 bytes.
                int read = 0;
                int offset = 0;

                while ((read = fs.Read(buffer, 0, buffer.Length)) > 0)
                {
                    dataParam.Value = buffer;
                    offsetParam.Value = offset;
                    lengthParam.Value = read;

                    command.ExecuteNonQuery();

                    offset += read;
                }
            }
        }
    }
}