Raj Kaimal

LinqDataSource exceptions

Prerequisite: LinqDataSource & SqlDataSource Master/Details

When working with the LinqDataSource, you may get the exceptions listed below.

1. Operator '==' incompatible with operand types 'Int32' and 'Object'

The exception occurs because anytime a ControlParameter in the WhereParameters collection (IDictionary<string, object>) is null, it gets treated as type Object causing the LINQ dynamic expression parser comparison to fail. Consider the code snippet below:

    <asp:LinqDataSource ID="LinqDataSource2" runat="server" ContextTypeName="DataClassesDataContext"
        Select="new (OrderID, ProductID, UnitPrice, Quantity, Discount, Order)" TableName="Order_Details"
        Where="OrderID == @OrderID">
        <WhereParameters>
            <asp:ControlParameter ControlID="GridView1" Name="OrderID" PropertyName="SelectedValue"
                Type="Int32" />
        </WhereParameters>
    </asp:LinqDataSource>

This is part of the classic Master/Details scenario where the LinqDataSource fetches the Order Details based on the OrderID selected in the GridView1.

When the page loads the first time, the OrderID ControlParameter is equal to GridView1.SelectedValue.  GridView1.SelectedValue is null since no record has been selected in the GridView1 yet.  Unfortunately,  the LinqDataSource still attempts to fetch the data. The Linq expression parser treats the null  parameter as type Object and the comparison fails because it was expecting type Int32.

What we need here is a way to prevent the Select from occurring when any parameter is null.  The LinqDataSource, unlike the SqlDataSource, for some reason, does not have a CancelSelectOnNullParameter property. This property when set to true, will cancel the select when any parameter in the SelectParameters collection is null.

We can implement this by handling the Selecting event of the LinqDataSource and call the Cancel method when any WhereParameter is null like so:

    protected void LinqDataSource2_Selecting(object sender, LinqDataSourceSelectEventArgs e)
    {
        foreach (KeyValuePair<string, object> kvp in e.WhereParameters)
        {
            if (kvp.Value == null)
            {
                e.Cancel = true;
                return;
            }
        }
    }

 

2. Operator '==' incompatible with operand types 'Guid' and 'String'

This exception occurs in cases where a parameter in the WhereParameters collection is of type Guid.

    <asp:LinqDataSource ID="LinqDataSource2" runat="server" 
        ContextTypeName="DataClassesDataContext" 
        Select="new (DummyID, FirstName, LastName)" TableName="DummyTables" 
        Where="DummyID == @DummyID" onselecting="LinqDataSource2_Selecting">
        <WhereParameters>
            <asp:ControlParameter ControlID="GridView1" Name="DummyID" 
                PropertyName="SelectedValue" Type="Object" />
        </WhereParameters>
    </asp:LinqDataSource>

In the snippet above, you can see that the GridView1.SelectedValue is defined as a WhereParameter for the LinqDataSource. DummyID is the primary key of the data in GridView1 and is of type Guid. In the ControlParameter, its Type is set to Object because Guid is not available in the TypeCode enum. Unfortunately, this results in the linq expression parser treating the value as type String causing the comparison to fail.

According to the Dynamic Expression API, a flavor of which is used by the LinqDataSource internally, we can perform explicit conversions using the syntax type(expr) where type is a type name optionally followed by ? and expr is an expression. The expression language defines the following primitive types:

Object Boolean Char String SByte Byte
Int16 UInt16 Int32 UInt32 Int64 UInt64
Decimal Single Double DateTime TimeSpan Guid

The primitive types correspond to the similarly named types in the System namespace of the .NET Framework Base Class Library. You can also use the nullable form of a value type by writing a ? after the type name (ex: Where="Foo = Int32?(@Foo)").

Therefore, we can rewrite our where clause like so which gets rid of the exception.

    <asp:LinqDataSource ID="LinqDataSource2" runat="server" 
        ContextTypeName="DataClassesDataContext" 
        Select="new (DummyID, FirstName, LastName)" TableName="DummyTables" 
        Where="DummyID == Guid(@DummyID)" onselecting="LinqDataSource2_Selecting">
        <WhereParameters>
            <asp:ControlParameter ControlID="GridView1" Name="DummyID" 
                PropertyName="SelectedValue" Type="Object" />
        </WhereParameters>
    </asp:LinqDataSource>

IMO, both these exceptions and a couple of others could probably be avoided if the LinqDataSource had a CancelSelectOnNullParameter and if the  TypeCode enum had included the primitive types listed above and nullable value types.

Comments are always welcome!

Posted by rajbk | 2 comment(s)
Filed under: , ,

The .NET Framework 3.5 Commonly Used Types and Namespaces poster

Paul Andrew has posted a link to the .NET framework 3.5 commonly Used Types and Namespaces poster - cool stuff!

