我可以使用流来插入或更新SQL Server(C#)中的行吗?
假设我有一个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;
…但我不想使用数组来指定值。 这适用于小数据大小,但不会随着大小变大。 我想写成一个流。
无论何处需要varbinary
您都应该能够将SqlBytes
的实例作为参数传递给SqlCommand
。 同一个SqlBytes
类有一个包装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 。 这实际上通过SqlFileStream类支持ADO.NET中的 “真正”流式传输。
如果您不能使用FILESTREAM
存储,那么我担心您将不得不在某个时间点处理内存中的数据,这几乎就是ADO.NET的工作方式。
vladimir-khozeyev在他的回答中指出如何在不创建大缓冲区的情况下将.NET对象的大图形序列化为SQL Server BLOB? 在使用.NET Framework 4.5 SqlClient流支持时,您只需要一个Stream
SQL代码:
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上失败。