public void AddPage(WikiPage p)
        {
            p.ThrowIfArgumentNull();
            p.Title.ThrowIfArgumentNull();
            p.Body.ThrowIfArgumentNull();

            var found = pages.FindOne(Query.EQ("Title", p.Title));

            if (found != null)
                throw new Exception(string.Format("Wiki title clash, offending ID = {0}", found.ID.ToString()));

            if (p.CreatedOn == DateTime.MinValue)
                p.CreatedOn = DateTime.Now;

            if (string.IsNullOrEmpty(p.Alias))
                p.Alias = aliasify(p.Title);

            if (p.ID == null)
                p.ID = ObjectId.GenerateNewId();

            pages.Insert(p);

            pages.EnsureIndex("AuthorID", "Title");
        }
        public void UpdatePage(WikiPage p)
        {
            p.ThrowIfArgumentNull();
            p.ID.ThrowIfArgumentNull();

            __Page _p = db.__Pages.FirstOrDefault(x => x.ID == p.ID);

            if (_p != null)
            {
                _p.CreatedOn = p.CreatedOn;
                _p.ModifiedOn = p.ModifiedOn;
                _p.Alias = p.Alias;
                _p.AuthorID = p.AuthorID;
                _p.Title = p.Title;
                _p.Body = p.Body;
                _p.Published = p.Published;

                db.SubmitChanges();
            }
        }
        public List<WikiTag> GetPageTags(WikiPage p)
        {
            p.ThrowIfArgumentNull();
            p.ID.ThrowIfArgumentNull();

            List<WikiTag> result = null;

            List<__PageTag> _pt = db.__PageTags.Where(x => x.PageID == p.ID).ToList();

            if (_pt != null)
            {
                foreach (var pt in _pt)
                {
                    result.Add(new WikiTag()
                    {
                        ID = pt.ID,
                        CreatedOn = pt.__Tag.CreatedOn,
                        Name = pt.__Tag.Name
                    });
                }
            }

            return result;
        }
        public WikiPage GetPage(int id)
        {
            WikiPage result = null;

            __Page _p = db.__Pages.FirstOrDefault(x => x.ID == id);

            if (_p != null)
            {
                result = new WikiPage()
                {
                    ID = _p.ID,
                    CreatedOn = _p.CreatedOn,
                    ModifiedOn = _p.ModifiedOn,
                    Alias = _p.Alias,
                    AuthorID = _p.AuthorID,
                    Title = _p.Title,
                    Body = _p.Body,
                    Published = _p.Published
                };
            }

            return result;
        }
        public void DeletePageTags(WikiPage p)
        {
            p.ThrowIfArgumentNull();
            p.ID.ThrowIfArgumentNull();

            List<__PageTag> _pageTags = db.__PageTags.Where(x => x.ID == p.ID).ToList();

            if (_pageTags != null)
            {
                db.__PageTags.DeleteAllOnSubmit(_pageTags);
                db.SubmitChanges();
            }
        }
        public void DeletePage(WikiPage p)
        {
            p.ThrowIfArgumentNull();
            p.ID.ThrowIfArgumentNull();

            __Page _p = db.__Pages.FirstOrDefault(x => x.ID == p.ID);

            if (_p != null)
            {
                db.__Pages.DeleteOnSubmit(_p);
                db.SubmitChanges();
            }
        }
        public void AddPageTag(WikiPage p, string name)
        {
            p.ThrowIfArgumentNull();
            p.ID.ThrowIfArgumentNull();

            __Page _p = db.__Pages.FirstOrDefault(x => x.ID == p.ID);

            if (_p != null)
            {
                __PageTag _pt = db.__PageTags.FirstOrDefault(x => x.__Tag.Name == name);

                if (_pt == null)
                {
                    __Tag _t = db.__Tags.FirstOrDefault(x => x.Name == name);

                    if (_t == null)
                    {
                        __Tag _newTag = new __Tag()
                        {
                            Name = name,
                            CreatedOn = DateTime.Now
                        };

                        db.__Tags.InsertOnSubmit(_newTag);
                        db.SubmitChanges();

                        __PageTag _newPageTag = new __PageTag()
                        {
                            TagID = _newTag.ID,
                            PageID = p.ID
                        };

                        db.__PageTags.InsertOnSubmit(_newPageTag);
                        db.SubmitChanges();
                    }
                }
            }
        }
        public void AddPage(WikiPage p)
        {
            p.ThrowIfArgumentNull();
            p.Title.ThrowIfArgumentNull();

            Func<string, string> aliasify = delegate(string s)
                    {
                        s = matchSpecialCharacters.Replace(s, string.Empty).Trim();
                        s = matchWhitespaces.Replace(s, "-");

                        return s;
                    };

            __Page _p = new __Page()
            {
                CreatedOn = (p.CreatedOn == DateTime.MinValue) ? DateTime.Now : p.CreatedOn,
                ModifiedOn = p.ModifiedOn,
                Alias = p.Alias ?? aliasify(p.Title),
                AuthorID = p.AuthorID,
                Title = p.Title,
                Body = p.Body,
                Published = p.Published
            };

            try
            {
                db.__Pages.InsertOnSubmit(_p);
                db.SubmitChanges();
            }
            catch (SqlException e)
            {
                Console.WriteLine(string.Format("{0} - Page Title = {1}", e.Message, p.Title));
            }

            p.ID = _p.ID;
        }
        public void UpdatePage(WikiPage p)
        {
            p.ThrowIfArgumentNull();

            var page = pages.FindOneById(p.ID);

            if (page != null)
            {
                page.Alias = aliasify(p.Title);
                page.Body = p.Body;
                page.Title = p.Title;
                page.ModifiedOn = DateTime.Now;
                page.Published = p.Published;
                page.Tags = p.Tags;

                var update = Update.Replace<WikiPage>(page);
                pages.Update(Query.EQ("_id", p.ID), update);
            }
        }
        public List<WikiTag> GetPageTags(WikiPage p)
        {
            p.ThrowIfArgumentNull();

            if (p.Tags == null || !(p.Tags.Count() > 0))
                return new List<WikiTag>();

            return tags.Find(Query.In("_id", new BsonArray(p.Tags))).ToList();
        }
        public void DeletePageTags(WikiPage p)
        {
            p.ThrowIfArgumentNull();

            var page = pages.FindOneById(p.ID);

            if (page != null)
            {
                var update = Update.Unset("Tags");
                pages.Update(Query.EQ("_id", p.ID), update);
            }
        }
        public void AddPageTag(WikiPage p, string name)
        {
            p.ThrowIfArgumentNull();

            var page = pages.FindOneById(p.ID);

            if (page != null)
            {
                if (page.Tags == null)
                    page.Tags = new List<ObjectId>();

                var tag = tags.FindOne(Query.EQ("Name", name));

                if (tag != null)
                    page.Tags.Add(tag.ID);
                else
                {
                    WikiTag newTag = new WikiTag()
                    {
                        ID = ObjectId.GenerateNewId(),
                        Name = name
                    };

                    tags.Insert(newTag);
                    page.Tags.Add(newTag.ID);
                }

                var update = Update.SetWrapped("Tags", page.Tags);
                pages.Update(Query.EQ("_id", p.ID), update);

                pages.EnsureIndex("Tags");
            }
        }