Download it here

 

Daniel Moth also has a good older post on the .NET 3.5 bits
 

Posted by rajbk | with no comments
Filed under: ,

Classic Menu UI in Office 2007

So my 65 year old neighbor called me yesterday because he was frustrated with the Office 2007 Ribbon on his brand new machine...

After googling around, I found a great add-in for Office 2007 by Patrick Schmid called the RibbonCustomizer. It comes in two versions - the free Starter Edition and the Professional edition. Both versions, in addition to customizing the Ribbon, give you a "Classic UI" tab which emulate the Office 2003 menus and toolbars.

As you can see from the screen captures, it does not replace the Ribbon UI but adds onto it, which, IMHO, lets the user work with a familiar UI and allows them to slowly transition into the new UI.

For a core product like the Office Suite, Microsoft should have provided this ability by default.

My neighbor couldn't be happier...

Posted by rajbk | 3 comment(s)
Filed under: , ,

.NET Framework Libraries Source Code - License - MS-RL

When I first read Scott's post, I missed the Microsoft Reference License (Ms-RL) which the .net Framework libraries is released under.

The key thing to remember is this:

"Reference use" means use of the software within your company as a reference, in read only form, for the sole purposes of debugging your products, maintaining your products, or enhancing the interoperability of your products with the software, and specifically excludes the right to distribute the software outside of your company.

Posted by rajbk | 1 comment(s)
Filed under: ,

.NET Framework Libraries Source Code

Scott just announced that his team will be  releasing the souce code to the .NET base class libraries, ASP.net, Windows Forms and WPF!

The big advantage to this is that when you are stepping through the code, you no longer see the horrible "[External Code]' in your call stack. You are taken right to the source code! This really really helps in understanding how the internals of the classes work.

Wonder what I am going to do with reflector...hmm...

Read more at Scotts' blog

PS: The source code is being released under Ms-RL which means that I can view but I'm not allowed to copy and paste the source code.

Posted by rajbk | with no comments
Filed under: ,

SQL 2005 - Maximum number of characters displayed in each column

This setting in Microsoft SQL server management studio, which has a default setting of 256 characters, caused me to waste almost half an hour yesterday. I was looking in the wrong places trying to troubleshoot my stored procedure and wondering why my data was being truncated. There is no indication in management studio that the text was being truncated either.

To increase the maximum value, open SQL Server management studio and go to

 Tools » Options » Query Results » Results to Text » Maximum number of characters displayed in each column

Note also that there is a "Maximum Characters Retrieved" section under "Results to Grid" section too.

Posted by rajbk | 1 comment(s)
Filed under: ,

Building an RSS feed using LINQ to XML and LINQ to SQL

Version : VS 2008 Beta 2

In this post, I am going to show you how to build a RSS feed of the employees in the NorthWind database using LINQ. Before you proceed, you may want to read Scott's introduction of LINQ to XML over here if you haven't done so already.

To start, lets look at how we can programmatically create the XML document below:

 1: <?xml version="1.0" encoding="utf-8" ?>
 2: <Employees>
 3: <Employee>
 4: <Name>Tom</Name>
 5: <ID>1</ID>
 6: </Employee>
 7: <Employee>
 8: <Name>Jane</Name>
 9: <ID>2</ID>
 10: </Employee>
 11: </Employees>

Without LINQ, we could use the XmlDocument class to create an in-memory tree representation of the document above and write it to the HttpResponse stream like so:

 1: XmlDocument doc = new XmlDocument();
 2:  
 3: XmlDeclaration xmldec = doc.CreateXmlDeclaration("1.0", "utf-8", null);
 4: XmlElement root = doc.DocumentElement;
 5: doc.InsertBefore(xmldec, root);
 6:  
 7: XmlElement employees = doc.CreateElement("Employees");
 8: doc.AppendChild(employees);
 9:  
 10: XmlElement employee1 = doc.CreateElement("Employee");
 11: employees.AppendChild(employee1);
 12:  
 13: XmlElement empID1 = doc.CreateElement("ID");
 14: empID1.InnerText = "1";
 15: employee1.AppendChild(empID1);
 16:  
 17: XmlElement empName1 = doc.CreateElement("Name");
 18: empName1.InnerText = "Tom";
 19: employee1.AppendChild(empName1);
 20:  
 21: XmlElement employee2 = doc.CreateElement("Employee");
 22: employees.AppendChild(employee2);
 23:  
 24: XmlElement empID2 = doc.CreateElement("ID");
 25: empID1.InnerText = "2";
 26: employee1.AppendChild(empID2);
 27:  
 28: XmlElement empName2 = doc.CreateElement("Name");
 29: empName2.InnerText = "Jane";
 30: employee2.AppendChild(empName2);
 31:  
 32: Response.Clear();
 33: doc.Save(Response.Output);
 34: Response.End();

