Linq-SQL ToDictionary ()


81

Linq kullanarak SQL'den (2008) iki sütunu bir Sözlüğe (önbelleğe almak için) nasıl dönüştürebilirim?

Şu anda IQueryable b / c üzerinden döngü yapıyorum ToDictionary yönteminin çalışmasını sağlayamıyorum. Herhangi bir fikir? Bu çalışıyor:

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

Gerçekten yapmak istediğim şey, işe yaramadı gibi görünen böyle bir şey:

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

Ancak şu hatayı alıyorum: 'System.Linq.IQueryable'dan' System.Collections.Generic.IEnumerable'a dönüştürülemiyor

Yanıtlar:


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

Üzgünüm, net olmamış olabilirim, bunu daha önce denedim, ancak bu bir Dictionary <string, #Anonymous Type> oluşturuyor, Dictionary <string, string> değil
Codewerks

Deneyin kvp => kvp.Value as string. Cevabın amacı şuydu .AsEnumerable().
yfeldblum

Teşekkürler, evet AsEnumerable'a ihtiyaç olduğunu düşündüm, ancak ToDictionary çağrısı hala çalışmıyor. Her iki sütun da SQL'de varchar'dır, bu yüzden dizeler olarak geri gelirler, ancak bunu bir
Dic'e

Bunun hala geçerli olup olmadığını bilmiyorum, ama neden AsEnumerablegerekli? Benim için onsuz da çalışıyor, ama muhtemelen Linq çoktan değişti (7 yıl geçti)
Alexander Derck

1
@AlexanderDerck - O zamanlar AsEnumerablegerekliydi. Bunca zamandan sonra nedenini tam olarak hatırlamıyorum, ancak olası bir açıklama, bunun ToDictionarybir genişletme yöntemi olduğu IEnumerable, ancak Linq-SQL için arayüz değildi IEnumerable.
yfeldblum

16

Yalnızca anahtarı tanımlıyorsunuz, ancak değeri de eklemeniz gerekiyor:

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

3
-1 Hata, <string, string>parçanın public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer);aşırı yük yerine aşırı yüklemeyi kullanmasıdır public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector);.
user247702

Sanırım daha .AsEnumerable()önce ihtiyacı var.ToDictionary()
AceMark

mükemmel çalıştı ... nihayet aradığım
Brian

9

Teşekkürler çocuklar, cevaplarınız bunu düzeltmeme yardımcı oldu, şöyle olmalı:

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

5
AsEnumerable () 'a ihtiyaç duymanızın nedeni, LINQ to SQL'in yerel ve uzak (SQL) işlemeyi karıştırmamasıdır; bu, ilk parçanın SQL sunucusunda yürütülmesine ve ardından son sonraki parçanın LINQ to Objects kullanarak yerel olarak yürütülmesine neden olur. do Dictionarys :)
DamienG

Mantıklı. Ayrıca, ToDictionary'deki ikinci parametrenin, beni daha önce tetikleyen kendi Func argümanlarına ihtiyacı var.
Codewerks

1

Neden sadece onu dönüştürmek için tablodaki her öğe için anonim bir nesne oluşturuyorsunuz?

IDictionary<string, string> dic = db.Table.ToDictionary(row => row.Key, row => row.Value); Şuna benzer bir şey kullanabilirsiniz: Table ve ToDictionary () arasına bir AsEnumerable () çağrısı eklemeniz gerekebilir. Veri tabanının tam türünü bilmiyorum.


Ayrıca ilk örneği düzeltin, ikinci döngü değişkeniniz bildirim ve kullanımda uyuşmuyor.


2
Çünkü ToDictionarybellektir. Anonim bir nesne oluşturmamak, yalnızca ihtiyacınız olanlar yerine tüm sütunların veritabanından alınacağı anlamına gelir.
user247702

ToDictionarytemelde yatan yapı hakkında bilgi sahibi değildir, sadece anahtar ve değer için iki geri çağrıyı çağırır (bu durumda basit özellik lambdaları seçerek), bu nedenle bu ToDictionaryçağrı, sağladığı örnekteki foreach ile işlevsel olarak eşdeğer olmalıdır. Bildiğim kadarıyla tüm LINQ yöntemleri ertelendi, yani geri aramaların yalnızca gerektiğinde çağrıldığı anlamına geliyor.
TWiStErRob

3
SQL Server Profiler ile bakarsanız, anonim bir nesneyle yalnızca iki sütunun seçildiğini ve onsuz tüm sütunların seçildiğini görürsünüz.
user247702
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.