有一个表Category
,其中包含pk idCategory
和一个自引用外键fiCategory
。这意味着在fiCategory is null
时,类别是“主要类别”。如果fiCategory
链接到另一个类别,则它是它的子类别。但是这个子类别也有1-n个子类别(fiCategory
链接到它的idCategory
)也是有效的。
问:如何获取主要类别,子类别,“子子类别”等列表。用LINQ?
Backgound :
我正在使用类型化DataSet将Server1 / MySQL中的数据与Server2 / MS SQL-Server中的数据进行比较。规范化和清理后(有几个不一致)我想将新数据导入SQL-Server。首先,我必须导入主要类别,然后是子类别等。否则当我尝试将带有外键的行插入到尚未插入的类别时,SQL-Server会抛出约束异常。
这些是表(左MySQL-source,右SQL-Server目标表):
这里我得到MySQL中不在SQL-Server中的新行:
src
和dest
是类型化的DataSet
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
答案 0 :(得分:2)
Yes, Foreign Key constraints can be temporarily disabled
执行此操作的最佳方法(除了禁用外键,只是逐行复制整个表)是从主要类别开始递归的。从概念上讲,你会这样做:
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.
等。很容易得到你目前所拥有的任何类别的子类别,所以如果你只是从顶部开始,你可以走遍整个树并添加另一边缺少的任何东西。