LINQ provides a easier and cleaner way to create XML documents known as functional construction. Using functional construction, you can create all or parts of your in-memory XML tree in a single statement. This is made possible by a constructor in the XElement and XDocument classes that take in a params object (FYI, XElement and XDocument both inherit from type XContainer).

 1: public XElement(XName name, params object[] content);
 2: public XDocument(XDeclaration declaration, params object[] content);

The constructor calls an internal method called AddContentSkipNotify to validate the type of object passed into the params object. From the documentation, parameters can be any of the following:

  • A string, which is added as text content. This is the recommended pattern to add a string as the value of an element; the LINQ to XML implementation will create the internal XText node.
  • An XText, which can have either a string or CData value, added as child content.  This is mainly useful for CData values; using a string is simpler for ordinary string values.
  • An XElement, which is added as a child element
  • An XAttribute, which is added as an attribute
  • An XProcessingInstruction or XComment, which is added as child content
  • An IEnumerable, which is enumerated, and these rules are applied recursively
  • Anything else, ToString() is called and the result is added as text content
  • null, which is ignored

Using functional construction, we can create our in memory XML tree and write it to the response stream like so:

   1: XDocument doc = new XDocument(
   2:     new XDeclaration("2.0", "utf-8", "yes"),
   3:         new XElement("Employees",
   4:             new XElement("Employee",
   5:                 new XElement("Name", "Tom"),
   6:                 new XElement("ID", "1")),
   7:             new XElement("Employee",
   8:                 new XElement("Name", "Tom"),
   9:                 new XElement("ID", "1"))));
  10:  
  11: Response.Clear();
  12: doc.Save(Response.Output);
  13: Response.End();

This code is easier to write compared to the XmlDocument method. It is also easy see the underlying structure of the XML document by looking at the code.

From the documentation above, we know that if we pass in IEnumerable<T> to the XElement constructor, it will get enumerated and the rules will be applied recursively to each element in the collection.

With this knowledge, we could rewrite the code above with a LINQ TO XML query that returns an IEnumerable<XElement> from a collection of anonymous types like so:

   1:         var employees = new[] {
   2:             new {Name = "Tom", ID = 1},
   3:             new {Name = "Jane", ID = 2}
   4:         };
   5:  
   6:         XDocument doc = new XDocument(
   7:             new XDeclaration("2.0", "utf-8", "yes"),
   8:                 new XElement("Employees",
   9:                         //LINQ query that returns IEnumerable<XElement>
  10:                         from e in employees
  11:                         select new XElement("Employee",
  12:                             new XElement("Name", e.Name),
  13:                             new XElement("ID", e.ID)
  14:                         )
  15:                 )
  16:         );
  17:  
  18:         Response.Clear();
  19:         doc.Save(Response.Output);
  20:         Response.End();

Note that  "var employees" above is a collection of anonymous types. The output of this code will produce the same XML document like the previous two code samples did.

Instead of the hard coded employee collection, we could use a LINQ to SQL query that returns an IEnumerable<XElement> of employee names and their description from the database. That is the basic idea behind this post - Using LINQ to SQL to query the database, construct an in-memory XML tree using LINQ to XML by following the RSS specification and finally writing it out to the HttpResponse stream.

The XDocument we are going to construct will follow the RSS 2.0 specification (the minimum required) below:

   1: <?xml version="1.0" encoding="utf-8" standalone="yes"?>
   2: <rss version="2.0">
   3:   <channel>
   4:     <title></title>
   5:     <link></link>
   6:     <description></description>
   7:     <item>
   8:       <title></title>
   9:       <description></description>
  10:       <link></link>
  11:     </item>
  12:     ...
  13:     ...
  14:     ...
  15:     <item>
  16:       <title></title>
  17:       <description></description>
  18:       <link></link>
  19:     </item>
  20:   </channel>
  21: </rss>

Assuming we have created our Nortwind LINQ to SQL object model, we can write the final code in 25 lines(!) like this:

   1:     protected void Page_Load(object sender, EventArgs e)
   2:     {
   3:         NorthwindDataContext context = new NorthwindDataContext();
   4:         Response.Clear();
   5:         Response.ContentType = "text/xml";
   6:  
   7:         XDocument document = new XDocument(
   8:             new XDeclaration("1.0", "utf-8", null),
   9:             new XElement("rss",
  10:                 new XElement("channel",
  11:                     new XElement("title", "Employees of Northwind Traders Inc."),
  12:                     new XElement("link", "http://www.northwindtraders.com"),
  13:                     new XElement("description", "Employees of Northwind Traders Inc. ordered by last name."),
  14:                             from emp in context.Employees
  15:                             orderby emp.LastName
  16:                             select new XElement("item",
  17:                                 new XElement("title", emp.LastName + ", " + emp.FirstName),
  18:                                 new XElement("description", emp.Notes),
  19:                                 new XElement("link", "http://www.northwindtraders.com/employees.aspx?id=" + emp.EmployeeID)
  20:                             )
  21:                     ),
  22:                 new XAttribute("version", "2.0")));
  23:         document.Save(Response.Output);
  24:         Response.End();
  25:     }

