【问题标题】:Linq-to-SQL ToDictionary()Linq-to-SQL ToDictionary()
【发布时间】:2010-09-19 16:46:05
【问题描述】:

如何使用 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”

【问题讨论】:

    标签: c# linq linq-to-sql


    【解决方案1】:
    var dictionary = db
        .Table
        .Select(p => new { p.Key, p.Value })
        .AsEnumerable()
        .ToDictionary(kvp => kvp.Key, kvp => kvp.Value)
    ;
    

    【讨论】:

    • 对不起,我可能不太清楚,我以前试过,但这会创建一个 Dictionary,而不是 Dictionary
    • 试试kvp =&gt; kvp.Value as string。答案的重点是.AsEnumerable()
    • 谢谢,是的,我认为需要 AsEnumerable,但 ToDictionary 调用仍然不起作用。这两列都是 SQL 中的 varchars,因此它们以字符串形式返回,但我不知道如何将其填充到 Dic 中......
    • 我不知道这是否仍然相关,但为什么需要AsEnumerable?对我来说,没有它也可以工作,但可能 Linq 已经改变了(7 年过去了)
    • @AlexanderDerck - 当时,AsEnumerable 是必要的。我不记得确切原因,毕竟这么久,但可能的解释是ToDictionaryIEnumerable 的扩展方法,但Linq-to-SQL 的接口不是IEnumerable
    【解决方案2】:

    您只是在定义键,但您还需要包含值:

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

    【讨论】:

    • -1 错误在于&lt;string, string&gt; 部分使其使用public static Dictionary&lt;TKey, TSource&gt; ToDictionary&lt;TSource, TKey&gt;(this IEnumerable&lt;TSource&gt; source, Func&lt;TSource, TKey&gt; keySelector, IEqualityComparer&lt;TKey&gt; comparer); 重载而不是public static Dictionary&lt;TKey, TElement&gt; ToDictionary&lt;TSource, TKey, TElement&gt;(this IEnumerable&lt;TSource&gt; source, Func&lt;TSource, TKey&gt; keySelector, Func&lt;TSource, TElement&gt; elementSelector); 重载。
    • 我认为在.ToDictionary()之前仍然需要.AsEnumerable()
    • 完美运行……终于找到了我要找的那个
    【解决方案3】:

    谢谢大家,你们的回答帮我解决了这个问题,应该是:

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

    【讨论】:

    • 您需要 AsEnumerable() 的原因是因为 LINQ to SQL 不会混合本地和远程 (SQL) 处理,因此这会导致第一部分在 SQL 服务器上执行,然后最后的后续部分使用可以执行字典的 LINQ to Objects 在本地执行 :)
    • 有道理。此外,ToDictionary 中的第二个参数需要它自己的 Func 参数,这让我之前很困惑。
    【解决方案4】:

    为什么要为表中的每个项目创建一个匿名对象只是为了转换它?

    你可以简单地使用类似的东西: IDictionary&lt;string, string&gt; dic = db.Table.ToDictionary(row =&gt; row.Key, row =&gt; row.Value); 您可能需要在 Table 和 ToDictionary() 之间包含一个 AsEnumerable() 调用。 我不知道 db.Table 的确切类型。


    同时更正第一个示例,您的第二个循环变量在声明和使用时不匹配。

    【讨论】:

    • 因为ToDictionary 在内存中。不创建匿名对象意味着从数据库中检索所有列,而不仅仅是您需要的列。
    • ToDictionary 不知道底层结构,它只是调用键和值的两个回调(在本例中为简单的属性选择 lambdas),所以这个 ToDictionary 调用在功能上应该是等效的他提供的示例中的foreach。据我所知,所有 LINQ 方法都是延迟的,这意味着只有在必要时才会调用回调。
    • 如果您使用 SQL Server Profiler 进行查看,您会发现使用匿名对象时只选择了两列,没有它则选择了所有列。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多