Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a LINQ Where query to get only some of the ConfigurationManager.ConnectionStrings

My goal is to use a LINQ Where query on the ConfigurationManager.ConnectionStrings collection in a console application (assume a fresh .NET 4.5 console application with a System.Configuration reference added, and a correspodning using statement).

I started with this, which does not work:

var relevantSettings =
        ConfigurationManager.ConnectionStrings.Where(s => s.Name.StartsWith("Xyz"));

It tells me that:

The type arguments for method 'IEnumerable<TSource> System.Linq.Enumerable.Where<TSource(this IEnumerable<TSource>, Func<TSource,bool>)' cannot be inferred from the usage. Try specifying the arguments explicitly.

This caught me off guard, so I tried this to check my sanity, but this does not work either:

foreach (var settingsin ConfigurationManager.ConnectionStrings)
{
    if (settings.Name.StartsWith("Xyz")) Console.WriteLine("Found one!");
}

It complains not about the foreach statement, but about the .Name bit, with the error:

Could not resolve symbol 'Name'

I understand that there's probably something preventing the compiler from inferring the var's type, to double check I tried this which does work:

foreach (ConnectionStringSettings settings in ConfigurationManager.ConnectionStrings)
{
    if (connectionString.Name.StartsWith("Xyz")) Console.WriteLine("Found one!");
}

However, that doesn't help me very much, except for solving my immediate problem. I want to understand what is going on here.

All I wanted to do is use a simple LINQ Where statement to get a subset of the connection strings in my app.config. Why is the compiler preventing me from doing this?

like image 389
Jeroen Avatar asked Oct 17 '14 07:10

Jeroen


People also ask

Where is LINQ extension method used to filter the collection?

LINQ Where is a LINQ extension method which is used to filter the collection of elements based on the given condition? The condition can be precise as Func delegate type or in the lambda expression. This will be applicable in method syntax as well as in query syntax. In a single query, we can do multiple where extension methods.

What is the difference between LINQ where and method syntax?

It applies in both method and query syntax whereas method syntax requires the lambda expression and query syntax requires only the expression. The LINQ Where is used to limit the number of records from select, update, delete statements. Given below are few examples of LINQ where code the list of elements in the collection.

How where works in LINQ?

How Where Works in LINQ? The main purpose of LINQ where is used to filter elements based on the conditions. It comes under the filtering operator category. It applies in both method and query syntax whereas method syntax requires the lambda expression and query syntax requires only the expression.

How to use LINQ where clause filtering in method syntax?

The where clause is only used to extract records from select, delete, update and so on. Following is the syntax of using LINQ where clause filtering operator in method syntax to get data from collection list based on conditions. IEnumerable<string> result = countries.Where (x => x.StartsWith ("A"));


1 Answers

TL;DR Version

You need to do a .Cast<ConnectionStringSettings>() to make this work.

Details

Well, if you dig even a little deeper, you can get the compiler to tell you even more:

Func<ConnectionStringSettings, bool> StartsWithXyz = c => c.Name.StartsWith("Xyz");
var relevantSettings = ConfigurationManager.ConnectionStrings.Where(StartsWithXyz);

This is tells you:

Cannot convert instance argument type 'System.Configuration.ConnectionStringSettingsCollection' to 'System.Collections.Generic.IEnumerable<System.Configuration.ConnectionStringSettings>'

Driving up the inheritance tree of the ConnectionStringSettings property you can finally see the culprit, which makes a lot of sense: that property is of the non generic IEnumerable type.

This in fact makes the question a rather elaborate duplicate of this question, as the solution lies in casting the non-generic property to a generic list, so that LINQ and the compiler may do their magic. For this particular scenario, the following does work:

var relevantSettings = ConfigurationManager.ConnectionStrings
                                           .Cast<ConnectionStringSettings>()
                                           .Where(c => c.Name.StartsWith("Xyz"));

Enjoy!

like image 119
Jeroen Avatar answered Oct 07 '22 07:10

Jeroen