1

背景

我正在将数据从 MySQL 数据库导入 SQL-Server 数据库(用于报告和后来的 SSAS-Cube)。我想同时规范化数据。我想将重复分组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-table

Ticket_ID    idContact
89442226     1
89442261     2
89442354     3
89442359     4
89442367     5
89442504     6

问题

LINQ/LINQ-to-DataSet 是否可以按 Ticket_ID 分组并获取每个 ContactRow 的 ContactDetailRows 列表?我知道有一个GroupBy -Extension,但我不确定如何使用以及它是否满足我的需要(保留 ContactDetail-Rows,fe 就像一个以 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:类型化数据集(MySQL)
  • src.email: 输入 DataTable => 到ContactDetail
  • dest: 类型化数据集(SQL-Server)
  • dest.Contact类型化数据表
  • dest.ContactDetail使用 fk 键入 DataTableContact

我更喜欢 VB.NET,因为我对 LINQ 还不太熟悉,而且 C# 中的语法完全不同。

编辑:

感谢@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 的迭代方法更快来检测联系人是否已经创建。

4

2 回答 2

1

我的 VB 生锈了,但这里有一个镜头:

Dim ticketGroups = From c in dest.Contact
                    Group c By Ticket_ID = c.Ticket_ID 
                    Into Tickets = Group

For Each ticketGroup In ticketGroups
    For Each ticket in ticketGroup.Tickets
        ' Create the row, add it, etc.
        Dim newContact = Me.dest.Contact.NewContactRow
        newContact.Ticket_ID = ticketGroup.Ticket_ID
        ' .... '
        dest.Contact.AddContactRow(newContact)
    Next
Next

或者,如果您想在每次循环中检查它,您可以使用HashSet,只需将票证 ID 每次都添加到哈希集中,然后通过该Contains方法检查它的存在。这会比你正在做的更快,但我怀疑 LINQ 分组会比 HashSet 更快。

于 2011-07-14T22:43:47.507 回答
1

我认为使用查找(如字典,但使用键/集合代替)对您来说是一个很好的解决方案。像这样的东西:

var lookup = ds.Tables["src"].AsEnumerable().ToLookup(x => x.Field<int>("Ticket_ID"));
foreach (var row in ds.Tables["dest"].AsEnumerable())
{
    if(!lookup.Contains(row.Field<int>("Ticket_ID ")))
    {
        //create new Contact
    }
    else
    {
        //do other struff
    }
}

如果您需要任何帮助将任何语法翻译成 VB 评论我。

于 2011-07-14T22:45:22.430 回答