Перетворити результат запиту Linq в словник


346

Я хочу додати кілька рядків до бази даних за допомогою Linq до SQL, але я хочу зробити "спеціальну перевірку" перед тим, як додати рядки, щоб знати, чи потрібно додавати, замінювати чи ігнорувати вхідні рядки. Я хотів би, щоб інтервал між клієнтом та сервером БД був якомога нижчим та мінімізував кількість запитів.

Для цього я хочу отримати якомога менше інформації, необхідної для перевірки, і лише один раз на початку процесу.

Я думав зробити щось подібне, але очевидно, це не працює. Хтось має ідею?

Dictionary<int, DateTime> existingItems = 
    (from ObjType ot in TableObj
        select (new KeyValuePair<int, DateTime>(ot.Key, ot.TimeStamp))
    )

Я б хотів мати наприкінці Словник, не завантажуючи цілих об’єктів ObjectType з TableObject.

Я також розглядав наступний код, але намагався знайти належний спосіб:

List<int> keys = (from ObjType ot in TableObj orderby ot.Key select ot.Key).ToList<int>();
List<DateTime> values = (from ObjType ot in TableObj orderby ot.Key select ot.Value).ToList<int>();
Dictionary<int, DateTime> existingItems = new Dictionary<int, DateTime>(keys.Count);
for (int i = 0; i < keys.Count; i++)
{
    existingItems.Add(keys[i], values[i]);
}

Відповіді:


633

Спробуйте скористатися таким ToDictionaryметодом :

var dict = TableObj.ToDictionary( t => t.Key, t => t.TimeStamp );

2
@pawan, це заповнювач кожного елемента перерахунку і приймає тип об'єктів у перерахунку.
tvanfosson

1
@pawan - це не виглядає правильно. Я б очікував, що var servers = list.Select( s => new { s.ProjectName, Url = "tcp://" + s.BuildMachineName + ":" + s.PortNumber + "/CruiseManager.rem" } ).ToDictionary( s => s.ProjectName, s.Url ); це створить словник, накреслений назвою проекту назви проекту / URL-адреси.
tvanfosson

3
Чому .Select( t => new { t.Key, t.TimeStamp } )вираз потрібен?
Бен Коллінз

9
@BenCollins: Я думаю, що проміжний .Selectзмушує згенерований SQL вибирати лише Key і TimeStamp, а не вибирати кожен стовпець.
Джої Адамс

1
Ви можете опустити цього посередника, Selectякщо ви робите Linq для Object (замість Linq до SQL)
Pac0

119

Дивлячись на ваш приклад, я думаю, що саме цього ви хочете:

var dict = TableObj.ToDictionary(t => t.Key, t=> t.TimeStamp);

Нічого собі ... Це може бути простим ... Оскільки я досить новачок у програмуванні, я спробую це і зробити трохи профілювання, щоб переконатися, що під кришкою я не отримую удар цілого об'єкта. Я буду тримати вас у курсі.
Tipx

1
Я щойно зробив перевірку. На жаль, отримуючи TableObj, він отримує всі об'єкти з db, тому я в кінцевому підсумку отримую трафічний удар. Я також перевірив запити, які я розмістив другим способом (і хотів уникнути), і вони отримують лише необхідні елементи. Звичайно, він виконує 2 запити, тому сервер повинен шукати двічі таблиці, але відображення об'єктів досить просте.
Tipx

7
Ви можете зробити це: TableObj.Select (t => новий {t.Key, t.TimeStamp}) .DDictionary (t => t.Key, t => t.TimeStamp); LinqToSql повинен мати можливість помітити, що ви хочете лише дві речі (з вибору) і повернути їх. Я не впевнений, що це досить розумно, щоб заглибитись у специфіку ToDictionary ().
Talljoe

1
НІШЕ! Ось отриманий запит: SELECT [t0]. [Key], [t0]. [TimeStamp] FROM [TableObj] AS [t0]. Я не хочу брати за це заслугу, тому вперед і розміщуйте це як привид! :-P
Tipx

8

Спробуйте наступне

Dictionary<int, DateTime> existingItems = 
    (from ObjType ot in TableObj).ToDictionary(x => x.Key);

Або повноцінна версія умовиводу

var existingItems = TableObj.ToDictionary(x => x.Key);

Дякую за прихильного JaredPar. Я вчив про щось подібне, але думаю, що це поверне цілі об'єкти типу ObjType, і я хотів би уникати завантаження цілих об'єктів.
Tipx

@Tipx, чи можете ви надати деяку інформацію про те, що ви хочете відфільтрувати? Додавання фільтруючого пункту можливо, але я не можу сказати з вашого питання, що важливо
JaredPar

Все, що мені потрібно знати, чи потрібно додавати "новий рядок", ігнорувати чи замінювати інший рядок часовою міткою об'єкта. Об'єкти в БД мають багато полів, які мені не потрібні для перевірки, і я не хочу отримувати ефективність отримання цілих об'єктів. Щоб зробити це просто, я отримав таблицю в своєму BD з 20 стовпцями, 100 000 рядків, і я хотів би витягнути Словник, використовуючи значення перших двох стовпців.
Tipx

Я щойно перевірив запити сервера, згенеровані цим кодом, і, як ви, напевно, знали, він отримує цілі об'єкти.
Tipx

0

Використовуйте простір імен

using System.Collections.Specialized;

Зробіть екземпляр DataContextкласу

LinqToSqlDataContext dc = new LinqToSqlDataContext();

Використовуйте

OrderedDictionary dict = dc.TableName.ToDictionary(d => d.key, d => d.value);

Для отримання значень використовуйте простір імен

   using System.Collections;

ICollection keyCollections = dict.Keys;
ICOllection valueCollections = dict.Values;

String[] myKeys = new String[dict.Count];
String[] myValues = new String[dict.Count];

keyCollections.CopyTo(myKeys,0);
valueCollections.CopyTo(myValues,0);

for(int i=0; i<dict.Count; i++)
{
Console.WriteLine("Key: " + myKeys[i] + "Value: " + myValues[i]);
}
Console.ReadKey();

Для клавіш Multilple ?
Кікенет
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.