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


346

Я хочу добавить несколько строк в базу данных, используя Linq to 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 to Object (вместо Linq to SQL)
Pac0

119

Глядя на ваш пример, я думаю, что это то, что вы хотите:

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

Ух ты ... Это может быть просто ... Так как я довольно новичок в программировании, я попробую это и сделаю небольшое профилирование, чтобы убедиться, что под капотом я не получаю попадание всего объекта. Я буду держать вас в курсе.
Tipx

1
Я только что сделал свой чек. К сожалению, когда я получаю TableObj, он выбирает все объекты из БД, поэтому я получаю трафик. Я также проверил запросы, которые я отправил вторым способом (и хотел избежать), и они получили только необходимые элементы. Конечно, он выполняет 2 запроса, поэтому сам сервер должен дважды искать таблицы, но сопоставление объектов достаточно простое.
Tipx

7
Вы могли бы сделать: TableObj.Select (t => new {t.Key, t.TimeStamp}). ToDictionary (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 строк, и я хотел бы извлечь словарь, используя значения первых 2 столбцов.
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();

Для нескольких ключей ?
Kiquenet
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.