1

マルチルックアップ値のいずれかが別のクエリの結果に含まれているリストのアイテムを取得しようとしています。

状況は次のとおりです。ユーザーが 5 つのプロパティ ドロップダウンの一連の共有ポイント (Foundation 2010) リストを使用してレポート (「融合」) を作成できる Web パーツを構築しています。プロパティは、リスト内のルックアップを通じて接続されます。ドロップダウンの選択が変更されるたびに、ポストバックが発生し、次のドロップダウンが再入力されます。

問題は、プロパティ間の接続がドロップダウンと単純に一致しないことです。これは、ドロップダウン入力がレポートの直感的な入力用に選択されており、データモデルが効率的で簡単なプログラミング用ではなく、システム データの簡単で直感的な入力用に設計されているためです...

データ モデルの関連部分:
-場所 (場所) はリストです
-契約 (契約) はリストで、各契約には 1 つ以上の場所があります (マルチルックアップ)
-緊急 (緊急) はリストで、各緊急事態には 1 つの契約があります(ルックアップ)
-Meldingtypes (レポートタイプ) はリスト
です -Categoriën (カテゴリ) はリストです。各カテゴリには 1 つの meldingtype があり (ルックアップ)、各カテゴリには 1 つ以上のコントラクトがあります (マルチルックアップ)

レポートの入力は次のとおりです。
ユーザーは最初に Locatie を選択し
ます ユーザーは 2 番目に Meldingtypeを選択し
ます ユーザーは 3 番目に Category を選択します ユーザー
は 4 番目に Contract
を選択します 最後にユーザーは Urgentie を選択します

もちろん、ドロップダウンには有効なオプションのみを入力する必要があります。したがって、場所が選択されると、ドロップダウンに表示される唯一のメルディングタイプは、選択された場所を持つ契約を持つカテゴリを持つものでなければなりません...ええ、私は知っています;)

ドロップダウンに入力するためのクエリの作成に問題があります。複数のクエリ、Contains セレクターを使用した構造など、いくつかの方法を試してきましたが、どれも機能しませんでした。最後の繰り返しで、アイテムがマルチルックアップによって参照されるときにアイテムが持つプロパティを使用するクエリを作成しました。以下は、meldingtype ドロップダウンの例です。

    private void fillMeldingtypeDropdown(Intermediair.IntermediairDataContext idctx)
    {
        var meldingtypeData = (from l in idctx.Locaties
                               from co in l.ContractenItem
                               from ca in co.CategorieënItem
                               where l.Id == selectedLocatieId
                               select ca.Meldingtype
                              ).Distinct<Intermediair.Item>();
        foreach (Intermediair.Item meldingtype in meldingtypeData)
        {
            ctrl_Meldingtype.Items.Add(new ListItem(meldingtype.Titel, meldingtype.Id.ToString()));
        }
    }

selectedLocatieId は、Locatie ドロップダウン コントロールから値を取得するプロパティです。

上記のコードは、System.InvalidOperationException をスローします。エラーの説明はオランダ語で、翻訳すると次のようになります。

EntitySet.Contains を使用すると、同じエラーが発生します。

    private void fillCategorieDropdown(Intermediair.IntermediairDataContext idctx)
    {
        var contractenData = from c in idctx.Contracten
                             where c.LocatieS.Contains( 
                                 (  from l in idctx.Locaties 
                                    where l.Id == selectedLocatieId 
                                    select l
                                 ).First<Intermediair.LocatiesItem>() 
                             )
                             select c;
        var categorieenData = ( from ca in idctx.Categorieën
                                from co in contractenData
                                where ca.Contract.Contains(co) && ca.Meldingtype.Id == selectedMeldingtypeId
                                select ca
                              ).Distinct<Intermediair.CategorieënItem>();
        foreach (var categorie in categorieenData)
        {
            ctrl_Categorie.Items.Add(new ListItem(categorie.Titel, categorie.Id.ToString()));
        }
    }

いくつかの順列を試しましたが、正しいものが見つからないようです。マルチルックアップ フィールドを使用した linq-to-sharepoint クエリの良い例を見つけることができません。また、linq にまだ十分に慣れていないため、市長の間違いを犯している可能性があります。私がこれを理解している間、私は本当に役立つアイデアをいただければ幸いです。

