/// <summary>
        ///     Opens the specified attachment for editing
        /// </summary>
        /// <param name="index">Attachment index</param>
        /// <param name="autoSaveChanges">Should the object monitor changes on the edited file and save them back to the database?</param>
        public virtual void EditAttachment(FileAttachmentIndex index, bool autoSaveChanges)
        {
            var fName = Environment.TickCount.ToString(CultureInfo.InvariantCulture);
            // We use the temp internet path, which is convenient since the OS takes care of deleting files
            var tempPath = Environment.GetFolderPath(Environment.SpecialFolder.InternetCache) + @"\Milos";

            if (!Directory.Exists(tempPath))
            {
                Directory.CreateDirectory(tempPath);
            }
            var tempFileName = tempPath + @"\" + fName + "." + Type;

            SaveAttachmentAs(index, tempFileName);
            if (autoSaveChanges)
            {
                // We use a file watcher to monitor changes
                var watcher = new FileSystemWatcher(tempPath, fName + "." + Type)
                {
                    IncludeSubdirectories = false, NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.LastWrite
                };
                watcher.Changed            += OnEditedFileChanged;
                watcher.EnableRaisingEvents = true;
                Watchers.Add(watcher);
                WatchedFiles.Add(tempFileName, new WatcherInfo(PK, index, this, tempFileName));

                // We also use a timer to find out when the file has been closed
                // and we can do a final save
                if (_fileWatcherTimer == null)
                {
                    _fileWatcherTimer = new Timer(FileWatcherTimerTick, null, 10000, 10000);
                }
            }

            Process.Start(tempFileName);
        }
        /// <summary>
        ///     Saves the specified attachment as the specified file name.
        /// </summary>
        /// <param name="index">Attachment index</param>
        /// <param name="fileName">Name the file is to be saved as</param>
        public virtual void SaveAttachmentAs(FileAttachmentIndex index, string fileName)
        {
            switch (index)
            {
            case FileAttachmentIndex.FirstAttachment:
                if (Attachment.Length > 0)
                {
                    var fileStream = new FileStream(fileName, FileMode.CreateNew);
                    fileStream.Write(Attachment, 0, Attachment.Length);
                    fileStream.Close();
                }
                else
                {
                    throw new AttachmentNotFoundException("The current entity (" + Title + ") does not have a primary attachment.");
                }

                break;

            case FileAttachmentIndex.SecondAttachment:
                if (Attachment2.Length > 0)
                {
                    var fileStream = new FileStream(fileName, FileMode.CreateNew);
                    fileStream.Write(Attachment2, 0, Attachment.Length);
                    fileStream.Close();
                }
                else
                {
                    throw new AttachmentNotFoundException("The current entity (" + Title + ") does not have a secondary attachment.");
                }

                break;

            case FileAttachmentIndex.ThirdAttachment:
                if (Attachment3.Length > 0)
                {
                    var fileStream = new FileStream(fileName, FileMode.CreateNew);
                    fileStream.Write(Attachment3, 0, Attachment.Length);
                    fileStream.Close();
                }
                else
                {
                    throw new AttachmentNotFoundException("The current entity (" + Title + ") does not have a third attachment.");
                }

                break;
            }
        }
        ///// <summary>
        /////     Attaches the specified file from a web upload
        ///// </summary>
        ///// <param name="uploadFile">Http posted file</param>
        ///// <returns>True if successful</returns>
        //public virtual bool AttachFile(HttpPostedFile uploadFile)
        //{
        //    return AttachFile(uploadFile, FileAttachmentIndex.FirstAttachment);
        //}

        ///// <summary>
        /////     Attaches the specified file from a web upload
        ///// </summary>
        ///// <param name="uploadFile">Http posted file</param>
        ///// <param name="attachmentNumber">Attachment number/index</param>
        ///// <returns>True if successful</returns>
        //public virtual bool AttachFile(HttpPostedFile uploadFile, FileAttachmentIndex attachmentNumber)
        //{
        //    if (uploadFile.ContentLength < 1) throw new FileNotFoundException("Specified upload file does not exist (posted content has a length of 0 bytes).", uploadFile.FileName);

        //    var fileBytes = new byte[uploadFile.ContentLength];
        //    uploadFile.InputStream.Read(fileBytes, 0, uploadFile.ContentLength);

        //    // We can now assign the values to the current object
        //    switch (attachmentNumber)
        //    {
        //        case FileAttachmentIndex.FirstAttachment:
        //            Attachment = fileBytes;
        //            AttachDate = DateTime.Now.ToUniversalTime();
        //            FileDate = DateTime.Now.ToUniversalTime();
        //            FileName = JustFileName(uploadFile.FileName);
        //            Type = JustExtension(uploadFile.FileName);
        //            if (Title.Length == 0) Title = FileName;
        //            break;
        //        case FileAttachmentIndex.SecondAttachment:
        //            Attachment2 = fileBytes;
        //            FileDate2 = DateTime.Now.ToUniversalTime();
        //            FileName2 = JustFileName(uploadFile.FileName);
        //            Type2 = JustExtension(uploadFile.FileName);
        //            break;
        //        case FileAttachmentIndex.ThirdAttachment:
        //            Attachment3 = fileBytes;
        //            FileDate3 = DateTime.Now.ToUniversalTime();
        //            FileName3 = JustFileName(uploadFile.FileName);
        //            Type3 = JustExtension(uploadFile.FileName);
        //            break;
        //    }

        //    return true;
        //}

        ///// <summary>
        /////     Returns the file name of a full path
        ///// </summary>
        ///// <param name="fullName">Fully qualified file name</param>
        ///// <returns>File name</returns>
        //private static string JustFileName(string fullName)
        //{
        //    var occ = StringHelper.Occurs('\\', fullName);
        //    if (occ > 0) fullName = fullName.Substring(StringHelper.At("\\", fullName, occ));
        //    return fullName;
        //}

        ///// <summary>
        /////     Returns the extension of a full path/file
        ///// </summary>
        ///// <param name="fullName">Fully qualified file name</param>
        ///// <returns>File extension</returns>
        //private static string JustExtension(string fullName)
        //{
        //    var occ = StringHelper.Occurs('.', fullName);
        //    if (occ > 0) fullName = fullName.Substring(StringHelper.At(".", fullName, occ));
        //    return fullName;
        //}

        /// <summary>
        ///     Attaches the specified file
        /// </summary>
        /// <param name="fileName">File to attach</param>
        /// <param name="attachmentNumber">Attachment number/index</param>
        /// <returns>True if successful</returns>
        public virtual bool AttachFile(string fileName, FileAttachmentIndex attachmentNumber)
        {
            if (!File.Exists(fileName))
            {
                throw new FileNotFoundException("Specified file does not exist and can therefore not be attached.", fileName);
            }

            try
            {
                using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read))
                {
                    var fileData = new byte[fileStream.Length];
                    fileStream.Read(fileData, 0, (int)fileStream.Length);
                    fileStream.Close();
                    return(AttachFile(fileData, fileName, attachmentNumber));
                }
            }
            catch (IOException)
            {
                return(false);
            }
        }
        /// <summary>
        ///     Attaches the specified bytes as the file.
        /// </summary>
        /// <param name="fileData">The file data (bytes).</param>
        /// <param name="fileName">Name of the file.</param>
        /// <param name="attachmentNumber">The attachment number.</param>
        /// <returns></returns>
        public bool AttachFile(byte[] fileData, string fileName, FileAttachmentIndex attachmentNumber)
        {
            var fileInfo = new FileInfo(fileName);

            // We can now assign the values to the current object
            switch (attachmentNumber)
            {
            case FileAttachmentIndex.FirstAttachment:
                Attachment = fileData;
                AttachDate = DateTime.Now.ToUniversalTime();
                FileDate   = File.GetCreationTime(fileName);
                FileName   = fileInfo.Name;
                Type       = fileInfo.Extension;
                if (Title.Length == 0)
                {
                    Title = fileInfo.Name;
                }
                break;

            case FileAttachmentIndex.SecondAttachment:
                Attachment2 = fileData;
                FileDate2   = File.GetCreationTime(fileName);
                FileName2   = fileInfo.Name;
                Type2       = fileInfo.Extension;
                break;

            case FileAttachmentIndex.ThirdAttachment:
                Attachment3 = fileData;
                FileDate3   = File.GetCreationTime(fileName);
                FileName3   = fileInfo.Name;
                Type3       = fileInfo.Extension;
                break;
            }

            return(true);
        }