/// <summary>
        /// 根据ID数组移除模型
        /// </summary>
        /// <param name="ids">ID集合</param>
        /// <param name="connectionId">连接ID</param>
        /// <param name="currUser">当前用户</param>
        /// <returns>返回信息</returns>
        public override ReturnInfo <bool> RemoveByIds([DisplayName2("ID集合"), ArrayNotEmpty] int[] ids, string connectionId = null, BasicUserInfo currUser = null)
        {
            ReturnInfo <bool> re = new ReturnInfo <bool>();

            // 先取出当前ID集合的文件地址
            ReturnInfo <IList <AttachmentInfo> > returnInfo = Find(ids, connectionId, currUser);

            if (returnInfo.Failure() || returnInfo.Data.IsNullOrCount0())
            {
                re.FromBasic(returnInfo);

                return(re);
            }

            string[] fileAddress = new string[returnInfo.Data.Count];
            for (var i = 0; i < fileAddress.Length; i++)
            {
                fileAddress[i] = returnInfo.Data[i].FileAddress;
            }

            re = base.RemoveByIds(ids, connectionId, currUser);
            if (re.Failure())
            {
                return(re);
            }

            AttachmentUploadStore.Remove(currUser, fileAddress);

            return(re);
        }
        /// <summary>
        /// 根据归属移除
        /// </summary>
        /// <param name="ownerType">归属类型</param>
        /// <param name="ownerId">归属ID</param>
        /// <param name="connectionId">连接ID</param>
        /// <param name="currUser">当前用户</param>
        /// <returns>返回信息</returns>
        public virtual ReturnInfo <bool> RemoveByOwner(short ownerType, int ownerId, string connectionId = null, BasicUserInfo currUser = null)
        {
            ReturnInfo <bool> returnInfo = new ReturnInfo <bool>();
            ReturnInfo <IList <AttachmentInfo> > ownerReturnInfo = QueryByOwner(ownerType, ownerId, connectionId: connectionId, currUser: currUser);

            if (returnInfo.Failure() || ownerReturnInfo.Data.IsNullOrCount0())
            {
                returnInfo.FromBasic(ownerReturnInfo);

                return(returnInfo);
            }

            Persistence.DeleteByOwner(ownerType, ownerId, connectionId);

            // 查找所有的文件地址
            string[] fileAddress = new string[ownerReturnInfo.Data.Count];
            for (var i = 0; i < fileAddress.Length; i++)
            {
                fileAddress[i] = ownerReturnInfo.Data[i].FileAddress;
            }

            AttachmentUploadStore.Remove(currUser, fileAddress);

            return(returnInfo);
        }
        /// <summary>
        /// 根据ID移除模型
        /// </summary>
        /// <param name="id">ID</param>
        /// <param name="connectionId">连接ID</param>
        /// <param name="currUser">当前用户</param>
        /// <returns>返回信息</returns>
        public override ReturnInfo <bool> RemoveById([Id] int id, string connectionId = null, BasicUserInfo currUser = null)
        {
            ReturnInfo <bool> re = new ReturnInfo <bool>();

            // 先取出当前ID的文件地址
            ReturnInfo <AttachmentInfo> returnInfo = Find(id, connectionId, currUser);

            if (returnInfo.Failure() || returnInfo.Data == null)
            {
                re.FromBasic(returnInfo);

                return(re);
            }

            re = base.RemoveById(id, connectionId, currUser);
            if (re.Failure())
            {
                return(re);
            }

            if (!string.IsNullOrWhiteSpace(returnInfo.Data.FileAddress))
            {
                AttachmentUploadStore.Remove(currUser, returnInfo.Data.FileAddress);
            }

            return(re);
        }
        public virtual ReturnInfo <bool> Upload(IList <AttachmentInfo> attachments, IList <Stream> streams, BasicUserInfo currUser = null)
        {
            ReturnInfo <bool> re = new ReturnInfo <bool>();

            AttachmentStreamInfo[] attachmentStreams = new AttachmentStreamInfo[attachments.Count];
            for (var i = 0; i < attachments.Count; i++)
            {
                attachments[i].FileSize = Convert.ToSingle(streams[i].Length / 1024.00);
                ValiFile(attachments[i], re);
                if (re.Failure())
                {
                    return(re);
                }

                attachmentStreams[i] = new AttachmentStreamInfo()
                {
                    FileName = attachments[i].FileName,
                    Stream   = streams[i]
                };
            }
            ReturnInfo <IList <string> > returnInfo = AttachmentUploadStore.Upload(currUser, attachmentStreams);

            if (returnInfo.Failure())
            {
                ReturnInfo <bool> result = new ReturnInfo <bool>();
                result.FromBasic(returnInfo);

                return(result);
            }

            for (var i = 0; i < returnInfo.Data.Count; i++)
            {
                attachments[i].FileAddress = returnInfo.Data[i];
                attachments[i].ExpandName  = attachments[i].FileName.FileExpandName();
            }

            return(Add(attachments, currUser: currUser));
        }
        public virtual ReturnInfo <bool> Upload([DisplayName2("附件"), Model] AttachmentInfo attachment, Stream stream, BasicUserInfo currUser = null)
        {
            AttachmentStreamInfo attachmentStream = new AttachmentStreamInfo()
            {
                FileName = attachment.FileName,
                Stream   = stream
            };
            ReturnInfo <IList <string> > returnInfo = AttachmentUploadStore.Upload(currUser, attachmentStream);

            if (returnInfo.Failure())
            {
                ReturnInfo <bool> result = new ReturnInfo <bool>();
                result.FromBasic(returnInfo);

                return(result);
            }

            attachment.FileAddress = returnInfo.Data[0];
            attachment.ExpandName  = attachment.FileName.FileExpandName();
            attachment.FileSize    = Convert.ToSingle(stream.Length / 1024.00);

            return(Add(attachment, currUser: currUser));
        }