0

2 つのテーブルを含む linq-to-sql データ レイヤーがあります。"親子"。子と親の間には関係があり (親には多くの子供がいるなど)、親も多くの親を持つことができます (子供が成長して自分自身が親になるとき)。

この階層をユーザーに表示したいのですが、これを効率的に行う方法がわかりません。

非効率的なアプローチは次のとおりです。

foreach(Parent in db.Parents)
{
    output(Parent.Parents)
    output(Parent.Children)
}

しかし、これはループ内の反復ごとに db 往復を 2 回生成します (eek!!)。大規模なファミリの場合、これは非常に高価になります。

より良い方法はありますか?(神よ、そう願っています!)

4

1 に答える 1

1

UI に渡したいコレクション全体を熱心に読み込むことをお勧めします。親 -> 親コレクションを生成する方法が再帰的である場合 (そう思われるかもしれません)、L2S コードを使用して項目を再帰的に選択します。このようにして、UI で結果の最終的なコレクションを反復しても、SQL コマンドが非効率的にトリガーされることはありません。

例:
これが最善/最短/クリーンな方法かどうかはわかりませんが、うまくいけばアイデアが得られます。static機能はコンソールアプリです。

class Program
{
    static void Main(string[] args)
    {
        foreach (ParentDTO p in GetParents().ToList())
        {
            if (p.Parent == null)
                Console.WriteLine(String.Format("{0} ({1})",
                    p.Name, p.ID.ToString()));
            else
                Console.WriteLine(String.Format("{0} ({1}){2}",
                    p.Name, p.ID.ToString(), "\r\n\t-" + p.Parent.Name));
        }

        Console.ReadKey();
    }

    private static IQueryable<ParentDTO> GetParents()
    {
        var db = new DataClasses1DataContext();
        db.Log = new DebuggerWriter();

        return from p in db.Parents
               let parentParent = GetParentOfParent(p.ParentID)
               select new ParentDTO
               {
                   ID = p.ID,
                   Name = p.Name,
                   Parent = parentParent
               };
    }

    private static ParentDTO GetParentOfParent(int? childParentID)
    {
        if (childParentID.HasValue)
            return GetParents().Single(p => p.ID == childParentID);
        else
            return null;
    }
}

表データ:

ID ParentID Name
1 NULL Bill
2 8 Mary
3 1 Gary
4 1 Milla
5 NULL Sue
6 NULL Fred
7 NULL Marg
8 7 Hillary

出力:

ビル (1)
メアリー (2)
-ヒラリー
ゲイリー (3)
-ビル
ミラ (4)
-ビル
スー (5)
フレッド (6)
マーグ (7)
ヒラリー (8)
-マーグ

(インデント/ハイフン付きの名前はそれぞれの親です)

これは、L2S dc からのデバッガ出力Logです。

SELECT [t0].[ID], [t0].[ParentID], [t0].[Name]
FROM [dbo].[Parent] AS [t0]
WHERE ([t0].[ID]) = @p0
- - @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [8]
-- コンテキスト: SqlProvider(Sql2005) モデル: AttributedMetaModel ビルド: 3.5.30729.1

SELECT [t0].[ID], [t0].[ParentID], [t0].[Name]
FROM [dbo].[Parent] AS [t0]
WHERE ([t0].[ID]) = @p0
- - @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [7]
-- コンテキスト: SqlProvider(Sql2005) モデル: AttributedMetaModel ビルド: 3.5.30729.1

SELECT [t0].[ID], [t0].[ParentID], [t0].[Name]
FROM [dbo].[Parent] AS [t0]
WHERE ([t0].[ID]) = @p0
- - @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [1]
-- コンテキスト: SqlProvider(Sql2005) モデル: AttributedMetaModel ビルド: 3.5.30729.1

SELECT [t0].[ID], [t0].[ParentID], [t0].[Name]
FROM [dbo].[Parent] AS [t0]
WHERE ([t0].[ID]) = @p0
- - @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [1]
-- コンテキスト: SqlProvider(Sql2005) モデル: AttributedMetaModel ビルド: 3.5.30729.1

SELECT [t0].[ID], [t0].[ParentID], [t0].[Name]
FROM [dbo].[Parent] AS [t0]
WHERE ([t0].[ID]) = @p0
- - @p0: Input Int (Size = 0; Prec = 0; Scale = 0) [7]
-- コンテキスト: SqlProvider(Sql2005) モデル: AttributedMetaModel ビルド: 3.5.30729.1

..すべてが一斉に発射されました.ToList();(予想どおり)。

これが役に立つことを願っています。

于 2009-12-12T08:47:51.297 に答える