views:

4768

answers:

4

How do I properly convert two columns from SQL (2008) using Linq into a Dictionary (for caching)?

I currently loop through the IQueryable b/c I can't get the ToDictionary method to work. Any ideas? This works:

var query = from p in db.Table
            select p;

Dictionary<string, string> dic = new Dictionary<string, string>();

foreach (var p in query)
{
    dic.Add(sub.Key, sub.Value);
}

What I'd really like to do is something like this, which doesn't seem to work:

var dic = (from p in db.Table
             select new {p.Key, p.Value })
            .ToDictionary<string, string>(p => p.Key);

But I get this error: Cannot convert from 'System.Linq.IQueryable' to 'System.Collections.Generic.IEnumerable'

Answer (thanks!):

var dic = db
        .Table
        .Select(p => new { p.Key, p.Value })
        .AsEnumerable()
        .ToDictionary(k=> k.Key, v => v.Value);
+15  A: 
var dictionary = db
    .Table
    .Select(p => new { p.Key, p.Value })
    .AsEnumerable()
    .ToDictionary(kvp => kvp.Key, kvp => kvp.Value)
;
Justice
Sorry, I may have not been clear, I've tried thie before, but this creates a Dictionary<string, #Anonymous Type>, not Dictionary<string, string>
Codewerks
Try `kvp => kvp.Value as string`. The point of the answer was `.AsEnumerable()`.
Justice
Thanks, yeah I figured AsEnumerable was needed, but the ToDictionary call still doesn't work. Both columns are varchars in SQL, so they come back as strings, but I can't figure out how to get it to stuff into a Dic....
Codewerks
figued it out, thanks for your help!
Codewerks
+4  A: 

You are only defining the key, but you need to include the value also:

var dic = (from p in db.Table
             select new {p.Key, p.Value })
            .ToDictionary<string, string>(p => p.Key, p=> p.Value);
CMS
Tried this as well before, but this throws a build error, "The name 'p' does not exist in the current"
Codewerks
figured it out, thanks for your help!
Codewerks
You're welcome :-)
CMS
+3  A: 

Thanks guys, your answers helped me fix this, should be:

var dic = db
        .Table
        .Select(p => new { p.Key, p.Value })
        .AsEnumerable()
        .ToDictionary(k=> k.Key, v => v.Value);
Codewerks
The reason you need AsEnumerable() is because LINQ to SQL doesn't mix local and remote (SQL) processing so this causes the first part to execute on the SQL server and then the final subsequent part to execute locally using LINQ to Objects which can do Dictionarys :)
DamienG
Makes sense. Also, the second parameter in ToDictionary needs its own Func arguments, which was tripping me up earlier.
Codewerks
+1  A: 

Why would you create an anonymous object for every item in the table just to convert it?

You could simply use something like: IDictionary<string, string> dic = db.Table.ToDictionary(row => row.Key, row => row.Value); You may need to include an AsEnumerable() call between Table and ToDictionary(). I don't know the exact type of db.Table.


Also correct the first sample, your second loop variable is mismatching at declaration and usage.

TWiStErRob