假设我有一个VarBinary [MAX]列,我可以使用从System.IO.Stream派生的类型插入或更新到该列吗?怎么样?
我认为我可以使用SqlDataReader
从这样的列中获取只读流,在阅读器上调用GetSqlBytes(),获取SqlBytes实例,然后引用Stream属性。
我想要的是反过来 - 我想要一个流更新或插入。
可能? (来自c#...没有编写T-SQL?)
修改
我见过这样的代码:
System.Data.SqlClient.SqlCommand _SqlCommand
= new System.Data.SqlClient.SqlCommand(_SQL, _SqlConnection);
// Convert image to memory stream
System.IO.MemoryStream _MemoryStream = new System.IO.MemoryStream();
_Image.Save(_MemoryStream, _ImageFormat);
// Add image as SQL parameter
System.Data.SqlClient.SqlParameter _SqlParameter
= new System.Data.SqlClient.SqlParameter("@" + _ImageFieldName, SqlDbType.Image);
_SqlParameter.Value = _MemoryStream.ToArray();
_SqlCommand.Parameters.Add(_SqlParameter);
// Executes a Transact-SQL statement against the connection
// and returns the number of rows affected.
_SqlRetVal = _SqlCommand.ExecuteNonQuery();
// Dispose command
_SqlCommand.Dispose();
_SqlCommand = null;
...但我不想使用数组来指定值。这适用于小数据大小,但不会随着大小变大。我想写成一个流。
答案 0 :(得分:7)
您应该能够将SqlBytes
的实例作为参数传递给SqlCommand
,只要需要varbinary
。同一个SqlBytes
类的constructor overload包含Stream
。因此,只需从流中创建一个SqlBytes
实例,然后将其作为参数值传递。
换句话说,将其纳入修改后的代码中,而不是:
MemoryStream _MemoryStream = new System.IO.MemoryStream();
_Image.Save(_MemoryStream, _ImageFormat);
SqlParameter _SqlParameter = new
SqlParameter("@" + _ImageFieldName, SqlDbType.Image);
_SqlParameter.Value = _MemoryStream.ToArray();
_SqlCommand.Parameters.Add(_SqlParameter);
使用此:
MemoryStream _MemoryStream = new System.IO.MemoryStream();
_Image.Save(_MemoryStream, _ImageFormat);
_MemoryStream.Position = 0; // I *think* you need this
SqlParameter _SqlParameter = new
SqlParameter("@" + _ImageFieldName, SqlDbType.VarBinary);
_SqlParameter.Value = new SqlBytes(_MemoryStream);
_SqlCommand.Parameters.Add(_SqlParameter);
当然,在命令执行完毕后,不要忘记处理MemoryStream
和所有其他IDisposable
个实例。
编辑:好的,我刚刚看到你编辑的底部,这暗示数据非常大,你不希望它最终在内存中,这实际上不会解决这个问题。事情是,如果价值那么大,那么首先将它存储在varbinary
列中是个坏主意。
如果您使用的是SQL Server 2008,则可以(而且应该!)使用FILESTREAM。这实际 通过ADO.NET类在SqlFileStream中支持“真实”流式传输。
如果您不能使用FILESTREAM
存储,那么我担心您将不得不在某个时间点处理内存中的数据,这几乎就是ADO.NET的工作方式。
答案 1 :(得分:2)
vladimir-khozeyev在他的回答中指出 How to I serialize a large graph of .NET object into a SQL Server BLOB without creating a large buffer?使用.NET Framework 4.5 SqlClient Streaming Support
时,您只需要一个StreamSQL代码:
CREATE TABLE BigFiles
(
[BigDataID] [int] IDENTITY(1,1) NOT NULL,
[Data] VARBINARY(MAX) NULL
)
C#代码:
using (FileStream sourceStream = new FileStream(filePath, FileMode.Open))
{
using (SqlCommand cmd = new SqlCommand(string.Format("UPDATE BigFiles SET Data=@Data WHERE BigDataID = @BigDataID"), _sqlConn))
{
cmd.Parameters.AddWithValue("@Data", sourceStream);
cmd.Parameters.AddWithValue("@BigDataID", entryId);
cmd.ExecuteNonQuery();
}
}
此代码适用于Windows 7,但在Windows XP和2003 Server上失败。