4

背景(つまり、相対補完とは一体何ですか?)

相対補体

私がやろうとしていること

「車」または「トラック」のいずれかのオプション セットを持つカスタムVehicleエンティティがあるとします。VehicleTypeContact と Vehicle の間には 1 対多の関係があります (つまり、ContactId は vehicle エンティティにあります)。車のみの連絡先を返す XRM クエリ (Linq To CRM、QueryExpression、fetch Xml など) を作成するにはどうすればよいですか?

相対補数ベン図

4

4 に答える 4

1

オプション1:

上記の AdamV の提案を修正した方がよいと思います。Linq to CRM、Query Expressions、FetchXML だけを使用して、この特定のクエリに回答する方法が思い浮かびません。Daryl はクライアントが何であるかを提供していませんが、Linq と Query Expressions が受け入れ可能な製品であるとすれば、.NET がテーブルにあると思います。親エンティティ (この場合は連絡先) の関連エンティティの数を含む集計フィールドを作成すると、ブール オプション以上のものが提供されます。クエリ要件がしきい値 (X 台以上、Y 台未満、合計 X 台と Y 台の間) に変更された場合、ブール値のオプションは配信に失敗します。この質問のクライアントは不明ですが、

利点:

  1. クエリアプローチでクライアントの純度を維持
  2. シンプルなクライアント クエリ
  3. おそらく可能な限りのパフォーマンス

欠点:

  1. 集計フィールドの設定
  2. 集計フィールドの増減を管理するためのワークフローまたはプラグイン
  3. 集計の初期ロード用の SQL スクリプト。
  4. 集計フィールドが同期しなくなるリスク (ワークフローまたはプラグインの失敗)

オプション 2:

クライアント内の純度が必須ではなく、.NET がテーブルにある場合は、集計フィールドとセットアップをスキップして、ビューに対して SQL を実行するだけです。ADO.NET を使用したくない場合でも、Dapper、Massive、PetaPOCO などのシン ORM でオブジェクト モデルを提供できます。Andreas が OP の最初の回答に関するコメントで提供しているように、SQL で行うのはかなり簡単なことのように思えます。

頭の中で何かをスケッチする:

SELECT c.*
FROM Contact 
WHERE C.Contactid in (
    Select contactid 
    FROM Vehicle v 
    group by v.contactid , v.type
    having v.type = ‘Car’ and count(contactid) > 1 
) 
AND NOT IN (
    Select contactid 
    FROM Vehicle v 
    group by v.contactid , v.type
    having v.type <> ‘Car’ and count(contactid) > 1 
)

利点:

  1. はるかに少ない仕事
  2. CRMエンティティは放っておかれます

欠点:

  1. クライアントやアプリケーションによっては、DataAccess メソッドを混在させるのは少し面倒です。
  2. オプション 1 よりもパフォーマンスが低い可能性が高い

オプション 3:

組み合わせ: オプション 1 から集計フィールドを取得します。ただし、オプション 1 で記述する必要がある初期ロード ジョブと同様のクエリを使用して、スケジュールされた SQL ジョブ (または同様のもの) を使用してそれらを更新します。

利点:

  1. オプション 1 からほとんどの作業とリスクを取り除く
  2. オプション 1 のすべてのパフォーマンスを保持

欠点:

  1. これをサポートされていない機能と見なす人もいます。
于 2013-01-15T22:56:11.823 に答える
1

真の相対補完クエリを実行するには、サブクエリを実行できる必要があります。

あなたのクエリは基本的に、車に関するすべての連絡先を教えてください、そして、それらの結果から、車以外の車両を持つ連絡先をすべて削除します。これは、@JasonKoopmansの回答のSQLが行うことです。残念ながら、CRM は SubQueries をサポートしていません

したがって、これを達成する唯一の方法は、クライアント側でサブクエリを実行するか、メインクエリを介してアクセスできる方法でサブクエリとなるものの結果を保存することです (つまり、連絡先エンティティにカウントされます)。