Note that the LINQ to SQL query fetches the employee name (LastName + FirstName columns) and the Notes column and creates an XElement called "title" and "description" respectively. We also create a dummy "link" node that points to www.northwindtraders.com since it is part of the requirement of the RSS specs. Once we have our XDocument created, we clear the Response stream, set the content type to text/xml and then "Save" the document to the HttpResponse stream.

This is not the optimal solution though since the DB is queried everytime the page is requested. We obviously have to cache the results on the server for a set amount of time. This can easily be done by calling the .ToList() extension method on the XDocument and storing the results in Cache. I show an example of how to cache the results of a LINQ query here

Note also that you should always HtmlEncode data before rendering it on the browser (which is not shown in the sample code). 

I hope this post has shown you how super easy it is to create XML documents from content in the database using LINQ. To learn more, download VS 2008 Beta 2 and check out the LINQ samples.

Posted by rajbk | with no comments
Filed under: , , ,

Using the ListView in tiled mode (Part 2) - CSS layout

Using the ListView in tiled mode (Part 1)

Updated 12/01/2007 for VS 2008 RTM

In this second part of my post on customizing the ListView UI, we are going to look at how to consume a Flickr RSS feed and display the feed items in a ListView (tiled mode). The layout will be done using only CSS (no tables). We will also make use of the new DataPager control to display a pager at the top and bottom of the page. Each page will contain 9 photos with 3 photos per row.

flickrtolistview

I am using an RSS feed of some nice photos from Wagner Campelo (I don't know the guy but found him while looking for photos on flickr for this post).

To get started, we add a ListView control and LinqDataSource control to the page and set the DataSource property of the ListView control to the LinqDataSource. We then implement an event handler to handle the Selecting event of the Linqdatasource. We do this to write a custom LINQ expression in the code behind which will fetch the RSS feed and extract the fields we are interested in. This data is assigned to the Result property of the LinqDataSourceSelectEventArgs object. The code behind is shown below:

 1: protected void LinqDataSource1_Selecting(object sender, LinqDataSourceSelectEventArgs e)
 2: {
 3: XDocument rssFeed = XDocument.Load("http://api.flickr.com/services/feeds/photos_public.gne?id=86361978@N00&tags=colors&lang=en-us&format=rss_200");
 4: e.Result = from item in rssFeed.Descendants("item")
 5: select new
 6: {
 7: Title = item.Element("title").Value,
 8: Description = item.Element("description").Value
 9: };
 10: }

Note that we have written an LINQ expression that enumerates all root "item" nodes and extracts the "title" and "description" node values. To learn more about this, read Scott's tutorial on LINQ to XML

The code above is going to parse the RSS feed every time a post back occurs making it non-optimal. What we should do instead is to cache the result of the RSS feed for a set amount of time. The code can be refactored to support caching like so:

 1: public partial class _Default : System.Web.UI.Page
 2: {
 3: private const string FeedUrl = "http://api.flickr.com/services/feeds/photos_public.gne?id=86361978@N00&tags=colors&lang=en-us&format=rss_200";
 4: private const string PhotoCache = "photoCache";
 5:  
 6: protected void LinqDataSource1_Selecting(object sender, LinqDataSourceSelectEventArgs e)
 7: {
 8: e.Result = GetFlickrFeed();
 9: }
 10:  
 11: private object GetFlickrFeed()
 12: {
 13: Object o = Cache[PhotoCache];
 14: if (o == null)
 15: {
 16: XDocument rssFeed = XDocument.Load(FeedUrl);
 17: var photos = from item in rssFeed.Descendants("item")
 18: select new
 19: {
 20: Title = item.Element("title").Value,
 21: Description = item.Element("description").Value
 22: };
 23: o = photos.ToList();
 24: UpdateRefreshDate();
 25: //We are caching for 5 seconds only for demonstration purposes
 26: Cache.Insert(PhotoCache, o, null, DateTime.Now.AddSeconds(5), Cache.NoSlidingExpiration);
 27: }
 28: return o;
 29: }
 30:  
 31: /// <summary>
 32: /// Update the label control in the list view with 
 33: /// the last refreshed time.
 34: /// </summary>
 35: private void UpdateRefreshDate()
 36: {
 37: Label lblLastRefresh = (Label)ListView1.FindControl("lblLastRefresh");
 38: lblLastRefres