There's a table Category
with a pk idCategory
and a self-referencing foreign-key fiCategory
. That means categories are "main-categories" when fiCategory is null
. If fiCategory
links to another category, it is a sub-category of it. But it's also valid that this sub-category also has 1-n sub-categories(with fiCategory
linking to it's idCategory
).
Q: How can i get a list of main-categories,sub-categories,"sub-sub-categories", ...etc. with LINQ?
Backgound:
I'm using typed DataSets to compare data from Server1/MySQL with data from Server2/MS SQL-Server. After normalizing and cleaning(there are several inconsistencies) i want to import the new data into SQL-Server. First of all i have to import the main-categories, then the sub-categories and so on. Otherwise SQL-Server would throw a constraint exception when i would try to insert a row with a foreign-key to a category that is yet not inserted.
These are the tables(left MySQL-source, right SQL-Server destination table):
Here i'm getting the new rows in MySQL that are not in SQL-Server:
src
and dest
are typed DataSets
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
Now i want to import the new rows. In this way i get all "main-categories":
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
In this way i get all sub-categories:
Dim subCat = From kat In src.kategorie
Join d In diff
On kat.kategorie_id Equals d
Where Not kat.IsparentNull
Select kat
Both LINQ-queries are working, but how do i get all "levels" of sub-categories? I need to insert the rows from "top" to "bottom". Is there a way that works even with any depth?
At least this is not working(repeating pk-values):
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
I'm still learning LINQ and appreciating any kind of suggestions(also in C#). Thank you in advance.
Note: Maybe you know a way i can temporarily disable the foreign key contraint in SQL-Server and enable it after i inserted all rows from ADO.NET. That would be much simpler.
This is the solution, thanks to @Tridus:
Dim mainCat = From kat In src.kategorie
Where kat.IsparentNull
Select kat
For Each kat In mainCat
rowsUpdated += insertCategory(kat, diff, daCategoryOut)
Next
This is the recursive function:
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