1

有一个Category带有 pkidCategory和自引用外键的表fiCategory。这意味着当 fiCategory is null. 如果fiCategory链接到另一个类别,它是它的子类别。但是这个子类别也有 1-n 个子类别(fiCategory链接到它idCategory)也是有效的。

问:如何获取主类别、子类别、子类别、...等的列表。与 LINQ?

背景

我正在使用类型化的数据集来比较来自 Server1/MySQL 的数据和来自 Server2/MS SQL-Server 的数据。规范化和清理后(有几个不一致的地方)我想将新数据导入 SQL-Server。首先我必须导入主要类别,然后是子类别等等。否则,当我尝试将具有外键的行插入尚未插入的类别时,SQL-Server 将引发约束异常。

这些是表(左 MySQL 源表,右 SQL Server 目标表):

类别: MySQL 源代码 类别:SQL-Server 目标

在这里,我得到了 MySQL 中不在 SQL-Server 中的新行:

src并且dest是类型化的数据集

Dim idSrc = From c In src.kategorie Select c.kategorie_id
Dim idDest = From c In dest.Category Select c.idCategory
Dim diff = idSrc.Except(idDest)
Dim needUpdate = diff.Any

现在我想导入新行。通过这种方式,我得到了所有“主要类别”:

Dim mainCat = From kat In src.kategorie
            Join d In diff
            On kat.kategorie_id Equals d
            Where kat.IsparentNull
        Select kat

For Each cat In mainCat
    Dim newCat = Me.dest.Category.NewCategoryRow
    newCat.idCategory = cat.kategorie_id
    newCat.Name = cat.name
    newCat.SetfiCategoryNull()
    dest.Category.AddCategoryRow(newCat)
    rowsUpdated += daCategoryOut.Update(dest.Category)
Next

通过这种方式,我得到了所有子类别:

Dim subCat = From kat In src.kategorie
               Join d In diff
               On kat.kategorie_id Equals d
               Where Not kat.IsparentNull
          Select kat

两个 LINQ 查询都在工作,但我如何获得子类别的所有“级别”?我需要将行从“顶部”插入到“底部”。有没有一种方法可以在任何深度下都有效?

至少这不起作用(重复 pk 值):

Dim subCatWithChild = From cat In subCat
                      Join child In 
                     (From kat In src.kategorie Where Not kat.IsparentNull)
                      On child.parent Equals cat.kategorie_id
                   Select cat

我仍在学习 LINQ 并欣赏任何类型的建议(也在 C# 中)。先感谢您。

注意:也许您知道一种方法,我可以暂时禁用 SQL-Server 中的外键约束,并在我从 ADO.NET 插入所有行后启用它。那会简单得多。


这是解决方案,感谢@Tridus:

Dim mainCat = From kat In src.kategorie
          Where kat.IsparentNull
      Select kat

For Each kat In mainCat
   rowsUpdated += insertCategory(kat, diff, daCategoryOut)
Next

这是递归函数:

Private Function insertCategory(ByVal parent As CC_IN.kategorieRow, ByVal diff As IEnumerable(Of Int32), ByVal daCategoryOut As CC_OutTableAdapters.CategoryTableAdapter) As Int32
    Dim rowsInserted As Int32 = 0

    If diff.Contains(parent.kategorie_id) Then
        Dim newCat = Me.dest.Category.NewCategoryRow
        newCat.idCategory = parent.kategorie_id
        newCat.Name = parent.name
        If parent.IsparentNull Then
            newCat.fiCategory = parent.parent
        Else
            newCat.SetfiCategoryNull()
        End If
        dest.Category.AddCategoryRow(newCat)
        rowsInserted += daCategoryOut.Update(dest.Category)
    End If

    'get all childs from this parent
    Dim childs = From cat In Me.src.kategorie
               Where Not cat.IsparentNull AndAlso cat.parent = parent.kategorie_id
               Select cat
    'insert all childs for this parent
    For Each child In childs
        rowsInserted += insertCategory(child, diff, daCategoryOut)
    Next

    Return rowsInserted
End Function
4

1 回答 1

2

是的,外键约束可以暂时禁用

最好的方法(除了禁用外键并逐行复制整个表)是从主要类别开始递归。从概念上讲,你会这样做:

Get the main categories (which you've done)
For each main category
   Is this one in the other DB? If not, add it.
   Get the sub-categories of this main category.
   For each sub-category
     Is this one in the other DB? If not, add it.
     Get the sub-categories of this sub-category.

等等。很容易获得您当前拥有的任何类别的子类别,因此如果您只是从顶部开始,您可以遍历整个树并添加另一边缺少的任何内容。

于 2011-07-19T22:46:16.960 回答