LINQ Bug specific to VB Smart Device projects

You Can Take it With You

Syndication

News

  • Don't miss the next Windows Mobile Webcast... Unit Testing for Mobile Devices: http://msevents.microsoft.com/CUI/WebCastEventDetails.aspx?EventID=1032382824&EventCategory=4&culture=en-US&CountryCode=US.

I've been working increasingly with LINQ these days trying to get a handle on just what works well and what doesn't when using LINQ in device apps. In preparing for my LINQ webcast coming up on 27-February, I put together a couple of "Hello World" equivalent LINQ programs. As I tend to do, I write the programs in C# first and then write them in VB.

Using a typed DataSet to represent the SQL Server Compact 3.5 (SSC) Northwind database in my C# program, I have the following simple LINQ query and assign the result as the DataSource to a DataGrid.

var selectedRows = from order in _northwindDataSet.Orders
where order.Ship_Country == filterDialog.SelectedCountry
select order;

dataGrid1.DataSource = selectedRows.AsDataView();

Works just as expected … so I then create a VB Smart Device project, and do the same.

Dim selectedRows = From order In NorthwindDataSet.Orders _
Where order.Ship_Country = "UK" _
Select order

OrdersBindingSource.DataSource = selectedRows.AsDataView()

Much to my surprise, I receive a compiler error on the last line… AsDataView is not a member of IEnumerableList(of NorthwindDataSet.OrdersRow)

To make sure that I'm not making some error in the VB syntax, I create a desktop VB project containing the same code … works perfectly! No compiler errors and runs as expected.

With this being the case, I went back to look at the VB compiler error. The compiler is right, there is no AsDataView extension method that supports IEnumerable(of T) which is exactly the problem. The compiler should not be inferring the selectedRows data type to be IEnumerable(of T). The correct inferred type for a query that returns a collection containing a DataRow-derived type is EnumerableDataRow(of T) – bottom line … I've hit what appears to me to be a bug specific to the VB Smart Device projects.

Note: See the post LINQ Bug specific to VB Smart Device projects (Maybe Its Not A Bug) for a complete explanation of exactly what's happening and for an example of a better workaround.

Since the compiler is inferring the wrong type, I thought I'd try explicitly typing the variable that receives the query result.

Dim selectedRows As EnumerableRowCollection(Of NorthwindDataSet.OrdersRow) = From order In NorthwindDataSet.Orders _
Where order.Ship_Country = "UK" _
Select order

OrdersBindingSource.DataSource = selectedRows.AsDataView()

The good news is that the code does compile … the bad news is that it throws an InvalidCastException at runtime.

But we do have a workaround … The problem is tied to the VB Smart Device project's handling of converting the query syntax into the method-based syntax. If you write the statement directly in the method-based syntax, all works as expected.

Dim selectedRows = _
NorthwindDataSet.Orders.Where(Function(order) order.Ship_Country = "UK")

OrdersBindingSource.DataSource = selectedRows.AsDataView()

Not quite as pretty as the query-based syntax but does have the benefit of actually working. J

At least for now … when you're doing a LINQ query in a VB Smart Device project and wish to apply one of the EnumerableRowCollection(of T) member methods or extension methods to the result, you'll need to use the method-based syntax.

Note: I encountered this bug using Visual Studio 2008 and .NET Compact Framework 3.5 with no service packs. Presumably if you're reading this after the release of a relevant service pack, this bug (hopefully) no longer exists.


Posted Feb 04 2008, 03:51 PM by jim-wilson

Add a Comment

(required)  
(optional)
(required)  
Remember Me?