我想将一些文件的内容放入数据库,以便通过单独的进程读取。这是一个两步的事情,因为文件将被上传到java服务器,但后来由一个定期运行的单独的c#应用程序处理。
我打算使用nvarchar(Max)
列来表示数据,但我看不清楚如何以合理的方式从这种列中读取。我不想使用SqlDataReader.GetString
,因为这将迫使我立即将所有数据保存在内存中。这些文件并不大,但这似乎是一个愚蠢的事情 - 它会把它作为一个单独的字符串,然后需要分成几行,所以整个方法将完全倒退。
我假设我只能使用普通的流阅读器,但是调用GetStream
失败,说它不适用于这种类型的列。
有什么想法吗?是否只是更容易让数据库假装这不是真正的文本并将其存储为字节,以便我可以流式传输它?
答案 0 :(得分:3)
我前段时间写了这个扩展方法:
public static class DataExtensions
{
public static Stream GetStream(this IDataRecord record, int ordinal)
{
return new DbBinaryFieldStream(record, ordinal);
}
public static Stream GetStream(this IDataRecord record, string name)
{
int i = record.GetOrdinal(name);
return record.GetStream(i);
}
private class DbBinaryFieldStream : Stream
{
private readonly IDataRecord _record;
private readonly int _fieldIndex;
private long _position;
private long _length = -1;
public DbBinaryFieldStream(IDataRecord record, int fieldIndex)
{
_record = record;
_fieldIndex = fieldIndex;
}
public override bool CanRead
{
get { return true; }
}
public override bool CanSeek
{
get { return true; }
}
public override bool CanWrite
{
get { return false; }
}
public override void Flush()
{
throw new NotSupportedException();
}
public override long Length
{
get
{
if (_length < 0)
{
_length = _record.GetBytes(_fieldIndex, 0, null, 0, 0);
}
return _length;
}
}
public override long Position
{
get
{
return _position;
}
set
{
_position = value;
}
}
public override int Read(byte[] buffer, int offset, int count)
{
long nRead = _record.GetBytes(_fieldIndex, _position, buffer, offset, count);
_position += nRead;
return (int)nRead;
}
public override long Seek(long offset, SeekOrigin origin)
{
long newPosition = _position;
switch (origin)
{
case SeekOrigin.Begin:
newPosition = offset;
break;
case SeekOrigin.Current:
newPosition = _position + offset;
break;
case SeekOrigin.End:
newPosition = this.Length - offset;
break;
default:
break;
}
if (newPosition < 0)
throw new ArgumentOutOfRangeException("offset");
_position = newPosition;
return _position;
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
public override void Write(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
}
}
它是为BLOB设计的,但它也适用于NVARCHAR(最大)(至少在SQL Server上)。
你可以像这样使用它:
using (var dataReader = command.ExecuteReader())
{
dataReader.Read();
using (var stream = dataReader.GetStream("Text"))
using (var streamReader = new StreamReader(stream))
{
// read the text using the StreamReader...
}
}