2

まず、動的 where 句、ScottGu のブログ、Albahari の PredicateBuilder クラスに関する多くのスレッドを検索して読みましたが、これらのメソッドを正しく適用する方法がわかりません。私の場合。どういうわけか、私はそれについて頭を包むことができません。

次のコードがあります。これは、次のように「静的に」実行すると機能します。

var persons = from father in fathers
              select new                                
              {
                 Count = father.Sons
                                    .Select(son => son)
                                    .Where(son => son.Skills.Any(skill => skill.SkillType == "Languages" && skill.Name == "French"))
                                    .Where(son => son.Skills.Any(skill => skill.SkillType == "Sport" && skill.Name == "Football"))
                                    .Count(),

                 Name = father.Name
               };

ただし、実行時に where 句を生成したいと考えています。親オブジェクトには Son オブジェクトのコレクションがあり、さらに Son オブジェクトのコレクションには Skills オブジェクトのコレクションがあります。クエリが示すように、私は各父親の名前と、特定のスキル セットを持つ息子の数を知りたいと考えています。スキルのセットは実行時に選択されるため、この例ではスキルのセットが 2 つ (2 つの where 句) しかありませんが、実行時に 10 個または任意の数の句になる可能性があります。

私の最大の問題は、トップ レベル (父) からの情報だけでなく、第 3 レベル (スキル)第2レベル(息子)の情報に関するもの。

必要に応じて、明日試したことのサンプル コードを投稿します。ちょっと急いでいるので、今はできません。どんな助けでも大歓迎です。

編集:

必要なのは、ユーザーが選択したフィルター条件の数に応じて、実行時に where 句を連結する方法です。さまざまなフィルター条件が外部ソースから取得され、実行時に構築されます。たとえば、次のようになります。

シナリオ 1 では、ユーザーによって選択される 3 つの基準、たとえば、基準 1、基準 2、および基準 3 が存在する可能性があります。シナリオ 2 には、基準 1、基準 2、...、基準 5 などの 5 つの基準があります。3 番目のシナリオでは、10 個の基準 (たとえば、基準 1、基準 2、...、基準 10) を持つことができます。私が必要としているのは、3、5、10、またはその他の基準があるかどうかを事前に知らなくても、シナリオごとに次のことを実行できることです。

シナリオ 1:

var persons = from father in fathers
              select new                                
              {
                 Count = father.Sons
                                    .Select(son => son)
                                    .Where(criteria1)
                                    .Where(criteria2)
                                    .Where(criteria3)
                                    .Count(),

                 Name = father.Name
               };

シナリオ 2:

var persons = from father in fathers
              select new                                
              {
                 Count = father.Sons
                                    .Select(son => son)
                                    .Where(criteria1)
                                    .Where(criteria2)
                                    .Where(criteria3)
                                    .Where(criteria4)
                                    .Where(criteria5)
                                    .Count(),

                 Name = father.Name
               };

シナリオ 3:

var persons = from father in fathers
                  select new                                
                  {
                     Count = father.Sons
                                        .Select(son => son)
                                      .Where(criteria1)
                      .Where(criteria2)
                      .Where(criteria3)
                      .Where(criteria4)
                      .Where(criteria5)                   
                      .Where(criteria6)
                      .Where(criteria7)
                      .Where(criteria8)
                      .Where(criteria9)
                      .Where(criteria10)
                                  .Count(),
                     Name = father.Name
                   };
4

3 に答える 3

2

jonnyGold による回答は適切ですが、Son オブジェクトが父オブジェクトへの参照を持つ必要があります。それを必要としない解決策は次のとおりです。

var query = from father in fathers
            from son in father.Sons
            select new {father, son};

foreach (Skill skillCriterion in CriterionSkills)
{
    var capturedSkillCriterion = skillCriterion;
    query = query.Where(fs => fs.son.Skills.Any(
        skill => skill.SkillType == capturedSkillCriterion.SkillType && 
                 skill.Name == capturedSkillCriterion.Name));         
}         

var persons = from fs in query
              group fs by fs.father into g 
              select new                                 
              { 
                 Count = g.Count(),
                 Name = g.Key.Name
              };
于 2012-06-08T11:32:12.487 に答える
1
var sons = fathers.SelectMany(f => f.Sons);

foreach(Skill skillCriterion in CriterionSkills)
{
    sons = sons.Where(son => son.Skills.Any(skill => skill.SkillType == skillCriterion.SkillType && skill.Name == skillCriterion.Name));
}

// we need to assume some sort of formal father-son relationship
var persons = from son in sons
              group son by new {son.Father.ID, son.Father.Name} into g
              select new
              {
                g.Key.Name,
                g.Count()
              };
于 2012-06-07T16:23:57.147 に答える
0

次に、フィルターの動的な性質を処理するクエリを設計します。たとえば、息子がサッカーやバレーボールをすることができる父と息子を作成しました。今、私のクエリは、サッカーだけの動的なリクエストを受け取ります...これが私のやり方です:

void Main()
{
   bool findFootballers   = true;
   bool findVolleyBallers = false;

   var Fathers = new List<Father>()
   {
      new Father() { Name = "Frank SR", Sons = new List<Son>() { new Son() { Name = "Bob", PlaysFootball = true }, new Son() { Name = "Frank", PlaysVolleyBall = true } } },
      new Father() { Name = "Knute", Sons = new List<Son>() { new Son() { Name = "Mean Jo Green", PlaysFootball = true }, new Son() { Name = "McMann", PlaysFootball = true } } }
   };


   Fathers.Where (f => (findFootballers == false) ? true : f.Sons.Any (s => s.PlaysFootball == true))
          .Where (f => (findVolleyBallers == false) ? true : f.Sons.Any (s => s.PlaysVolleyBall == true))
          .Select( f => new
                       {
                       Name = f.Name,
                       TargetSportSons = string.Join(", ", f.Sons
                                                            .Where (s => (findFootballers == false) ? true : s.PlaysFootball)
                                                            .Where (s => (findVolleyBallers == false) ? true : s.PlaysVolleyBall)
                                                            .Select (s => s.Name))
                       }
                 )
            .ToList()
            .ForEach(fs => Console.WriteLine ("Father {0} has these sons {1} who play {2}", fs.Name, fs.TargetSportSons, (findFootballers ? "Football" : "VolleyBall ")));

// Output
// Father Frank SR has these sons Bob who play Football
// Father Knute has these sons Mean Jo Green, McMann who play Football

}

public class Son
{
   public string Name { get; set; }
   public bool PlaysFootball { get; set; }
   public bool PlaysVolleyBall { get; set;}
}


public class Father
{
   public string Name { get; set; }
   public List<Son> Sons = new List<Son>();

}

// Define other methods and classes here
于 2012-06-07T16:46:29.320 に答える