Фон
Я импортирую данные из базы данных MySQL в базу данных SQL-сервера (для отчетов, а затем и для куба SSAS). Я хочу нормализовать данные одновременно. Я хочу сгруппировать повторение Ticket_IDs
для одной записи в таблице Contact
с другой полезной информацией и оставить необработанные данные в под-таблице ContactDetail
(с иностранным ключом для контакта). Следовательно, каждая запись в Contact
имеет уникальный Ticket_ID
.
Я решил использовать строгие типизированные наборы данных для импорта. Теперь мне интересно, как лучше всего определить, добавил ли я уже Ticket_ID. Я мог бы проверить это в каждом цикле (~ 100000 записей), но я предполагаю, что есть лучший / более быстрый способ.
Упрощенные данные выборки:
Ticket_ID ID fiContact
89442226 1 1
89442226 2 1
89442226 3 1
89442261 4 2
89442261 5 2
89442354 6 3
89442359 7 4
89442359 8 4
89442367 9 5
89442504 10 6
Это должна быть Contact
-таблица
Ticket_ID idContact
89442226 1
89442261 2
89442354 3
89442359 4
89442367 5
89442504 6
Вопрос
Возможно ли с помощью LINQ / LINQ-to-DataSet сгруппировать по Ticket_ID и получить список ContactDetailRows для каждого ContactRow? Я знаю, что есть GroupBy -Extension, но я не уверен, как использовать и, если он делает то, что мне нужно (оставьте ContactDetail-Rows, например, как диктитарий с Ticket_ID в качестве ключа и List(of EmailRow)
как значение).
Вот что у меня есть (упрощенно):
For Each srcEmail In src.email 'i want to group src.email by Ticket_ID'
'so far i check for existence in every loop'
Dim res = From c In dest.Contact
Where c.Ticket_ID = srcEmail.ticket_id
If Not res.Any Then
'create new Contact
Dim newContact = Me.dest.Contact.NewContactRow
newContact.Ticket_ID = srcEmail.ticket_id
' ..... '
dest.Contact.AddContactRow(newContact)
End If
'TODO: create ContactDetail row and add it to the DataTable '
Next
src
: типизированный DataSet (MySQL)
src.email
: введено DataTable => в ContactDetail
dest
: типизированный DataSet (SQL-Server)
dest.Contact
набрано DataTable
dest.ContactDetail
набрано DataTable с FK до Contact
Я бы предпочел VB.NET, потому что я еще не так хорошо знаком с LINQ, а синтаксис в C # совсем другой.
Edit:
Благодаря @Magnus я получаю это следующим образом:
Dim emailsPerTicketID = src.email.ToLookup(Function(email) email.ticket_id)
For Each ticket In emailsPerTicketID
'create new Contact
Dim newContact = Me.dest.Contact.NewContactRow
newContact.Ticket_ID = ticket.Key
newContact.CreatedAt = ticket.First().modified_time
' ...... '
dest.Contact.AddContactRow(newContact)
'TODO: add now all EmailRows'
For Each emailRow In ticket
Dim newContactDetail = dest.ContactDetail.NewContactDetailRow
newContactDetail.ContactRow = newContact
newContactDetail.Interaction = emailRow.interaction
' .... '
dest.ContactDetail.AddContactDetailRow(newContactDetail)
Next
Next
Я посмотрю, будет ли это быстрее, чем итеративный подход с HashSet, чтобы определить, был ли контакт уже создан.