、およびSubQueryResultを格納するエンティティを作成することにより、理論的にはこれを「その場で」行うことができます。まず、少なくとも 1 台の車がある連絡先を取得し、各レコードに対して、contactId と、それらをすべて結び付けるためにクライアント側で生成された単一の SubQueryId を使用して SubQueryResult レコードを作成します。 ContactIdSubQueryId

次に、この SubQueryId を持つこの SubQueryResult にあるすべての連絡先を教えてくれるという別のクエリを実行します。この連絡先には車以外の車両はありません。

これは、2 つの個別のクエリを実行し、クライアント側でフィルターを実行するよりも効率的ではないとしか思えませんでした。新しい CRM リリースの新しい ExecuteMultipleRequests では、近いかもしれません。

于 2013-01-17T17:02:03.303 に答える
0

CRM 2011 はクエリ式を介してこれをサポートしていないため、CRM のすべてのレコードを引き戻し、クライアント側でチェックを実行することにしました。

2 つの Fetch XML ステートメントを記述できます。1 つはすべての連絡先とその車両の数を返し、もう 1 つはすべての連絡先とその車の数を返し、クライアント側でリストを比較します。ただし、ここでも、すべての連絡先を返し、クライアント側でフィルター処理する必要があります。

于 2012-12-07T22:11:22.070 に答える
0

テストしていませんが、このクエリ式はどうですか? Vehicleエンティティを内部結合としてリンクしているため、 Carである必要があります。私は少し怠け者でテストしたくないので、フィールドVehicleType文字列であると想定しています (私はこの筋金入りのスタイルを入力しています。コンパイルは必要ありません - 純粋な脳の作業です)。

必要に応じて、 Criteriaセクションを追加して、実際に取得するContactインスタンスを制御することもできます。それがどうだったか教えてください!

冗長で申し訳ありません。私はあなたがそれが短いのが好きであることを知っています. 循環器系のとき、私の脳はよりよく機能します。

new QueryExpression
{
  EntityName = "contact",
  ColumnSet = new ColumnSet("fullname"),
  LinkEntities =
  {
    new LinkEntity 
    { 
      JoinOperator = JoinOperator.Inner, 
      LinkFromEntityName = "contact", 
      LinkFromAttributeName = "contactid", 
      LinkToEntityName = "vehicle", 
      LinkToAttributeName = "contactid",
      Columns = new ColumnSet("vehicletype"),
      EntityAlias = "Vroom",
      //LinkCriteria = { Conditions = 
      //{
      //  new ConditionExpression(
      //    "vehicletype", ConditionOperator.Equal, "car")
      //} }
      LinkCriteria = { Conditions = 
      {
        new ConditionExpression(
          "vehicletype", ConditionOperator.NotEqual, "truck") 
      } }
    } 
  }
};

編集:

MVP の Gustaf Westerlund と話をしたところ、次の回避策が提案されました。元の質問に対する答えではないことを強調させてください。それを解決する方法にすぎません。そして、それは面倒です。:)

したがって、ヒントはContactまたはPersonエンティティにフラグを追加することです。次に、 Vehicleの新しいインスタンスを作成するたびに、メッセージを起動し、プラグインを使用して、後者の作成に関する最初の情報を更新する必要があります。

これにはいくつかの欠点があります。

  1. それは私たちが何かをすることを必要とします。
  2. それは単純なやり方ではありません。
  3. 新しいタイプの車両を追加するたびに、維持費が高くなります。
  4. 考慮すべきケースが多いため、バグの可能性が高くなります ( Vehicleインスタンスが再署名、削除されたときにフラグ化がどうなるかなど)。

したがって、あなたの質問に対する私の答えは、「できません」に変更されます。これは、提示された代替ソリューションによって(喜んで)間違っていることが証明されるまで有効です。アヒル!

個人的には、(ほとんど) すべてをフェッチし、そこに LINQ の猟犬を解き放ちます。しかし、私は笑顔や誇りを持たずにそれを行います. :)

于 2013-01-16T07:26:30.250 に答える