2

ユーザー定義のフィルター条件に従って、データベース内の人物をリストするレポートを作成しています。たとえば、名前や年齢などでフィルタリングできます。

var people = db.People.AsQueryable();
if (filterByName)
  people = people.Where(p => p.LastName.Contains(nameFilter));
if (filterByAge)
  people = people.Where(p => p.Age == age);

現在、フィルター条件の 1 つは、必要な予防接種を受けていない人を表示することです。と のテーブルがImmunizationありPersonImmunizationます ( に一意のインデックスがありますPersonID, ImmunizationID)。誰かがPersonImmunization記録に欠けている場合、または受けた投与回数が要件を下回っている場合は、それらを含める必要があります。そうでない場合は含めないでください。

SQL クエリを作成する場合、次のようになります。

select p.*
from Person p
cross join Immunization i
left join PersonImmunization pi 
  on pi.PersonID = p.ID and pi.ImmunizationID = i.ID
where pi.ID is null or pi.Doses < i.RequiredDoses;

where句のこの部分を作成するには、Expression述語を使用してこれを表現する必要があります。

if (filterByImmunizations) {
  Expression<Func<Person, bool>> nonCompliantImmunization = 
    person => <now what?>;
  people = people.Where(nonCompliantImmunization);
}

最初の問題は、予防接種を式に組み込む方法です。次に、それを入手したら、コンプライアンス違反者を見つける方が簡単かもしれないと思いますが、それを回答に含めていただければ幸いです!

編集 : Expression<Func<Person, bool>>. その理由は、いくつかの異なるコンテキストで、複雑なユーザー定義クエリを作成するための汎用フレームワーク全体を構築したためです。エンジンの内部を理解するために、基本クラスの内部のスニペットを次に示します。

public abstract class QueryBuilder<T> where T : EntityObject {

  public static IQueryable<T> FilterQuery(IQueryable<T> query, IEnumerable<QueryConditionLite> filters, bool anyConditionSufficient) {
    ...
  }

  protected Expression<Func<TBase, bool>> GetPredicate(Expression<Func<TBase, double>> expression, IQueryCondition condition) { 
    ... 
  }
}

次に、 がありPersonQueryBuilder : QueryBuilder<Person>、その中で、予防接種の要件に準拠していない人々を表示するフィルターを作成したいと考えています。クエリ構文だけではうまくいかないことに同意していただけると思います。

4

2 に答える 2

2

マルチパート結合としてアプローチします。

var nonCompiantImmunization =
  from p in Persons
  from i in Immunizations
  let pi = PersonImmunizations.Where(x =>
    x.ImmunizationID == i.ID && x.PersonID == p.ID)
  where !pi.Any() || pi.Sum(x => x.Doses) < i.RequiredDoses
  select new { p, i };

編集:制約に適合させるために、次のExpression<Func<Person, bool>>ように言い換えることができると思います:

Expression<Func<Person, bool>> nonCompliantImmunization = 
  person => (
      from i in Immunizations
      let pi = PersonImmunizations.Where(x =>
        x.ImmunizationID == i.ID && x.PersonID == person.ID)
      where !pi.Any() || pi.Sum(x => x.Doses) < i.RequiredDoses
      select true
    ).Any();
于 2013-08-05T15:59:54.163 に答える