Category
pkidCategory
と自己参照外部キーを含むテーブルがありますfiCategory
。つまり、。の場合、カテゴリは「メインカテゴリ」 fiCategory is null
です。別のカテゴリにリンクしている場合fiCategory
、それはそのサブカテゴリです。ただし、このサブカテゴリにも1-n個のサブカテゴリがあることも有効です(fiCategory
それにリンクしていidCategory
ます)。
Q:メインカテゴリ、サブカテゴリ、「サブサブカテゴリ」などのリストを取得するにはどうすればよいですか。LINQで?
背景:
型指定されたDataSetを使用して、Server1/MySQLのデータをServer2/MSSQL-Serverのデータと比較しています。正規化とクリーニング(いくつかの不整合があります)の後、新しいデータをSQL-Serverにインポートしたいと思います。まず、メインカテゴリをインポートし、次にサブカテゴリをインポートする必要があります。そうしないと、SQL-Serverは、まだ挿入されていないカテゴリに外部キーを含む行を挿入しようとすると、制約例外をスローします。
これらはテーブルです(左のMySQLソース、右のSQL Server宛先テーブル):
ここでは、SQL-ServerにないMySQLの新しい行を取得しています。
src
とdest
は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
ここで、新しい行をインポートします。このようにして、すべての「メインカテゴリ」を取得します。
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