2014-10-20 4 views
1

Вот мой код:Невозможно добавить тот же ключ словарю несколько раз

IEnumerable<ServiceTicket> troubletickets = db.ServiceTickets.Include(t => t.Company).Include(t => t.UserProfile); 
var ticketGroups = new Dictionary<string, List<ServiceTicket>>(); 

ticketGroups = troubletickets 
       .GroupBy(o => o.DueDate).ToDictionary(
        group => { 
         var firstOrDefault = @group.FirstOrDefault(); 
         return firstOrDefault != null 
          ? firstOrDefault.DueDate.HasValue 
           ? firstOrDefault.DueDate.Value.ToShortDateString() 
           : "" 
          : ""; 
        }, 
        group => group.ToList() 
       ).OrderBy(g => g.Key).ToDictionary(g => g.Key, g => g.Value); 

ошибка, что я получаю: "Элемент с тем же ключом уже был добавлен. Это связано с тем, что значение DueDate иногда повторяется. Мой вопрос в том, как я могу сохранить ключ от добавления, если он уже существует в словаре?

+0

Вместо использования ['ToDictionary()'] (http://msdn.microsoft.com/en-us/library/vstudio/bb549277%28v=vs.100%29.aspx), выполните итерацию элементов в запрос и построить словарь самостоятельно. Вы даже можете сделать свое собственное перечислимое расширение 'ToDictionaryWithDuplicatedKeys()'. – dbc

+2

Я отредактировал ваш заголовок. Пожалуйста, смотрите: «Если вопросы включают« теги »в их названиях?] (Http://meta.stackexchange.com/questions/19190/), где консенсус« нет, они не должны ». –

+2

Вы также можете использовать [HashSet] (http://msdn.microsoft.com/en-us/library/bb359438%28v=vs.110%29.aspx) - добавление дублирующего ключа возможно, но коллекция содержит элемент только один раз. Но было бы, вероятно, проще применять Distinct, как уже было предложено. – pasty

ответ

1

Кажется, что вы группируете одно значение (значение DueDate), но используя другое значение в качестве словарного ключа.

Можете ли вы не просто использовать собственный код для группировки?

ticketGroups = troubletickets 
       .GroupBy(o => o.DueDate.HasValue 
           ? o.DueDate.Value.ToShortDateString() 
           : "") 
       .ToDictionary(g => g.Key, g => g.ToList()); 

Обратите внимание, что я взял наш излишнюю OrderBy и второй ToDictionary вызова - я предположил, что вы пытались «заказать» словарь, который не будет работать как обычный словарь не упорядочен.

0

Вы получаете дубликаты ключей, потому что есть два способа получить пустую строку как ключ, либо пустую группу, либо пустую дату. Дубликат всегда будет пустой строкой. Интересно, действительно ли вы намеревались получить пустую строку как ключ, когда группа пуста. В любом случае, это необязательно, вы всегда можете фильтровать пустые группы позже.

легче группировать по дате (включая нуль) первого через ядро ​​базы данных, а затем применить строку форматирования в памяти:

IQueryable<ServiceTicket> troubletickets = db.ServiceTickets 
              .Include(t => t.Company) 
              .Include(t => t.UserProfile); 

Dictionary<string, List<ServiceTicket>> ticketGroups = 
       troubletickets 
       .GroupBy(ticket => ticket.DueDate) 
       .AsEnumerable() // Continue in memory 
       .ToDictionary(g => g.Key.HasValue 
             ? g.Key.Value.ToShortDateString() 
             : string.Empty, 
            g => g.Select(ticket => ticket)); 

Теперь группировка по значению Key, а не на First элемент в группа. Key никогда не является нулевым, это всегда Nullable<DateTime>, с или без значения.

Примечание стороны: вы заметите, что EF не будет генерировать SQL group by заявление, что это потому, что SQL заявление «деструктивный»: она только возвращает сгруппированных столбцы и агрегированные данные, а не отдельные записи о том, что LINQ GroupByделает возвращение. По этой причине сгенерированный SQL довольно раздутый, и может повысить производительность, если вы разместите AsEnumerable до .GroupBy.

Смежные вопросы