Converter resultado da consulta Linq em dicionário


346

Desejo adicionar algumas linhas a um banco de dados usando o Linq to SQL, mas desejo fazer uma "verificação personalizada" antes de adicionar as linhas para saber se devo adicionar, substituir ou ignorar as linhas recebidas. Eu gostaria de manter o tráfego entre o cliente e o servidor de banco de dados o mais baixo possível e minimizar o número de consultas.

Para fazer isso, quero buscar o mínimo de informações necessárias para a validação e apenas uma vez no início do processo.

Eu estava pensando em fazer algo assim, mas obviamente não funciona. Alguém tem uma ideia?

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

O que eu gostaria de ter no final seria um Dicionário, sem ter que baixar todos os objetos ObjectType do TableObject.

Também considerei o código a seguir, mas estava tentando encontrar uma maneira adequada:

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

Respostas:


632

Tente usar o ToDictionarymétodo da seguinte maneira:

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

2
@pawan, é um espaço reservado para cada elemento na enumeração e assume o tipo de objetos na enumeração.
— precisa saber é o seguinte

11
@ pawan - isso não parece certo. Eu esperaria que var servers = list.Select( s => new { s.ProjectName, Url = "tcp://" + s.BuildMachineName + ":" + s.PortNumber + "/CruiseManager.rem" } ).ToDictionary( s => s.ProjectName, s.Url ); isso cria um dicionário digitado pelo nome do projeto dos pares nome do projeto / URL.
— Tevanfosson

3
Por que a .Select( t => new { t.Key, t.TimeStamp } )expressão é necessária?
— Ben Collins

9
@ BenCollins: Eu acho que o intermediário .Selectfaz com que o SQL gerado selecione apenas Key e TimeStamp, em vez de selecionar todas as colunas.
— Joey Adams

11
Você pode omitir este intermediário Selectse você estiver fazendo Linq para Object (em vez de Linq para SQL)
— Pac0

119

Olhando para o seu exemplo, acho que é isso que você deseja:

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

Uau ... Pode ser simples assim ... Como sou bastante iniciante em programação, vou tentar fazer um pouco de criação de perfil para garantir que, sob o capô, não recebo o impacto de todo o objeto. Vou mantê-lo informado.
— Tipx

11
Acabei de fazer meu cheque. Infelizmente, ao obter o TableObj, ele busca todos os objetos do banco de dados, então acabo recebendo o tráfego. Também verifiquei as consultas da segunda maneira que publiquei (e queria evitar) e elas só obtêm os itens necessários. Certamente, ele faz duas consultas para que o próprio servidor precise pesquisar duas vezes as tabelas, mas o mapeamento de objetos é bastante simples.
— Tipx

7
Você pode fazer: TableObj.Select (t => new {t.Key, t.TimeStamp}). ToDictionary (t => t.Key, t => t.TimeStamp); O LinqToSql deve perceber que você deseja apenas duas coisas (a partir da seleção) e devolvê-las. Não tenho certeza de que seja inteligente o suficiente para investigar as especificidades do ToDictionary ().
— Talljoe 5/06/09

11
AGRADÁVEL! Aqui está a consulta resultante: SELECT [t0]. [Key], [t0]. [TimeStamp] FROM [TableObj] AS [t0]. Eu não quero levar o crédito por isso, então vá em frente e publique isso como uma resposta! :-P
— Tipx 5/06/09

8

Tente o seguinte

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

Ou a versão inferida do tipo completo

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

Obrigado pela resposta JaredPar. Eu ensinei sobre algo assim, mas acho que isso retornaria todos os objetos do tipo ObjType, e quero evitar o download de todos os objetos.
— Tipx

@ Tipx, você pode fornecer algumas informações sobre o que deseja filtrar? Adicionando uma cláusula de filtro é possível, mas eu não posso dizer de sua pergunta o que é importante
— JaredPar

Tudo o que preciso saber se a "nova linha" precisa ser adicionada, ignorada ou substituída por outra linha é o registro de data e hora do objeto. Os objetos no banco de dados têm muitos campos dos quais não preciso para a validação e não quero obter o desempenho de obter os objetos inteiros. Para simplificar, consegui uma tabela no meu BD com 20 colunas, 100 000 linhas e gostaria de extrair um dicionário usando os valores das 2 primeiras colunas.
— Tipx

Acabei de verificar as consultas do servidor geradas por esse código e, como você provavelmente sabia, ele obtém todos os objetos.
— Tipx

0

Usar espaço para nome

using System.Collections.Specialized;

Criar instância da DataContextclasse

LinqToSqlDataContext dc = new LinqToSqlDataContext();

Usar

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

Para recuperar os valores, use o namespace

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

Para chaves de múltiplas entradas ?
— Kiquenet
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.