LINQ Gotcha

Published Wed, May 7 2008 20:00 | William

After a long hiatus, I was trying to figure out something cool or at least interesting to blog about.  I was having trouble figuring out what I wanted to write, but then one after another, I got a ton of ideas.

One thing I wanted to do for my current project was finding out if a specific ConnectionString was present in the <ConnectionStrings> setting of a .config file. This is a big oversimplification but it's close enough to explain. So I wrote the following:

var myVar = from cs in ConfigurationManager.ConnectionStrings
            select cs;

 foreach (var Mine in myVar)
 {
       Console.WriteLine(myVar);
 }

I knew the second I tried to write a where clause that there was a problem b/c intellisense wasn't showing anything I expected. When I tried to display some of the properties in the foreach loop, nothing was visible. I knew something was wrong. So I tried to compile and got the following error:

Could not find an implementation of the query pattern for source type 'System.Configuration.ConnectionStringSettingsCollection'.  'Select' not found.  Consider explicitly specifying the type of the range variable 'cs'. 

Well, that was helpful b/c I knew at least the problem was with the  range variable .  I wasn't sure what type of collection the ConfigurationManager.ConnectionStrings  property was so I decided to look it up just to be sure. (I also just wanted to make sure it was in fact some type of collection or another. I couldn't imagine that it wouldn't have been, but just wanted to make sure for purely superstitious reasons) Ok, so it's a ConnectionStringsSettingsCollection , nothing surprising there. Digging deeper I saw that ConnectionStringsSettingsCollection inherits from ConfigurationElementCollection . At that point, it all became crystal clear for I saw the following in the class definition:

public abstract class ConfigurationElementCollection : ConfigurationElement, ICollection, 
    IEnumerable

Do you see the problem? There's an IEnumerable but no IEnumerable<T>   . You see, the collection implements the non-Generic IEnumerable but not the Generic IEnumerable. Hence, a explicit range variable is in order to make this work.  I know I know, that's exactly what the error message recommended, but I didn't understand why at first and wanted to dig deeper into it. So bascially, here's what was needed to make it work.  Simply use the Cast<T>   extension method on the collection and well, that's it.

ConnectionStringSettingsCollection cfg = ConfigurationManager.ConnectionStrings;

var myvar = from cs in cfg.Cast<ConnectionStringSettings>()
                  select cs;
foreach (var mine in myvar)
{
    Console.WriteLine(mine);
}

Of course, you could just cut out some of the bloat and address the collection directly

var myvar = from cs in ConfigurationManager.ConnectionStrings.Cast<ConnectionStringSettings>()
            select cs;

foreach (var mine in myvar)
{
  Console.WriteLine(mine);
}

Whenever Intellisense doesn't do what you're expecting it to, that's the first tipoff something is wrong in your query.  Although my days of 2 day work weeks have come to an end temporarily, I'll try to find some time to blog the rest of what I was working on - there's so much you can do with LINQ that I often overlook.  And this is the first time I've come across the explicit range variable issue but I'm guessing it'll come up again, particularly if you use LINQ regularly.

 

 

 

Comments

# Jason Haley said on May 8, 2008 9:13 AM:
# Jb Evain said on May 8, 2008 11:35 AM:

You can write:

from ConnectionStringSettings cs in cfg

select cs;

And csc will automatically call Cast<ConnectionStringSettings> on cfg.

# William said on May 9, 2008 1:36 PM:

Hi JB:

Indeed it will.  Semantically, both approaches involve an explicit cast b/c since it's the non-generic implementation of IEnumerable that's implemented, the behavior is differen than what you'd expect.

Search

This Blog

Tags

Community

Archives

News

My other sites

Cool Stuff

Book Stuff

Security

ORM

Data Access

Funny Stuff

Compact Framework Stuff

Web Casts

My KnowledgeBase Articles

My MVP Profile

Design Patterns

Performance

Debugging

Remoting

My Fellow Authors

My Books

LINQ

Misc

Speech

Syndication

Email Notifications