/// <summary>
        /// Получить контент сообщения.
        /// </summary>
        /// <param name="contentLink"></param>
        /// <returns></returns>
        public virtual MessageContent GetMessageContent(int contentLink)
        {
            UnitOfWork work = BeginWork();

            MessageContentInfo contentInfo = work.Get <DAO.MessageContentInfo>(contentLink).ToObj();

            if (contentInfo == null)
            {
                return(null);
            }

            MessageContentStreamBase stream = ConstructMessageContentStream(contentInfo.LINK, work, DataStreamMode.READ, contentInfo.ContentType().Encoding());

            stream.ReadTimeout = this.ExecuteTimeout;

            if (contentInfo.Length == null)
            {
                contentInfo.Length = (int)stream.Length;
            }

            var content = new MessageContent();

            content.ApplyInfo(contentInfo);
            content.Value = new MessageContentReader(stream, this.bufferSize);

            return(content);
        }
        /// <summary>
        ///
        /// </summary>
        /// <param name="stream"></param>
        /// <param name="bufferSize">Больше или равно 1024.</param>
        public MessageContentReader(MessageContentStreamBase stream, int bufferSize)
        {
            #region Validate parameters
            if (stream == null)
            {
                throw new ArgumentNullException("stream");
            }

            if (!stream.CanRead)
            {
                throw new ArgumentException("Поток не доступен для чтения.", "stream");
            }

            if (bufferSize < 1024)
            {
                throw new ArgumentException("Недостаточный размер буфера данных.", "bufferSize");
            }
            #endregion

            this.baseStream = stream;
            this.bufferSize = bufferSize;
        }
        /// <summary>
        /// Сохранить контент сообщения.
        /// </summary>
        /// <param name="content"></param>
        public virtual void SaveMessageContent(MessageContent content)
        {
            #region Validate parameters
            if (content == null)
            {
                throw new ArgumentNullException("content");
            }
            #endregion

            MessageContentInfo contentInfo = content.ContentInfo();
            ContentType        contentType = contentInfo.ContentType();
            Encoding           encoding    = contentType.Encoding();

            using (UnitOfWork work = BeginWork())
            {
                int msgLink = content.MessageLINK.Value;
                var msg     = work.Get <DAO.Message>(msgLink);
                if (msg == null)
                {
                    throw new MessageNotFoundException(msgLink);
                }

                DAO.MessageContentInfo dao = contentInfo.ToDao(msg);

                if (dao.LINK == 0)
                {
                    work.Save(dao);
                }
                else
                {
                    work.Update <DAO.MessageContentInfo>(ref dao);
                }

                if (content.Value != null)
                {
                    using (MessageContentStreamBase stream = ConstructMessageContentStream(dao.LINK, work, DataStreamMode.WRITE, encoding))
                    {
                        stream.WriteTimeout = this.ExecuteTimeout;

                        var buffer = new char[this.bufferSize];
                        int charsReaded;
                        do
                        {
                            charsReaded = content.Value.Read(buffer, 0, buffer.Length);
                            if (charsReaded > 0)
                            {
                                stream.Write(buffer, 0, charsReaded);
                            }
                        } while (charsReaded > 0);

                        if (dao.Length == null)
                        {
                            dao.Length = (int)stream.Length;
                            work.Update <DAO.MessageContentInfo>(ref dao);
                        }

                        work.End();
                    }
                }
                else
                {
                    work.End();
                }

                contentInfo = dao.ToObj();
                content.ApplyInfo(contentInfo);
            }
        }