Dave Burke : Freelance .NET Web Developer specializing in Online Communities

CS OPML-to-Blogroll Add-on: Conversion

Keyvan Nayyeri released his OPML-to-Blogroll Converter Add-on for CS 2.0 a few days ago and I jumped on it.  I installed it on my CS 2.0 development server with little problem, as Keyvan's instructions were brief and clearly written.  I had to tweak the exception handling a bit to process my GreatNews Reader OPML file all the way through without spitting out a runtime, but it wasn't a problem.

But the thing I couldn't deal with was how long it took to convert my @120 feed OPML file to a CS Links list.  The converter cranked for well over a minute.  That wouldn't do, and I had to get to the bottom of what was going on.

Keyvan's converter does a lot of XML handling, using XSL Transform on the OPML file as well as on the temporarily created XML files for LinkCategories and Links from the OPML file.  First thing I did was rework the logic and use a straight XMLTextReader, grabbing elements and attributes as needed.  My GreatNews OPML file is two-tiered (as any resulting CS Link List would be), so I based XML handling on what tier the OUTLINE element was located; a category had a reader.depth of 2, a link reader.depth 3.

I compiled up the XML handling changes from Keyvan's approach, but conversion was STILL cranking for over a minute to do the job.  It wasn't XML handling sucking up the cycles, it was the native CS WeblogDataProvider CreateLinks() method being used for each and every OPML feed entry entered into CS.  CHOKE!  Not a criticism of Keyvan or of CS, the CS WeblogDataProvider was never designed to enter multiple links like this into the CS_Links table.

Using the CS DataProviders is a very clean "best practice" type of implementation leveraging the CS architectural model, but another approach was needed to make this app useable.

The DataProvider approach:

private void AddLinks(DataSet Sites, System.Collections.Specialized.StringDictionary CategoryDic)
{
    foreach (DataRow Row in Sites.Tables[0].Rows)
    {
        CommunityServer.Components.Link objLink = new Link();

        objLink.Title = Convert.ToString(Row["Name"]);
        objLink.Description = Convert.ToString(Row["Description"]);
        objLink.Url = Convert.ToString(Row["Url"]);
        objLink.IsEnabled = true;
        objLink.LinkCategoryID = Convert.ToInt32(CategoryDic[Convert.ToString(Row["Category"])]);

        Links.CreateLink(objLink);
}// foreach
}// AddLinks


My idea was to read through the OPML, enter a LinkCategory, then enter all of its links with a single batch statement.  So the core logic I decided to go with was:

private void EnterLinkItem(XmlTextReader _reader) 
{
    string _title = QuoteClean(_reader.GetAttribute("title"));
    string _desc = QuoteClean(_reader.GetAttribute("description"));
    string _url = _reader.GetAttribute("htmlUrl");
    int _settingsID = CSContext.Current.SettingsID;

    _linkSqlStatement += "insert into cs_links values (" + _linkCategoryID + ",'" + _title + "','" + _url + "'," +
    "1," + _linkSortValue + "," + _settingsID + ",null,'" + _desc + "','" + DateTime.Now + "');\n";
    _linkSortValue++;

}

private void ExecuteLinkSQLStatement()  // called when Link Category Changes
{
    SQLHelper.ExecuteNonQuery(_linkSqlStatement);
    _linkSqlStatement = string.Empty;
}


The complete conversion class is viewable here.  I did use the CS DataProvider for entering the Link Categories.  Hey, I LIKE the CS DataProvider model!  I could have squeezed out even better performance if I did something similar with Link Category entry, but my obsession with this conversion process paid off.  The original 60-90 seconds processing time was reduced to less than 5 seconds.

I'll have the source available when my OPML Blogroll is online.  I'm still deciding on how to display it.  One of the things I'll need to do is to add expanding panels for the OPML categories, so that will be part of the mod as well.  I'll keep you posted.

Thanks for allowing me to piggyback on your excellent work, Keyvan!


[tags: Community Server, OPML, Blogroll]

Comments (2) | Post RSS RSS comment feed

Posted on 4/3/2006 10:25:00 PM by Dave Burke
Categories: Community Server
Tags:

Related posts

Comments (2) -

4/5/2006 4:55:05 AM Permalink

Hey Dave;
Excuse me for my delay. I was off to university and had no time to be online Wink
And thank you very much for testing it.
Generally, you're right.
It's slow because I had to add them with a method and calling it many times. I implemented your approach before and putted them directly to database as a Smart Client here (classes are applicable easily to Web Projects):
http://nayyeri.net/archive/2006/01/30/445.aspx
(Unfortunately, I removed the file but if you're interested I'll send you this project.

This time, I tried to use CS APIs because it is better approach, I think.
I'll send more about my comments about ASP.NET 1.x and ASP.NET 2.0 and their differences. I faced with some obsolete methods when was working on this and if you are using .NET 2.0, they will reduce the speed Smile
Thank you again for testing and your great comments.

Keyvan Nayyeri |

4/5/2006 6:16:03 AM Permalink

Keyvan, You're right about those obsolete methods in .NET 2.0.  You're saying those were speed suckers, too, eh?  Like I said in the post, the CS DataProvider wasn't designed for batch input.  I used everything of yours except the core logic.  Again, I really like how you package up your add-ons.  Great readme.txt, too!  Thanks for your comments!

daveburke |


Powered by BlogEngine.NET 2.0.0.36
Theme by Dave Burke