【发布时间】:2011-07-19 22:19:12
【问题描述】:
有一个表 Category 带有一个 pk idCategory 和一个自引用外键 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 中的新行:
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
【问题讨论】:
-
解决方案应放入自己的答案中并标记为已接受的答案,或者您应编辑现有已接受的答案并将“解决方案”添加到其中,以便解决方案存在于一个位置。
-
我接受了 Tridus 的回答,并将我的实际解决方案添加到我的问题中清晰可见,因此我不明白我会做得更好。
标签: .net vb.net linq ado.net linq-to-dataset