2011-07-19 18 views
1

テーブルCategoryには、pk idCategoryと自己参照外部キーfiCategoryがあります。つまり、カテゴリは「fiCategory is null」のときは「メインカテゴリ」です。 fiCategoryが別のカテゴリにリンクしている場合、それはそのサブカテゴリです。しかし、このサブカテゴリにも1-nのサブカテゴリがあります(fiCategoryidCategoryにリンクしています)。LINQの自己参照テーブルの "レベル"を取得するにはどうすればよいですか?

Q:メインカテゴリ、サブカテゴリ、サブサブカテゴリなどのリストを取得するにはどうすればよいですか? LINQとは?

Backgound

私は、サーバー2/MS SQL-ServerからのデータとのServer1/MySQLのデータを比較するために型指定されたデータセットを使用しています。正規化とクリーニング(いくつかの矛盾があります)した後、私はSQL Serverに新しいデータをインポートします。まず、メインカテゴリ、次にサブカテゴリなどをインポートする必要があります。さもなければ、まだ挿入されていないカテゴリに外部キーを持つ行を挿入しようとすると、SQL Serverは制約の例外をスローします。

これらは、テーブル(左MySQLのソース、右SQL-Serverの先テーブル)です。

Kategorie: MySQL-sourceCategory: SQL-Server destination

ここで私はSQL-ServerではありませんMySQLで新しい行を取得しています:

srcdest今、私はイムしたい

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のおかげソリューションです:

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

解答はそれ自身の解答に入れ、受け入れられた解答としてマークするか、既存の解答を編集して解決策を追加して解が1か所に存在するようにする必要があります。 –

+0

私はTridusの答えを受け入れて、私の質問に私の実際の解決策を追加しました。したがって、私は何が良くできたのか分かりません。 –

答えて

2

Yes, Foreign Key constraints can be temporarily disabled

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

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

これは再帰関数です。

外部キーを無効にし、テーブル全体を行単位でコピーする以外の方法は、メインカテゴリから再帰的に開始することです。概念的には、あなたがこれを行うだろう:など

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. 

をそれはあなたが現在持っているものは何でもカテゴリのサブカテゴリを取得するのは簡単ですので、あなただけの上部に開始する場合は、ツリー全体を歩いてい何かを追加することができます反対側には欠けている。

+0

ありがとうございます。つまり、子カテゴリがある限り、親カテゴリを取り、すべての子を挿入する関数を再帰的に呼び出す必要がありますか?しかし興味深いことに、T-SQLの再帰的なCTEのようなすべてのレベルを与えるLINQソリューションはありませんか? –

+0

いいえ、ありませんと思います。あなたは、ストアドプロシージャをセットアップし、サーバー上で再帰的な処理を行うためにそれを呼び出すでしょう。 – Tridus

関連する問題