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.