[編集:別の試行が失敗しました] 中間結果を確認するために、すべてのステップの個別のクエリを作成しようとしました。また、Any-Contains の組み合わせを試して、categorie のマルチルックアップ コントラクトと、その場所から取得した複数のコントラクトを照合しました。

        var locatieItem = (from l in idctx.Locaties
                           where l.Id == selectedLocatieId
                           select l
                          ).First();
        var contractenData = from c in locatieItem.ContractenItem
                             select c;
        var categorieenData = from c in idctx.Categorieën
                              where c.Contract.Any(co => contractenData.Contains(co))
                              select c;
        var meldingtypeData = (from c in categorieenData
                               select c.Meldingtype
                              ).Distinct();
        foreach (var meldingtype in meldingtypeData)
        {
            ctrl_Meldingtype.Items.Add(new ListItem(meldingtype.Titel, meldingtype.Id.ToString()));
        }

locatieItem と contractenData は期待どおりに入力されますが、categorieenData は再び同じエラーを生成します。[/編集]

PS コード内のオランダ語の名前は英語で非常に読みやすいため、名前を翻訳していません。混乱させて申し訳ありません。

4

2 に答える 2

0

SharePoint 2010 の linq にはいくつかの制限があります。おそらく、この記事で正しい方向に進むことができます: http://www.chaholl.com/archive/2010/03/12/joins-in-linq-to-sharepoint-2010 .aspx

于 2011-02-21T14:58:51.907 に答える
0

私は問題を解決しました。データベースから取得されるレコードが多すぎるため、多少のオーバーヘッドが生じます。ただし、重複のみであるため、キャッシュによってそのオーバーヘッドのほとんどが解決されることを願っています。

私が現在使用しているクエリは、非常に単純です。

        var categorieenContractenData = from c in contractenData
                                        select c.CategorieënItem;

これにより、CategoryItems の 1 つのセットが得られるのではなく、CategoryItems のセットのセットが得られます。その一部は重複している可能性があります。次に、2 つの foreach ループを使用して各エントリをループし、簡単に取得できるように項目を 3 つのデータ構造に配置します。これは、3 つのドロップダウンのそれぞれを満たすために、linq-query を 1 回実行するだけでよいことを意味します。

週末までに実際のデータがデータベースにあることを期待しているので、それが十分に速いかどうかをテストします。そうでない場合は、追加のリストを作成する必要があります (イベントレシーバーで埋められます)。

完全なコード:

    private void ensureLoadData(Intermediair.IntermediairDataContext idctx)
    {
        if (dataLoaded) return;

        meldingtypes = new SortedList<string, int?>();
        categorieen = new SortedList<int?,SortedList<string,int?>>();
        contracten = new SortedList<int?, SortedList<int?, SortedList<string, int?>>>();
        IQueryable<Intermediair.ContractenItem> contractenData = from c in
                                                                     (from l in idctx.Locaties
                                                                      where l.Id == selectedLocatieId
                                                                      select l
                                                                     ).SingleOrDefault().ContractenItem
                                                                 select c;
        var categorieenContractenData = from c in contractenData
                                        select c.CategorieënItem;
        foreach (EntitySet<Intermediair.CategorieënItem> categorieenPerContract in categorieenContractenData)
        {
            foreach (Intermediair.CategorieënItem categorie in categorieenPerContract)
            {
                if (!meldingtypes.ContainsKey(categorie.Meldingtype.Titel))
                {
                    meldingtypes.Add(categorie.Meldingtype.Titel, categorie.Meldingtype.Id);
                    categorieen.Add(categorie.Meldingtype.Id, new SortedList<string,int?>());
                    contracten.Add(categorie.Meldingtype.Id, new SortedList<int?, SortedList<string, int?>>());
                }
                if (!categorieen[categorie.Meldingtype.Id].ContainsKey(categorie.Titel))
                {
                    categorieen[categorie.Meldingtype.Id].Add(categorie.Titel, categorie.Id);
                    contracten[categorie.Meldingtype.Id].Add(categorie.Id, new SortedList<string,int?>());
                    foreach (Intermediair.ContractenItem contract in categorie.Contract)
                    {
                        contracten[categorie.Meldingtype.Id][categorie.Id].Add(contract.Titel, contract.Id);
                    }
                }
            }
        }
        dataLoaded = true;
    }
于 2011-03-01T11:19:46.543 に答える