/* * This work is licensed under the Creative Commons Attribution 2.5 License. * To view a copy of this license, visit http://creativecommons.org/licenses/by/2.5/ * or send a letter to Creative Commons, 543 Howard Street, 5th Floor, * San Francisco, California, 94105, USA. * * Original developer: David Betz * */ using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; using System.ServiceModel.Syndication; using System.Text; using Minima.Addon; using Minima.Data.Context; using Minima.Data.Entities; using Minima.Helpers; namespace Minima { /// /// Class to simplify and centralize interaction with the database. /// public class MinimaFacade { #region Add-ons /// /// Pings Technorati - see www.technorati.com /// /// ID of the blog to ping public void PingTechnorati(Int32 blogId) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { Blog blog = null; try { blog = db.Blogs.Single(p => p.BlogId == blogId); } catch (InvalidOperationException ex) { if (ex.Message == "Sequence contains no elements") { throw new ArgumentOutOfRangeException("That blog ID does not exist.", ex); } } TechnoratiNotifier.Ping(blog.BlogTitle, new Uri(blog.BlogPrimaryUrl)); } } #endregion #region Blogs /// /// Returns only the details of a blog /// /// ID of the blog /// A filled blog object; it does not contain entries public Blog GetBlogDetails(Int32 blogId, MinimaLINQDataContext db) { var all = db.Blogs.Single(p => p.BlogId == blogId); var shell = new Blog(); foreach (var a in all.BlogEntries) { shell.BlogCreateDate = all.BlogCreateDate; shell.BlogDescription = all.BlogDescription; shell.BlogFeedTitle = all.BlogFeedTitle; shell.BlogFeedUrl = all.BlogFeedUrl; shell.BlogId = all.BlogId; shell.BlogPrimaryUrl = all.BlogPrimaryUrl; shell.BlogTitle = all.BlogTitle; shell.Labels = all.Labels; } return shell; } /// /// Returns the title of a blog /// /// ID of the blog /// Title of the blog public String GetBlogTitle(Int32 blogId) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { return db.Blogs.Single(p => p.BlogId == blogId).BlogTitle; } } /// /// Returns a blog. /// /// ID of the blog /// Number of most recent entries to retrieve /// If true, the content of the blog entries are returned. Otherwise, it is not. You should only return the content if you absolutely need it. /// A filled blog object public Blog GetBlog(Int32 blogId, Int32 count, MinimaLINQDataContext db) { return db.Blogs.Single(p => p.BlogId == blogId); } /// /// Returns a blog entry by url mapping. Mainly only used by the website. /// /// Url mapping as would be seen in the URL address. /// A blog object filled with a single blog entry public BlogEntry GetBlogEntryByUrlMapping(Int32 blogId, String urlMapping, MinimaLINQDataContext db) { var blogEntry = (from be in db.BlogEntries join beum in db.BlogEntryUrlMappings on be.BlogEntryId equals beum.BlogEntryId where beum.BlogEntryUrlMappingName == urlMapping.ToLower() && be.BlogId == blogId select be).First(); return blogEntry; } #endregion #region Blog Entry /// /// Creates a blog entry /// /// ID of the blog /// Set of authors /// Title of the blog entry /// Date and time of the blog entry, for "now" use a date before 1950 /// Content of the blog entry /// Set of labels, these will be created if they do not exist /// public Int32 CreateNewBlogEntry(Int32 blogId, Author[] authorSet, String title, String content, DateTime dateTime, Label[] labelSet, Boolean publish) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { if (authorSet == null || authorSet.Length < 1) { throw new ArgumentNullException("Author may not be null"); } else { foreach (Author author in authorSet) { if (String.IsNullOrEmpty(author.AuthorEmail)) { throw new ArgumentNullException("Author e-mail may not be null"); } } } BlogEntry be = new BlogEntry(); be.BlogId = blogId; be.BlogEntryTitle = title; be.BlogEntryText = content; be.BlogEntryStatusId = publish ? 1 : 3; if (dateTime.Year >= 1950) { be.BlogEntryPostDateTime = dateTime; } be.BlogEntryModifyDateTime = DateTime.Now; db.BlogEntries.InsertOnSubmit(be); try { db.SubmitChanges(); } catch { } BlogEntryUrlMapping beum = new BlogEntryUrlMapping(); beum.BlogEntryId = be.BlogEntryId; beum.BlogEntryUrlMappingName = CreateBlogEntryPostUrlMapping(title); db.BlogEntryUrlMappings.InsertOnSubmit(beum); db.SubmitChanges(); if (labelSet != null && labelSet.Length > 0) { foreach (Label label in labelSet) { var c = from p in db.Labels select p; Int32 labelId = 0; String lower = label.LabelTitle.ToLower(); foreach (Label l in c) { if (l.LabelTitle.ToLower() == lower) { labelId = l.LabelId; break; } } if (labelId == 0) { Label l = new Label(); l.BlogId = blogId; l.LabelTitle = label.LabelTitle; db.Labels.InsertOnSubmit(l); db.SubmitChanges(); labelId = l.LabelId; } LabelBlogEntry lbe = new LabelBlogEntry(); lbe.BlogEntryId = be.BlogEntryId; lbe.LabelId = labelId; db.LabelBlogEntries.InsertOnSubmit(lbe); db.SubmitChanges(); } } if (authorSet != null && authorSet.Length > 0) { foreach (Author author in authorSet) { var c = from p in db.Authors select p; Int32 authorId = 0; String lower = author.AuthorEmail.ToLower(); foreach (Author l in c) { if (l.AuthorEmail.ToLower() == lower) { authorId = l.AuthorId; break; } } if (authorId == 0) { if (String.IsNullOrEmpty(author.AuthorEmail)) { throw new ArgumentNullException("Author does not exist. Therefore, the author name is required."); } Author l = new Author(); l.AuthorName = author.AuthorName; l.AuthorEmail = author.AuthorEmail; db.Authors.InsertOnSubmit(l); db.SubmitChanges(); authorId = l.AuthorId; } BlogEntryAuthor lbe = new BlogEntryAuthor(); lbe.BlogEntryId = be.BlogEntryId; lbe.AuthorId = authorId; db.BlogEntryAuthors.InsertOnSubmit(lbe); db.SubmitChanges(); } } else { throw new ArgumentNullException("There must be at least one author for a blog entry"); } return be.BlogEntryId; } } /// /// Deletes a blog entry. For debug purposes only. /// /// ID of the blog entry to delete public void DeleteBlogEntry(Int32 blogEntryId) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { var authorLinks = from p in db.BlogEntryAuthors where p.BlogEntryId == blogEntryId select p; var urlLinks = from p in db.BlogEntryUrlMappings where p.BlogEntryId == blogEntryId select p; var labelLinks = from p in db.LabelBlogEntries where p.BlogEntryId == blogEntryId select p; if (authorLinks.Count() > 0) { foreach (BlogEntryAuthor t1 in authorLinks) { db.BlogEntryAuthors.DeleteOnSubmit(t1); } } db.SubmitChanges(); if (urlLinks.Count() > 0) { foreach (BlogEntryUrlMapping t2 in urlLinks) { db.BlogEntryUrlMappings.DeleteOnSubmit(t2); } } db.SubmitChanges(); if (labelLinks.Count() > 0) { foreach (LabelBlogEntry t3 in labelLinks) { db.LabelBlogEntries.DeleteOnSubmit(t3); } } db.SubmitChanges(); var b = db.BlogEntries.Single(p => p.BlogEntryId == blogEntryId); db.BlogEntries.DeleteOnSubmit(b); db.SubmitChanges(); } } /// /// Updates various properties of a blog entry /// /// ID of the blog entry to update /// Title of the blog entry /// Content of the blog entry, blank if no change /// Date and time of the blog entry, for "now" use a date before 1950 /// Published on true, Draft on false public void UpdateBlogEntry(Int32 blogEntryId, String title, String content, DateTime dateTime, Boolean publish) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { BlogEntry be = null; try { be = db.BlogEntries.Single(p => p.BlogEntryId == blogEntryId); } catch (InvalidOperationException ex) { if (ex.Message == "Sequence contains no elements") { throw new ArgumentOutOfRangeException("Invalid blog entry ID.", ex); } } if (dateTime.Year >= 1950) { be.BlogEntryPostDateTime = dateTime; } be.BlogEntryStatusId = publish ? 1 : 3; if (!String.IsNullOrEmpty(content)) { be.BlogEntryText = content; } if (!String.IsNullOrEmpty(title)) { // Has this title's mapping been used by a different blog entry? String mapping = CreateBlogEntryPostUrlMapping(title); var beumc = from p in db.BlogEntryUrlMappings where p.BlogEntryUrlMappingName == mapping && p.BlogEntryId != blogEntryId select p; // Probably something I'll be fixing in the future... if (beumc.Count() > 1) { throw new ArgumentException("This title's mapping has already been used, please change the title"); } beumc = from p in db.BlogEntryUrlMappings where p.BlogEntryUrlMappingName == mapping && p.BlogEntryId == blogEntryId select p; // If this is a new title completely, create a new mapping to allow access by // the old and the new links if (beumc.Count() < 1) { BlogEntryUrlMapping beum = new BlogEntryUrlMapping(); beum.BlogEntryId = blogEntryId; beum.BlogEntryUrlMappingName = CreateBlogEntryPostUrlMapping(title); db.BlogEntryUrlMappings.InsertOnSubmit(beum); db.SubmitChanges(); } } be.BlogEntryTitle = title; db.SubmitChanges(); } } /// /// Returns the ID of the blog that a blog entry to which a blog entry corresponds /// /// ID of the blog entry /// ID of the blog public Int32 GetBlogIdByBlogEntryId(Int32 blogEntryId) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { return db.BlogEntries.Single(p => p.BlogEntryId == blogEntryId).BlogId; } } /// /// Returns the title of a blog entry by blog entry ID /// /// ID of the blog entry /// Title of the blog entry public String GetBlogEntryTitle(Int32 blogEntryId) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { return db.BlogEntries.Single(p => p.BlogEntryId == blogEntryId).BlogEntryTitle; } } /// /// Returns a complete blog entry /// /// ID of the blog entry /// The blog entry object public BlogEntry GetBlogEntry(Int32 blogEntryId, MinimaLINQDataContext db) { return db.BlogEntries.Single(p => p.BlogEntryId == blogEntryId); } public void DisableBlogEntry(Int32 blogEntryId) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { var be = db.BlogEntries.Single(p => p.BlogEntryId == blogEntryId); be.BlogEntryStatusId = 2; db.SubmitChanges(); } } public List GetCompleteBlogEntryLinkList(Int32 blogId) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { var blogEntries = from p in db.BlogEntries where p.BlogEntryStatusId == 1 && p.BlogId == blogId select p; List set = new List(); foreach (var e in blogEntries) { set.Add(new BlogEntryAccessSummary(new Uri(BlogEntrySupport.GetBlogEntryUrl(e)), e.BlogEntryPostDateTime)); } return set; } } #endregion #region Feed /// /// Returns the feed URL of the blog /// /// /// A feed object public Feed GetFeedUrl(Int32 blogId) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { var blog = db.Blogs.Single(p => p.BlogId == blogId); return new Feed(blog.BlogFeedTitle, blog.BlogFeedUrl); } } /// /// Publish RSS feed to specified location /// /// ID of the blog /// Maximum number of blog entries to return /// XML of RSS Feed public SyndicationFeed GetRssFeed(Int32 blogId, Int32 maxNumberOfEntries) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { var collection = from p in db.BlogEntries where p.BlogId == blogId && p.BlogEntryStatusId == 1 orderby p.BlogEntryPostDateTime descending select p; SyndicationFeed feed = new SyndicationFeed(); if (collection.Count() < 1) { throw new ArgumentException("There are no blog entries"); } var blog = db.Blogs.Single(p => p.BlogId == blogId); feed.Title = new TextSyndicationContent(blog.BlogTitle); feed.Description = new TextSyndicationContent(blog.BlogDescription); feed.Links.Add(new SyndicationLink(new Uri(MinimaConfiguration.Domain))); Collection items = new Collection(); foreach (BlogEntry entity in collection) { SyndicationItem item = new SyndicationItem(); StringBuilder authors = new StringBuilder(); foreach (BlogEntryAuthor a in entity.BlogEntryAuthors) { item.Authors.Add(new SyndicationPerson(a.Author.AuthorEmail, a.Author.AuthorName, MinimaConfiguration.Domain)); } item.Title = new TextSyndicationContent(entity.BlogEntryTitle); if (entity.BlogEntryUrlMappings.Count < 1) { throw new ArgumentNullException("Missing url mapping. Every blog entry must have at least one associated url mapping."); } item.Links.Add(new SyndicationLink(new Uri(String.Format("{0}/{1}/{2}/{3}.aspx", UrlHelper.FixWebPath(MinimaConfiguration.Domain), entity.BlogEntryPostYear, (entity.BlogEntryPostMonth > 9 ? entity.BlogEntryPostMonth.ToString() : "0" + entity.BlogEntryPostMonth.ToString()), entity.BlogEntryUrlMappings.ElementAt(0).BlogEntryUrlMappingName)))); item.Summary = new TextSyndicationContent(entity.BlogEntryText); item.PublishDate = new DateTimeOffset(entity.BlogEntryPostDateTime); items.Add(item); if (items.Count == maxNumberOfEntries) { break; } } feed.Items = items; return feed; //+ Use this if you would like to obtain the XML output //StringBuilder b = new StringBuilder( ); //StringWriter writer = new StringWriter(b); //XmlTextWriter xmlWriter = new XmlTextWriter(writer); //feed.SaveAsRss20(xmlWriter); } } #endregion #region Special /// /// Returns a blog. /// /// ID of the blog /// Number of most recent entries to retrieve /// If true, the content of the blog entries are returned. Otherwise, it is not. You should only return the content if you absolutely need it. /// A filled blog object public List GetBlogEntries(Int32 blogId, Int32 count, Boolean activeOnly, MinimaLINQDataContext db) { List blogEntries = null; if (activeOnly) { blogEntries = (from be in db.BlogEntries where be.BlogId == blogId && be.BlogEntryStatusId == 1 orderby be.BlogEntryPostDateTime descending select be).Take(count).ToList(); } else { blogEntries = (from be in db.BlogEntries where be.BlogId == blogId orderby be.BlogEntryPostDateTime descending select be).Take(count).ToList(); } return blogEntries; } /// /// Returns the blog entries associated with a particular label. This method is primarily for use by the website. /// /// ID of the blog /// Friendly title of the label /// A blog object public List GetBlogEntriesByLabel(Int32 blogId, String label, MinimaLINQDataContext db) { var results = (from be in db.BlogEntries join lbe in db.LabelBlogEntries on be.BlogEntryId equals lbe.BlogEntryId join l in db.Labels on lbe.LabelId equals l.LabelId where be.BlogId == blogId && l.LabelFriendlyTitle.ToLower() == label.ToLower() && be.BlogEntryStatusId == 1 orderby be.BlogEntryPostDateTime descending select be); return (List)results.ToList(); } /// /// Returns the blog entries from a particular month, wrapped in a blog object. This method is primarily for use by the website. /// /// ID of the blog /// Year the blog entries were posted /// Month the blog entries were posted /// public List GetBlogEntriesByMonth(Int32 blogId, Int32 year, Int32 month, MinimaLINQDataContext db) { Int32 daysInMonth = DateTime.DaysInMonth(year, month); DateTime start = new DateTime(year, month, 1); DateTime end = new DateTime(year, month, daysInMonth); var collection = (from be in db.BlogEntries where be.BlogId == blogId && be.BlogEntryPostDateTime >= start && be.BlogEntryPostDateTime <= end && be.BlogEntryStatusId == 1 orderby be.BlogEntryPostDateTime descending select be).ToList(); return collection; } /// /// Returns information regarding archived entries. /// /// ID of the blog /// DataTable with a summary of archived information public List GetArchivedEntries(Int32 blogId, MinimaLINQDataContext db) { return db.GetArchivedEntryList(blogId).ToList(); } #endregion #region Author /// /// Creates an author /// /// E-mail address of the author /// Name of the author /// ID of the created author. The ID is for internal use, use the e-mail address as an identifier public Int32 CreateAuthor(String authorEmail, String authorName) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { var collection = from p in db.Authors where p.AuthorEmail == authorEmail select p; if (collection.Count() > 0) { return collection.First().AuthorId; } else { Author author = new Author(); author.AuthorName = authorName; author.AuthorEmail = authorEmail; author.AuthorCreateDate = DateTime.Now; db.Authors.InsertOnSubmit(author); db.SubmitChanges(); return author.AuthorId; } } } /// /// Updates an author /// /// E-mail address of the author, this is the identifier /// Name of the author public void UpdateAuthor(String authorEmail, String authorName) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { Author author = null; try { author = db.Authors.Single(p => p.AuthorEmail == authorEmail); } catch (InvalidOperationException ex) { if (ex.Message == "Sequence contains no elements") { throw new ArgumentOutOfRangeException("Invalid author e-mail address.", ex); } } author.AuthorName = authorName; author.AuthorEmail = authorEmail; db.SubmitChanges(); } } /// /// Connects a author with a blog entry /// /// E-mail address of the author /// ID of the blog entry public void ApplyAuthor(String authorEmail, Int32 blogEntryId) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { var authors = from p in db.Authors where p.AuthorEmail == authorEmail select p; BlogEntry blogEntry = null; try { blogEntry = db.BlogEntries.Single(p => p.BlogEntryId == blogEntryId); } catch (InvalidOperationException ex) { if (ex.Message == "Sequence contains no elements") { throw new ArgumentOutOfRangeException("Invalid blog entry ID.", ex); } } if (authors.Count() > 0) { var beac = from p in db.BlogEntryAuthors where p.AuthorId == authors.First().AuthorId && p.BlogEntryId == blogEntryId select p; if (beac.Count() < 1) { BlogEntryAuthor bea = new BlogEntryAuthor(); bea.AuthorId = authors.First().AuthorId; bea.BlogEntryId = blogEntryId; db.BlogEntryAuthors.InsertOnSubmit(bea); db.SubmitChanges(); } } else { throw new ArgumentOutOfRangeException("That author does not exist."); } } } /// /// Disassociates an author from a blog entry, this does NOT delete the author /// /// E-mail address of the author /// ID of the blog entry public void RemoveAuthor(String authorEmail, Int32 blogEntryId) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { var authors = from p in db.Authors where p.AuthorEmail == authorEmail select p; BlogEntry blogEntry = null; try { blogEntry = db.BlogEntries.Single(p => p.BlogEntryId == blogEntryId); } catch (InvalidOperationException ex) { if (ex.Message == "Sequence contains no elements") { throw new ArgumentOutOfRangeException("Invalid blog entry ID.", ex); } } if (authors.Count() > 0) { BlogEntryAuthor bea = null; try { bea = db.BlogEntryAuthors.Single(p => p.BlogEntryId == blogEntryId && p.AuthorId == authors.First().AuthorId); } catch (InvalidOperationException ex) { if (ex.Message == "Sequence contains no elements") { throw new ArgumentOutOfRangeException("That author is not assigned to that blog entry.", ex); } } db.BlogEntryAuthors.DeleteOnSubmit(bea); db.SubmitChanges(); } else { throw new ArgumentOutOfRangeException("That author does not exist."); } } } /// /// Gets an author object by author e-mail address /// /// E-mail address of the author /// Author object public Author GetAuthorByEmailAddress(String authorEmail, MinimaLINQDataContext db) { Author author = null; try { author = db.Authors.Single(p => p.AuthorEmail == authorEmail); } catch (InvalidOperationException ex) { if (ex.Message == "Sequence contains no elements") { return null; } } return author; } #endregion #region Label /// /// Creates a label. It does not create labels that already exist in a particular blog. /// /// ID of the blog /// Title of the label /// ID of the created label public Int32 CreateLabel(Int32 blogId, String title) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { var labels = from p in db.Labels where p.BlogId == blogId && p.LabelTitle == title select p; if (labels.Count() > 0) { return labels.First().LabelId; } labels = from p in db.Labels where p.BlogId == blogId && p.LabelFriendlyTitle == CreateFriendlyLabelTitle(title) select p; if (labels.Count() > 0) { throw new ArgumentException("The friendly name of that label is already taken, it is recommended that you completely change the label title"); } Label label = new Label(); label.BlogId = blogId; label.LabelTitle = title; label.LabelFriendlyTitle = CreateFriendlyLabelTitle(title); db.Labels.InsertOnSubmit(label); db.SubmitChanges(); return label.LabelId; } } /// /// Updates a label /// /// ID of the label to update /// New title of the label public void UpdateLabel(Int32 labelId, String title) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { Label label = null; try { label = db.Labels.Single(p => p.LabelId == labelId); } catch (InvalidOperationException ex) { if (ex.Message == "Sequence contains no elements") { throw new ArgumentOutOfRangeException("Invalid label.", ex); } } if (label.LabelTitle == title) { return; } Label label2 = null; try { label2 = db.Labels.Single(p => p.BlogId == label.BlogId && p.LabelFriendlyTitle == CreateFriendlyLabelTitle(title)); } catch (InvalidOperationException ex) { if (ex.Message == "Sequence contains no elements") { label.LabelTitle = title; label.LabelFriendlyTitle = CreateFriendlyLabelTitle(title); db.SubmitChanges(); return; } } throw new ArgumentOutOfRangeException("The friendly name of that label is already taken, it is recommended that you completely change the label title"); } } /// /// Associates a label with a blog entry /// /// ID of the label /// ID of the blog entry public void ApplyLabel(Int32 labelId, Int32 blogEntryId) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { BlogEntry blogEntry = null; try { blogEntry = db.BlogEntries.Single(p => p.BlogEntryId == blogEntryId); } catch (InvalidOperationException ex) { if (ex.Message == "Sequence contains no elements") { throw new ArgumentOutOfRangeException("Invalid blog entry ID.", ex); } } var labels = from p in db.Labels where p.BlogId == blogEntry.BlogId && p.LabelId == labelId select p; if (labels.Count() < 1) { throw new ArgumentException("The given label ID and blog entry ID are not in the same blog."); } var lbec = from p in db.LabelBlogEntries where p.BlogEntryId == blogEntryId && p.LabelId == labelId select p; if (lbec.Count() < 1) { LabelBlogEntry lbe = new LabelBlogEntry(); lbe.BlogEntryId = blogEntryId; lbe.LabelId = labelId; db.LabelBlogEntries.InsertOnSubmit(lbe); db.SubmitChanges(); } } } /// /// Disassociates a label from a blog entry, it does NOT delete the label /// /// ID of the label /// ID of the blog entry public void RemoveLabel(Int32 labelId, Int32 blogEntryId) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { LabelBlogEntry lbe = null; try { lbe = db.LabelBlogEntries.Single(p => p.LabelId == labelId && p.BlogEntryId == blogEntryId); } catch (InvalidOperationException ex) { if (ex.Message == "Sequence contains no elements") { throw new ArgumentOutOfRangeException("That blog entry is not assigned that label.", ex); } } var lb = from p in db.LabelBlogEntries where p.LabelId == labelId && p.BlogEntryId == blogEntryId select p; if (lb.Count() > 0) { db.LabelBlogEntries.DeleteAllOnSubmit(lb); db.SubmitChanges(); } } } /// /// Deletes a label /// /// ID of the label /// ID of the blog entry public void DeleteLabel(Int32 labelId) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { var lb = from p in db.LabelBlogEntries where p.LabelId == labelId select p; foreach (LabelBlogEntry lbe in lb) { db.LabelBlogEntries.DeleteOnSubmit(lbe); db.SubmitChanges(); } var l = db.Labels.Single(p => p.LabelId == labelId); db.Labels.DeleteOnSubmit(l); db.SubmitChanges(); } } public Int32 GetBlogEntryLabelCount(Int32 blogEntryId) { using (MinimaLINQDataContext db = new MinimaLINQDataContext(MinimaConfiguration.DatabaseConfiguration)) { return GetBlogEntryLabels(blogEntryId, db).Count