Linq-to-SQL ToDictionary ()


81

Làm cách nào để chuyển đổi đúng cách hai cột từ SQL (2008) bằng Linq thành Từ điển (cho bộ nhớ đệm)?

Tôi hiện đang lặp qua b / c IQueryable Tôi không thể làm cho phương thức ToDictionary hoạt động. Có ý kiến ​​gì không? Những công việc này:

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

Những gì tôi thực sự muốn làm là một cái gì đó như thế này, mà dường như không hoạt động:

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

Nhưng tôi gặp lỗi này: Không thể chuyển đổi từ 'System.Linq.IQueryable' thành 'System.Collections.Generic.IEnumerable'

Câu trả lời:


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

Xin lỗi, tôi có thể chưa được rõ ràng, tôi đã cố gắng thie trước đó, nhưng điều này tạo ra một từ điển <string, #Anonymous Loại>, không Dictionary <string, string>
Codewerks

Cố gắng kvp => kvp.Value as string. Điểm của câu trả lời là .AsEnumerable().
yfeldblum 28/10/08

Cảm ơn, vâng, tôi thấy rằng AsEnumerable là cần thiết, nhưng lệnh gọi ToDictionary vẫn không hoạt động. Cả hai cột đều là varchars trong SQL, vì vậy chúng trở lại dưới dạng chuỗi, nhưng tôi không thể tìm ra cách đưa nó vào một Dic ....
Codewerks 28/10/08

Tôi không biết nếu điều này vẫn còn phù hợp, nhưng tại sao lại AsEnumerablecần thiết? Đối với tôi nó hoạt động mà không có quá, nhưng có lẽ LINQ đã thay đổi (7 năm đã trôi qua)
Alexander Derck

1
@AlexanderDerck - Vào thời điểm đó, điều AsEnumerablenày là cần thiết. Tôi không nhớ chính xác lý do tại sao, sau tất cả thời gian này, nhưng có thể giải thích rằng đó ToDictionarylà một phương thức mở rộng được bật IEnumerable, nhưng giao diện cho Linq-to-SQL thì không IEnumerable.
yfeldblum

16

Bạn chỉ đang xác định khóa, nhưng bạn cũng cần bao gồm giá trị:

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

3
-1 Lỗi là bộ <string, string>phận làm cho nó sử dụng public static Dictionary<TKey, TSource> ToDictionary<TSource, TKey>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, IEqualityComparer<TKey> comparer);quá tải thay vì public static Dictionary<TKey, TElement> ToDictionary<TSource, TKey, TElement>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector);quá tải.
user247702 27/11/12

Tôi nghĩ rằng nó vẫn cần .AsEnumerable()trước.ToDictionary()
AceMark

làm việc một cách hoàn hảo ... cuối cùng là một tôi đang tìm kiếm
Brian

9

Cảm ơn các bạn, câu trả lời của các bạn đã giúp tôi sửa lỗi này, nên là:

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

5
Lý do bạn cần AsEnumerable () là vì LINQ to SQL không kết hợp xử lý cục bộ và từ xa (SQL), vì vậy điều này khiến phần đầu tiên thực thi trên máy chủ SQL và sau đó phần cuối cùng thực thi cục bộ bằng cách sử dụng LINQ to Objects có thể làm từ điển :)
DamienG

Có ý nghĩa. Ngoài ra, tham số thứ hai trong ToDictionary cần các đối số Func của riêng nó, điều này đã khiến tôi vấp phải trước đó.
Codewerks 29/10/08

1

Tại sao bạn lại tạo một đối tượng ẩn danh cho mọi mục trong bảng chỉ để chuyển đổi nó?

Bạn có thể chỉ cần sử dụng một cái gì đó như: IDictionary<string, string> dic = db.Table.ToDictionary(row => row.Key, row => row.Value); Bạn có thể cần bao gồm một lệnh gọi AsEnumerable () giữa Table và ToDictionary (). Tôi không biết chính xác loại db.Table.


Cũng sửa mẫu đầu tiên, biến vòng lặp thứ hai của bạn không khớp ở phần khai báo và cách sử dụng.


2
ToDictionarylà trong bộ nhớ. Không tạo một đối tượng ẩn danh có nghĩa là tất cả các cột được truy xuất từ ​​cơ sở dữ liệu thay vì chỉ những cột bạn cần.
user247702 27/11/12

ToDictionarykhông biết về cấu trúc bên dưới, nó chỉ gọi hai lệnh gọi lại cho khóa và giá trị (trong trường hợp này là thuộc tính đơn giản chọn lambdas), vì vậy ToDictionarylệnh gọi này phải có chức năng tương đương với foreach trong ví dụ anh ta cung cấp. Theo như tôi biết, tất cả các phương thức LINQ đều được hoãn lại, có nghĩa là các lệnh gọi lại chỉ được gọi khi cần thiết.
TWiStErRob

3
Nếu bạn nhìn bằng SQL Server Profiler, bạn sẽ thấy rằng với một đối tượng ẩn danh, chỉ có hai cột được chọn và nếu không có nó, tất cả các cột đều được chọn.
user247702 28/11/12
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.