简体   繁体   English

使用C#从NVarchar(Max)列流式传输数据

[英]Streaming data from a NVarchar(Max) column using c#

I want to put the contents of some files into the database to be read by a seperate process. 我想将一些文件的内容放到数据库中,以供一个单独的进程读取。 This is a two step thing as the files will be uploaded to a java server but then processed by a seperate c# application that runs periodically. 这是两步操作,因为文件将上传到Java服务器,然后由定期运行的单独c#应用程序处理。

I was planning on using a nvarchar(Max) column to represent the data but I can't see how to read from that sort of column in a sensible way. 我打算使用nvarchar(Max)列来表示数据,但是我看不到如何以一种明智的方式从这种列中读取数据。 I don't want to use SqlDataReader.GetString as that will force me to hold all the data in memory at once. 我不想使用SqlDataReader.GetString因为这将迫使我一次将所有数据保存在内存中。 The files aren't massive but that just seems like a stupid thing to do - it'll give me it as a single string which will then need splitting up into lines, so the whole approach would be totally backwards. 文件不是很大,但是这看起来像是一个愚蠢的事情-将它作为单个字符串提供给我,然后需要分成几行,因此整个方法将完全倒退。

I was assuming I'd just be able to use a normal stream reader but calling GetStream fails saying it doesn't work for this type of column. 我以为我只能使用普通的流读取器,但调用GetStream无法说不适用于这种类型的列。

Any ideas? 有任何想法吗? Is it just going to be easier for the database to pretend this isn't really text and store it as bytes so I can stream it? 让数据库假装这不是真正的文本并将其存储为字节以便我可以流式传输是否会更加容易?

I wrote this extension method some time ago: 我前一段时间写了这个扩展方法:

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();
        }
    }
}

It's designed for a BLOB, but it works for a NVARCHAR(max) as well (at least on SQL Server). 它是为BLOB设计的,但也可以用于NVARCHAR(max)(至少在SQL Server上)。

You can use it like this: 您可以像这样使用它:

    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...
        }
    }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM