I have table like this:
CREATE TABLE [dbo].[BigFiles](
[ID] [uniqueidentifier] NOT NULL,
[Name] [nvarchar](255) NOT NULL,
[Size] [bigint] NOT NULL,
[Data] [image] NULL,
CONSTRAINT [PK_File] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
and I inserted some file approx big 700mb:
INSERT INTO [BigFiles] (ID, Name, Size, Data)
SELECT
NEWID(),
'bigFile.zip',
DATALENGTH(BulkColumn),
BulkColumn
FROM OPENROWSET(BULK N'bigFile.zip', SINGLE_BLOB) AS FileData;
Then I have created 32bit project in Visual Studio, where my csproj looks like this:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<PlatformTarget>x86</PlatformTarget>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Data.SqlClient" Version="6.0.2" />
</ItemGroup>
</Project>
Notice:
<PlatformTarget>x86</PlatformTarget>
<Prefer32Bit>true</Prefer32Bit>
Standard way with Ado.Net will not work:
using Microsoft.Data.SqlClient;
string connectionString = "Server=localhost;Database=saveBigData;User Id=myUserId;Password=myPass;TrustServerCertificate=True;Encrypt=False;";
using SqlConnection sqlConnection = new SqlConnection();
using SqlCommand sqlCommand = new SqlCommand();
sqlConnection.ConnectionString = connectionString;
sqlConnection.Open();
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandText = "SELECT * FROM [dbo].[BigFiles]";
sqlCommand.CommandTimeout = 0;
using SqlDataReader sqlDataReader = sqlCommand.ExecuteReader();
while (sqlDataReader.Read())
{
object[] values = new object[4];
sqlDataReader.GetValues(values);
}
In the line:
sqlDataReader.GetValues(values);
will be System.OutOfMemoryException raised. Instead the one should use SequentialAccess:
string fileName = Path.Combine(AppContext.BaseDirectory, $"{Guid.NewGuid()}.bin");
using SqlConnection sqlConnection = new SqlConnection();
using SqlCommand sqlCommand = new SqlCommand();
sqlConnection.ConnectionString = connectionString;
sqlConnection.Open();
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandText = "SELECT * FROM [dbo].[BigFiles]";
sqlCommand.CommandTimeout = 0;
using SqlDataReader reader = sqlCommand.ExecuteReader(CommandBehavior.SequentialAccess);
while (reader.Read())
{
using Stream sqlStream = reader.GetStream(3);
using FileStream fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write);
byte[] buffer = new byte[81920];
int bytesRead;
while ((bytesRead = sqlStream.Read(buffer, 0, buffer.Length)) > 0)
{
fileStream.Write(buffer, 0, bytesRead);
}
}
Example download from
here.