1

CategorypkidCategoryと自己参照外部キーを含むテーブルがありますfiCategory。つまり、。の場合、カテゴリは「メインカテゴリ」 fiCategory is nullです。別のカテゴリにリンクしている場合fiCategory、それはそのサブカテゴリです。ただし、このサブカテゴリにも1-n個のサブカテゴリがあることも有効です(fiCategoryそれにリンクしていidCategoryます)。

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

背景

型指定されたDataSetを使用して、Server1/MySQLのデータをServer2/MSSQL-Serverのデータと比較しています。正規化とクリーニング(いくつかの不整合があります)の後、新しいデータをSQL-Serverにインポートしたいと思います。まず、メインカテゴリをインポートし、次にサブカテゴリをインポートする必要があります。そうしないと、SQL-Serverは、まだ挿入されていないカテゴリに外部キーを含む行を挿入しようとすると、制約例外をスローします。

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

Kategorie:MySQL-ソース カテゴリ:SQL-Serverの宛先

ここでは、SQL-ServerにないMySQLの新しい行を取得しています。

srcdestは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
4

1 に答える 1

2

はい、外部キー制約を一時的に無効にすることができます

これを行うための最良の方法(外部キーを無効にして、テーブル全体を行ごとにコピーする以外)は、メインのカテゴリから再帰的に開始することです。概念的には、これを行います。

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.

など。現在持っているカテゴリのサブカテゴリを簡単に取得できるので、一番上から始めれば、ツリー全体を歩き、反対側に欠けているものを追加できます。

于 2011-07-19T22:46:16.960 に答える