Первоначально я разместил этот вопрос:
how-can-i-create-a-tar-file-in-memory-from-several-varbinarymax-колонны, что было полезным. Но я понял, что нам может потребоваться создать большие файлы .tar, с файлами около 2 ГБ, которые могут привести к ~ 20 ГБ .tar файлы. И использование MemoryStream не сработает, и я не могу выделить эту мюшную память на сервере. -a-tar, где ответ подразумевает, что метод не будет использовать много памяти, и этот подход записывается в файл смолы на диске. Столбцы с SQL Server и создайте временный файл на диске, который я затем передаю обратно в Calling Client. < /p>
Мой текущий код: < /p>
var tempFileName = Path.GetTempFileName();
await using var tarFileStream = File.Create(tempFileName);
await using (var tarWriter = new TarWriter(tarFileStream, leaveOpen: true))
{
await using var connection = new SqlConnection("YourConnectionString");
const string query = @"
SELECT
FileName,
FileData
FROM FilesTable;
";
await using var command = new SqlCommand(query, connection);
await connection.OpenAsync();
await using var reader = command.ExecuteReaderAsync(CommandBehavior.SequentialAccess);
while (await reader.ReadAsync())
{
var fileName = reader.GetString(0);
await using var fileDataStream = reader.GetStream(1);
var entry = new PaxTarEntry(TarEntryType.RegularFile, fileName)
{
DataStream = fileDataStream,
};
await tarWriter.WriteEntryAsync(entry);
}
}
tarFileStream.Position = 0;
// Stream tarFileStream to response body..
< /code>
Когда я пробую этот подход, и во время петли я получаю где-то около 8 ГБ, выделенных в LOH для пары 1,7 ГБ файлов, хранящихся в SQL Server (FileSttream). Я могу осмотреть использование памяти в Jetbrains Dotmemory, и память выделяется в базовой памяти Tarwriter, если я не ошибаюсь. ? По словам ответа Джона Скитса, я должен быть в состоянии не потреблять столько памяти? ): < /p>
await using var tempFileStream = File.Create(Path.GetTempFileName());
await using (var tarWriter = new TarWriter(tempFileStream, leaveOpen: true))
{
await using var file = File.Open("C:\\Users\\xyz\\Desktop\\BigFile.txt", FileMode.Open);
await tarWriter.WriteEntryAsync(new PaxTarEntry(TarEntryType.RegularFile, Guid.NewGuid().ToString())
{
DataStream = file
});
}
< /code>
Таким образом, это должна быть некоторая проблема, когда я устанавливаю свойство DataStream, когда поток поступает из SQLClient. < /p>
dotmemory:
< /p>
Изменить 2: воспроизводимый пример, чтение и вставка большого текстового файла 836 МБ в базу данных (без FileStream). Прочитайте его из базы данных с GetStream и напишите поток Tarwriter. < /P>
using System.Data;
using System.Formats.Tar;
using Microsoft.Data.SqlClient;
const string connectionString = "Integrated Security=true;Data Source=localhost;Initial Catalog=MyTestDatabase;" +
"User Id=username;Password=xy;Max pool size=200;Min pool size=10;Connection Timeout=30;" +
"Encrypt=false";
await using var connection = new SqlConnection(connectionString);
await using var largeFile = File.Open(@"C:\Users\xyz\Desktop\BigFile.txt", FileMode.Open);
await using var createAndInsertCommand = new SqlCommand(
"""
CREATE TABLE [dbo].[Temp] ([Id] INT NOT NULL, [Data] VARBINARY (MAX) NOT NULL);
INSERT INTO dbo.Temp VALUES (@Id, @Data);
""",
connection);
createAndInsertCommand.Parameters.Add("@Id", SqlDbType.Int).Value = 1;
createAndInsertCommand.Parameters.Add("@Data", SqlDbType.VarBinary, size: -1).Value = largeFile;
await createAndInsertCommand.Connection.OpenAsync();
await createAndInsertCommand.ExecuteNonQueryAsync();
// Read from database
await using var command = new SqlCommand("SELECT TOP 1 Data FROM dbo.Temp", connection);
await using var reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess);
if (await reader.ReadAsync())
{
await using var fileData = reader.GetStream(0);
await using var tempFileStream = File.Create(Path.GetTempFileName());
await using var tarWriter = new TarWriter(tempFileStream, leaveOpen: true, format: TarEntryFormat.Pax);
tarWriter.WriteEntry(new PaxTarEntry(TarEntryType.RegularFile, Guid.NewGuid().ToString())
{
DataStream = fileData
});
}
Первоначально я разместил этот вопрос: how-can-i-create-a-tar-file-in-memory-from-several-varbinarymax-колонны, что было полезным. Но я понял, что нам может потребоваться создать большие файлы .tar, с файлами около 2 ГБ, которые могут привести к ~ 20 ГБ .tar файлы. И использование MemoryStream не сработает, и я не могу выделить эту мюшную память на сервере. -a-tar, где ответ подразумевает, что метод не будет использовать много памяти, и этот подход записывается в файл смолы на диске. Столбцы с SQL Server и создайте временный файл на диске, который я затем передаю обратно в Calling Client. < /p> Мой текущий код: < /p> [code]var tempFileName = Path.GetTempFileName(); await using var tarFileStream = File.Create(tempFileName);
await using (var tarWriter = new TarWriter(tarFileStream, leaveOpen: true)) { await using var connection = new SqlConnection("YourConnectionString"); const string query = @" SELECT FileName, FileData FROM FilesTable; "; await using var command = new SqlCommand(query, connection); await connection.OpenAsync(); await using var reader = command.ExecuteReaderAsync(CommandBehavior.SequentialAccess);
while (await reader.ReadAsync()) { var fileName = reader.GetString(0); await using var fileDataStream = reader.GetStream(1);
var entry = new PaxTarEntry(TarEntryType.RegularFile, fileName) { DataStream = fileDataStream, }; await tarWriter.WriteEntryAsync(entry); } }
tarFileStream.Position = 0;
// Stream tarFileStream to response body.. < /code> Когда я пробую этот подход, и во время петли я получаю где-то около 8 ГБ, выделенных в LOH для пары 1,7 ГБ файлов, хранящихся в SQL Server (FileSttream). Я могу осмотреть использование памяти в Jetbrains Dotmemory, и память выделяется в базовой памяти Tarwriter, если я не ошибаюсь. ? По словам ответа Джона Скитса, я должен быть в состоянии не потреблять столько памяти? ): < /p> await using var tempFileStream = File.Create(Path.GetTempFileName()); await using (var tarWriter = new TarWriter(tempFileStream, leaveOpen: true)) { await using var file = File.Open("C:\\Users\\xyz\\Desktop\\BigFile.txt", FileMode.Open); await tarWriter.WriteEntryAsync(new PaxTarEntry(TarEntryType.RegularFile, Guid.NewGuid().ToString()) { DataStream = file }); } < /code> Таким образом, это должна быть некоторая проблема, когда я устанавливаю свойство DataStream, когда поток поступает из SQLClient. < /p> dotmemory:
< /p> Изменить 2: воспроизводимый пример, чтение и вставка большого текстового файла 836 МБ в базу данных (без FileStream). Прочитайте его из базы данных с GetStream и напишите поток Tarwriter. < /P> using System.Data; using System.Formats.Tar; using Microsoft.Data.SqlClient;
const string connectionString = "Integrated Security=true;Data Source=localhost;Initial Catalog=MyTestDatabase;" + "User Id=username;Password=xy;Max pool size=200;Min pool size=10;Connection Timeout=30;" + "Encrypt=false";
await using var connection = new SqlConnection(connectionString); await using var largeFile = File.Open(@"C:\Users\xyz\Desktop\BigFile.txt", FileMode.Open);
await using var createAndInsertCommand = new SqlCommand( """ CREATE TABLE [dbo].[Temp] ([Id] INT NOT NULL, [Data] VARBINARY (MAX) NOT NULL); INSERT INTO dbo.Temp VALUES (@Id, @Data); """, connection); createAndInsertCommand.Parameters.Add("@Id", SqlDbType.Int).Value = 1; createAndInsertCommand.Parameters.Add("@Data", SqlDbType.VarBinary, size: -1).Value = largeFile; await createAndInsertCommand.Connection.OpenAsync(); await createAndInsertCommand.ExecuteNonQueryAsync();
// Read from database await using var command = new SqlCommand("SELECT TOP 1 Data FROM dbo.Temp", connection); await using var reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess);
if (await reader.ReadAsync()) { await using var fileData = reader.GetStream(0);
await using var tempFileStream = File.Create(Path.GetTempFileName()); await using var tarWriter = new TarWriter(tempFileStream, leaveOpen: true, format: TarEntryFormat.Pax);