/// <summary>
        /// Removes the message with the given ID from the store.
        /// </summary>
        /// <param name="id">The ID of the message to remove.</param>
        /// <returns>true, if the message with the given ID was removed;
        /// false, if no message with the given ID was in this store.</returns>
        public bool Remove(string id)
        {
            using (MessageDataContext context = new MessageDataContext(connectionString))
            {
                IQueryable <StoredMessage> query = from msg in context.Messages
                                                   where msg.Id == id
                                                   select msg;

                if (query.Count() > 0)
                {
                    StoredMessage   storedMessage     = query.First();
                    IMessage        message           = MakeMessage(storedMessage);
                    MessageProvider provider          = MessageProviderFactory.Instance.GetProvider(message.Provider);
                    bool            deleteImmediately = false;

                    contentManager.DeleteFiles(message.Content);

                    if (provider != null)
                    {
                        deleteImmediately = !provider.NeedsDeletionStubs;
                    }

                    if (deleteImmediately)
                    {
                        IQueryable <Reader> deletedReadersQuery = from rdr in context.Readers
                                                                  where rdr.MessageId == id
                                                                  select rdr;

                        context.Readers.DeleteAllOnSubmit(deletedReadersQuery.ToList());
                        context.Messages.DeleteOnSubmit(storedMessage);
                        context.SubmitChanges();
                    }
                    else
                    {
                        storedMessage.IsDeleted     = true;
                        storedMessage.ContentString = null;
                        storedMessage.Notification  = null;
                        storedMessage.ExpiryDate    = DateTime.Now + TimeSpan.FromDays(2);
                        context.SubmitChanges();
                    }

                    OnChanged(new MessageStoreChangedEventArgs(message, MessageAction.Deleted));

                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }
        /// <summary>
        /// Add a reader for a message.
        /// </summary>
        /// <param name="message">The message to be marked as read by a reader.</param>
        /// <param name="name">The name of the reader.</param>
        /// <returns>true, if the reader was added;
        /// false, if the message was already marked as read by the reader or is not in this store.</returns>
        public bool AddReader(IMessage message, string name)
        {
            using (MessageDataContext context = new MessageDataContext(connectionString))
            {
                IQueryable <Reader> readerQuery = from rdr in context.Readers
                                                  where rdr.MessageId == message.Id && rdr.Name == name
                                                  select rdr;

                if (readerQuery.Count() == 0)
                {
                    IQueryable <StoredMessage> messageQuery = from msg in context.Messages
                                                              where msg.Id == message.Id
                                                              select msg;

                    if (messageQuery.Count() != 0)
                    {
                        Reader reader = new Reader();

                        reader.MessageId = message.Id;
                        reader.Name      = name;

                        context.Readers.InsertOnSubmit(reader);
                        context.SubmitChanges();

                        return(true);
                    }
                }

                return(false);
            }
        }
        private void PurgeExpiredMessages()
        {
            using (MessageDataContext context = new MessageDataContext(connectionString))
            {
                IQueryable <string> expiredIdsQuery = from msg in context.Messages
                                                      where msg.ExpiryDate < DateTime.Now
                                                      select msg.Id;

                List <string> expiredIds = expiredIdsQuery.ToList();

                OnMessagesExpired(expiredIds);

                IQueryable <Reader> expiredReadersQuery = from rdr in context.Readers
                                                          where expiredIds.Contains(rdr.MessageId)
                                                          select rdr;

                context.Readers.DeleteAllOnSubmit(expiredReadersQuery.ToList());

                IQueryable <StoredMessage> expiredMessagesQuery = from msg in context.Messages
                                                                  where msg.ExpiryDate < DateTime.Now
                                                                  select msg;

                context.Messages.DeleteAllOnSubmit(expiredMessagesQuery.ToList());
                context.SubmitChanges();
            }
        }
        /// <summary>
        /// Adds a message to this store.
        /// </summary>
        /// <param name="message">The message to add.</param>
        /// <returns>true, if the message was added; false, if the message is already in this store.</returns>
        public bool Add(IMessage message)
        {
            if (message.ExpiryDate >= DateTime.Now)
            {
                using (MessageDataContext context = new MessageDataContext(connectionString))
                {
                    IQueryable <StoredMessage> query = from msg in context.Messages
                                                       where msg.Id == message.Id
                                                       select msg;

                    if (query.Count() == 0)
                    {
                        StoredMessage storedMessage = MakeStoredMessage(message);

                        context.Messages.InsertOnSubmit(storedMessage);
                        context.SubmitChanges();

                        OnChanged(new MessageStoreChangedEventArgs(message, MessageAction.Created));

                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
            }
            else
            {
                return(AddAsDeleted(message));
            }
        }
        /// <summary>
        /// Clears the store.
        /// </summary>
        public void Clear()
        {
            canFireChangedHandler = false;

            try
            {
                ContentManager contentManager = new ContentManager(logger);

                using (MessageDataContext context = new MessageDataContext(connectionString))
                {
                    IQueryable <StoredMessage> query = from msg in context.Messages
                                                       where !msg.IsDeleted
                                                       select msg;

                    IList <IMessage> messages = MakeMessages(query.ToList <StoredMessage>());

                    foreach (IMessage message in messages)
                    {
                        contentManager.DeleteFiles(message.Content);
                    }
                }

                using (MessageDataContext context = new MessageDataContext(connectionString))
                {
                    IQueryable <Reader> expiredReadersQuery = from rdr in context.Readers
                                                              select rdr;

                    context.Readers.DeleteAllOnSubmit(expiredReadersQuery.ToList());

                    IQueryable <StoredMessage> expiredMessagesQuery = from msg in context.Messages
                                                                      select msg;

                    context.Messages.DeleteAllOnSubmit(expiredMessagesQuery.ToList());
                    context.SubmitChanges();
                }
            }
            catch (Exception e)
            {
                if (logger != null)
                {
                    logger.WarnFormat("Cannot clear {0}: {1}", this, e.Message);
                }
            }

            canFireChangedHandler = true;
        }
        /// <summary>
        /// Updates a message, provided it exists in the store.
        /// </summary>
        /// <param name="message">The message to update.</param>
        /// <returns>Wther the message was updated.</returns>
        public bool Update(IMessage message)
        {
            using (MessageDataContext context = new MessageDataContext(connectionString))
            {
                IQueryable <StoredMessage> query = from msg in context.Messages
                                                   where msg.Id == message.Id
                                                   select msg;

                if (query.Count() == 1)
                {
                    StoredMessage storedMessage = query.First <StoredMessage>();

                    UpdateStoredMessage(message, ref storedMessage);
                    context.SubmitChanges();

                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }
        /// <summary>
        /// Adds a message to this store and marks it as deleted. Changed events will <i>not</i> be fired.
        /// </summary>
        /// <param name="message">The message to add.</param>
        /// <returns>true, if the message was added; false, if the message is already in this store.</returns>
        private bool AddAsDeleted(IMessage message)
        {
            using (MessageDataContext context = new MessageDataContext(connectionString))
            {
                IQueryable <StoredMessage> query = from msg in context.Messages
                                                   where msg.Id == message.Id
                                                   select msg;

                if (query.Count() == 0)
                {
                    StoredMessage storedMessage = MakeStoredMessage(message);

                    storedMessage.IsDeleted = true;
                    context.Messages.InsertOnSubmit(storedMessage);
                    context.SubmitChanges();

                    return(true);
                }
                else
                {
                    return(false);
                }
            }
        }