gpt4 book ai didi

c# - 上传流到数据库

转载 作者:行者123 更新时间:2023-12-03 22:43:48 26 4
gpt4 key购买 nike

我有一个 FileForUploading应该上传到数据库的类。

public class FileForUploading
{
public FileForUploading(string filename, Stream stream)
{
this.Filename = filename;
this.Stream = stream;
}

public string Filename { get; private set; }

public Stream Stream { get; private set; }
}

我正在使用 Entity Framework 将其转换为 FileForUploadingEntity这是一个非常简单的类,但只包含 Filename属性(property)。我不想存储 Stream在内存中,而是直接将其上传到数据库。

“流式传输” Stream 的最佳方式是什么?直接到数据库?

到目前为止,我想出了这个
private void UploadStream(string name, Stream stream)
{
var sqlQuery = @"UPDATE dbo.FilesForUpload SET Content =@content WHERE Name=@name;";

var nameParameter = new SqlParameter()
{
ParameterName = "@name",
Value = name
};

var contentParameter = new SqlParameter()
{
ParameterName = "@content",
Value = ConvertStream(stream),
SqlDbType = SqlDbType.Binary
};

// the database context used throughout the application.
this.context.Database.ExecuteSqlCommand(sqlQuery, contentParameter, nameParameter);
}

这是我的 ConvertStream转换 Streambyte[] . (它在数据库中存储为 varbinary(MAX)
private static byte[] ConvertStream(Stream stream)
{
using (var memoryStream = new MemoryStream())
{
stream.CopyTo(memoryStream);
return memoryStream.ToArray();
}
}

上述解决方案是否足够好?如果 Stream,它会表现得好吗?大吗?

最佳答案

I don't want to store the Stream in memory but rather upload it directly to the database.



使用您提出的上述解决方案,您的应用程序中的内存中仍然有流的内容,您最初提到这是您试图避免的。

最好的办法是绕过 EF 并使用 async 函数上传流。以下示例取自 MSDN article SqlClient Streaming Support .
// Application transferring a large BLOB to SQL Server in .Net 4.5
private static async Task StreamBLOBToServer() {

using (SqlConnection conn = new SqlConnection(connectionString)) {
await conn.OpenAsync();
using (SqlCommand cmd = new SqlCommand("INSERT INTO [BinaryStreams] (bindata) VALUES (@bindata)", conn)) {
using (FileStream file = File.Open("binarydata.bin", FileMode.Open)) {

// Add a parameter which uses the FileStream we just opened
// Size is set to -1 to indicate "MAX"
cmd.Parameters.Add("@bindata", SqlDbType.Binary, -1).Value = file;

// Send the data to the server asynchronously
await cmd.ExecuteNonQueryAsync();
}
}
}
}

您可以将此示例转换为以下内容以使其适合您。请注意,您应该更改方法上的签名以使其异步,这样您就可以利用在长期数据库更新期间不会阻塞线程的优势。
// change your signature to async so the thread can be released during the database update/insert act
private async Task UploadStreamAsync(string name, Stream stream) {

var conn = this.context.Database.Connection; // SqlConnection from your DbContext
if(conn.State != ConnectionState.Open)
await conn.OpenAsync();
using (SqlCommand cmd = new SqlCommand("UPDATE dbo.FilesForUpload SET Content =@content WHERE Name=@name;", conn)) {
cmd.Parameters.Add(new SqlParameter(){ParameterName = "@name",Value = name});
// Size is set to -1 to indicate "MAX"
cmd.Parameters.Add("@content", SqlDbType.Binary, -1).Value = stream;
// Send the data to the server asynchronously
await cmd.ExecuteNonQueryAsync();
}
}

再一记。如果您想保存大型非结构化数据集(即您上传的流),那么最好不要将它们保存在数据库中。有很多原因,但最重要的是,关系数据库的设计并没有真正考虑到这一点,处理数据很麻烦,而且它们可以真正快速地消耗数据库空间,使其他操作(即备份、恢复等)变得更加困难)。

有一种替代方法仍然允许您在 native 中将指针保存在记录中,但将实际的非结构化数据驻留在磁盘上。您可以使用 Sql Server FileStream 执行此操作.在 ADO.NET 中,您将使用 SqlFileStream .这是关于如何配置 Sql Server 和数据库以允许 Sql File Streams 的一个很好的演练。它还有一些关于如何使用 SqlFileStream 的 Vb.net 示例。类(class)。

An Introduction to SQL Server FileStream

我确实假设您使用 Microsoft Sql Server 作为您的数据存储库。如果此假设不正确,请更新您的问题,并为您正在连接的正确数据库服务添加标签。

关于c# - 上传流到数据库,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37837484/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com