Adding RSS posts to ThinqLinq using System.ServiceModel.Syndication.SyndicationFeed by ThinqLinq

Adding RSS posts to ThinqLinq using System.ServiceModel.Syndication.SyndicationFeed

When I originally started the ThinqLinq project I began by loading the RSS feed from my DevAuthority blog, and iterating over the results adding them to the PostItems table in the data context. With LINQ this is relatively easy. Loading the XML from the feed is done with a single line:

Dim Feed As System.Xml.Linq.XDocument = _
    XDocument.Load("http://www.ThinqLinq.com/rss.aspx")

The xml document consists some basic informational elements which are not terribly important in this instance as we are only pulling from a single blog. Following the initial elements, the document contains a series of "item" elements that contain the actual post information. We can easily query the document and return an IEnumerable(Of XElement) object that we can iterate over and create new post items. Below is an excerpt from my original implementation.

For Each post As XElement In Feed...<item>
   
Dim DataPost As New LinqBlog.BO.PostItem
    DataPost.Author =
"Jim Wooley"
   
DataPost.Description = post.Element("description").Value
    DataPost.PublicationDate = CDate(post.Element("pubDate").Value)
    DataPost.Title = post.Element("title").Value
    dc.PostItems.Add(DataPost)
Next

Once the records are added to the table, we can commit them to the database with a single call to SubmitChanges as follows:

dc.SubmitChanges()

Ok, so that is easy enough. There are a couple of things to mention before we continue on. The .Add method will be changed to .InsertOnSubmit when LINQ and the .NET 3.5 Framework is released. This will be a breaking change for anyone who is currently working with the beta builds.

Another item of note: this implementation does not bother importing the various sub-collections, including attachments, comments, categories, etc. We will address some of those in a future update.

In looking back at the code and being more familiar with LINQ, it is about time to update this code taking advantage of some of LINQ's more interesting features. First VB 9 allows us to eliminate some of the functional construction syntax. Instead of weakly accessing the post.Element("description").Value, we can refer to post.<description>.Value. If we import the namespace, we will even get intellisense on the xml document.

In addition, rather than iterating over the item elements explicitly, we can use a  LINQ query to create an IEnumerable(Of PostItem) list using the object initializers in the select projection. We then fill the entire collection using the table's InsertAllOnSubmit. With this change, we eliminate the entire for each loop. Below is the revised code:

Dim Feed As System.Xml.Linq.XDocument = XDocument.Load("http://ThinqLinq.com/rss.aspx")

Dim dc As New LinqBlogDataContext()

dc.PostItems.InsertAllOnSubmit(From post In Feed...<item> _
    Select New PostItem With { _
    .Author = "Jim Wooley", _
    .Description = post.<description>.Value, _
    .PublicationDate = CDate(post.<pubDate>.Value), _
    .Title = post.<title>.Value})

dc.SubmitChanges()

That's it. We've read the feed from the site, filled the object collection and saved the resulting objects to the database. Clean and simple.

But hold on... The title of this post refers to the System.ServiceModel.Syndication.SundicationFeed object. This is a new object as part of the WCF enhancements in the .NET 3.5 Framework. To use it, add a reference to the System.ServiceModel.Web library. This object lets you create and consume feeds in both RSS and ATOM formats and use a single object model against both options. It also gives easy access to a number of child object structures, including Authors, Categories, Contributors, and Links. Additionally it strongly types the results so that we don't need to explicitly cast the values ourselves (for example with the PublicationDate). Here is the complete code to load the feed using the SyndicationFeed.Load method, fill the PostItem collection and submit them to the database.

Dim feed As SyndicationFeed = SyndicationFeed.Load( _
   
New System.Uri("http://ThinqLinq.com/rss.aspx"))

Dim dc As New LinqBlogDataContext()

dc.PostItems.InsertAllOnSubmit(From p In feed.Items _
    Select New PostItem With _
    {.Author = If(p.Authors.Count > 0, p.Authors(0).Name, "Jim Wooley"), _
    .Description = p.Summary.Text, _
    .PublicationDate = p.PublishDate, _
    .Title = p.Title.Text})

dc.SubmitChanges()

The code is substantially the same as the revised version using the XML Literals above. The advantage of using the Syndication services implementation is that it abstracts the feed structure (RSS/ATOM), giving direct and strongly typed access to the contents.

Now that we've set this up, maybe I can work on using the SyndicationFeed to generate the feeds in ThinqLinq and present that in a future post. Stay tuned.

Posted on - Comment
Categories: LINQ) - VB) -
comments powered by Disqus