0

私は3つのNHibernateエンティティを持っています

Division
{
  Id (PK),
  Name
}

District
{
  Id (PK),
  Name
}

Doctor
{
  Id (PK),
  Name,
  Division,
  District
}

部門地区で医師のフィルタリングを取得したい。

たとえば、ユーザーが選択した部門があり、この部門の下に医師が必要だとします。

最初の方法:

var doctors = doctorRepository
    .FilterBy(x => x.Division.Id == selectedDivision.Id)
    .ToList();

第二の方法:

var doctors = doctorRepository
    .FilterBy(x => x.Division == selectedDivision)
    .ToList();

私の最初の質問は、パフォーマンスを考慮した最善の方法はどれですか?

両方のクエリについて sql プロファイラーをチェックしました。最初のクエリでは、生成された SQL に分割テーブルを使用した左外部結合が含まれています。DivisionId が Doctor テーブルに存在するため、Division テーブルと結合する必要がある理由がわかりません。この余分な結合はパフォーマンスを低下させますか?

2 番目の質問: Division と District を使用して Doctor リポジトリからクエリを実行したい場合、 Division と District の両方が null になることがあります。この場合、NHibernate Linq でこのクエリをどのように記述すればよいですか?

4

1 に答える 1

1

最初のクエリでは、生成された SQL に分割テーブルを使用した左外部結合が含まれています。DivisionId が Doctor テーブルに存在するため、Division テーブルと結合する必要がある理由がわかりません。この余分な結合はパフォーマンスを低下させますか?

厳密には必要ないかもしれませんが、おそらく、この詳細が NHibernate Linq プロバイダーによって最適化されていないだけです。データベース エンジンが、最適化して取り除くことができることを認識しない限り (SQL の実行計画を見てください)、パフォーマンスに影響します。一般的なケースではどの程度かはわかりません。

2 番目の質問: Division と District を使用して Doctor リポジトリからクエリを実行したい場合、 Division と District の両方が null になることがあります。この場合、NHibernate Linq でこのクエリをどのように記述すればよいですか?

次のようなクエリを検討してください。

var doctors = doctorRepository
    .FilterBy(x => x.Division.Id == selectedDivision.Id)
    .ToList();

Linq2NH で実行すると、SQL に変換されます。x.Division が NULL の場合、式は .NET で逆参照されないため、問題は発生しません。NHibernate が selectedDivision を逆参照しようとする (NRE を引き起こす) のか、それともNULL のselectedDivision.Id場合に NULLに変換するのに十分賢いのかどうかはわかりませんselectedDivision。それを試してみてください!それ以外の場合、より安全な方法は次のように書くことです:

int? divId = selectedDivision != null ? selectedDivision.Id : (int?)null;
var doctors = doctorRepository
    .FilterBy(x => x.Division.Id == divId)
    .ToList();

NHibernate は、divId が null の場合に SQL で IS NULL を生成するほどスマートです。

フィルターを回避するための指示としての null

私は通常、次のようなパターンを使用します。

var queryable = GetMyBaseQueryable<Doctor>();

if (divisionFilter != null)
    queryable = queryable.Where(x => x.Division.Id == divisionFilter.Id)

if (districtIdFilter != null)    // districtIdFilter is some collection
    queryable = queryable.Where(x => districtIdFilter.Contains(x.District.Id))

var result = queryable.ToList();
于 2013-02-13T18:30:28.000 に答える