Linq-to-SQL ToDictionary()


81

如何使用Linq将SQL(2008)中的两列正确转换为Dictionary(用于缓存)?

我目前正在遍历IQueryable b / c,但无法使用ToDictionary方法。有任何想法吗?这有效:

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);
}

我真正想做的是这样的事情,它似乎不起作用:

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

但我收到此错误:无法从“ System.Linq.IQueryable”转换为“ System.Collections.Generic.IEnumerable”

Answers:


121
var dictionary = db
    .Table
    .Select(p => new { p.Key, p.Value })
    .AsEnumerable()
    .ToDictionary(kvp => kvp.Key, kvp => kvp.Value)
;

抱歉,我可能还不清楚,我之前尝试过此方法,但这会创建一个Dictionary <string,#Anonymous Type>,而不是Dictionary <string,string>
Codewerks

尝试kvp => kvp.Value as string。答案是.AsEnumerable()
yfeldblum

谢谢,是的,我认为需要AsEnumerable,但是ToDictionary调用仍然无法正常工作。这两列都是SQL中的varchars,因此它们以字符串形式返回,但是我不知道如何将其放入Dic中
。...– Codewerks

我不知道这是否仍然有用,但是为什么AsEnumerable需要?对我来说,它也可以
不起作用

1
@AlexanderDerck-当时,这AsEnumerable是必要的。我一直都不记得为什么会一直这样,但是一个可能的解释是那ToDictionary是on的扩展方法IEnumerable,但是Linq-to-SQL的接口却不是IEnumerable
yfeldblum 2015年

16

您仅在定义键,但还需要包括该值:

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

3
-1错误是<string, string>部件使它使用了public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer);过载而不是public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector);过载。
user247702

我认为它仍然需要.AsEnumerable().ToDictionary()
AceMark

完美地工作了...终于找到了我想要的那个人
Brian

9

谢谢大家,您的回答可帮助我解决此问题,应为:

var dic = db
        .Table
        .Select(p => new { p.Key, p.Value })
        .AsEnumerable()
        .ToDictionary(k=> k.Key, v => v.Value);

5
需要AsEnumerable()的原因是因为LINQ to SQL不会将本地和远程(SQL)处理混合在一起,所以这导致第一部分在SQL Server上执行,然后最后的后续部分使用LINQ to Objects在本地执行。做字典:)
DamienG

说得通。另外,ToDictionary中的第二个参数需要它自己的Func参数,这使我早些时候感到困惑。
Codewerks

1

为什么要为表中的每个项目创建一个匿名对象以进行转换?

您可以简单地使用类似以下内容的方法: IDictionary<string, string> dic = db.Table.ToDictionary(row => row.Key, row => row.Value); 您可能需要在Table和ToDictionary()之间包含一个AsEnumerable()调用。我不知道db.Table的确切类型。


同时更正第一个样本,您的第二个循环变量在声明和用法上不匹配。


2
因为ToDictionary是在内存中。不创建匿名对象意味着从数据库中检索所有列,而不仅仅是您需要的列。
user247702

ToDictionary因为不知道底层结构,它只调用键和值的两个回调(在本例中为选择lambda的简单属性),因此此ToDictionary调用在功能上应等效于他提供的示例中的foreach。据我所知,所有LINQ方法都被推迟了,这意味着仅在必要时才调用回调。
TWiStErRob 2012年

3
如果使用SQL Server Profiler,您会发现使用匿名对象时,只有两列被选中,而没有匿名对象的所有列均被选中。
user247702
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.