2009-05-27 8 views
2

このシナリオは、LinkToSqlとそれが作成するクラスを使用するようになりました。LinqToSql - データベースへの過度のクエリを避ける

クラシックシナリオ - 二つのテーブル:

メンバー
ID
名前
...

会員
ID
MEMBERID(外部キー)
スタート(日時)
有効期限(日時)
...

有効なメンバーシップは、開始と有効期限の間にあるものです。

ユーザーがアクティブなメンバーシップを持っているかどうかを調べるために、私はLinkToSql-生成されたメンバークラスに拡張するために、この部分クラスを作成しました:

Partial Public Class Member 
    Public ReadOnly Property HasActiveMembership() As Boolean 
     Get 
      Dim activeMembershipCount As Integer = (From m In Me.Memberships _ 
           Where m.MemberId = Me.MemberId _ 
           And m.StartDate < Now And m.ExpirationDate > Now() _ 
           Select m).Count 

      If activeMembershipCount > 0 Then Return True Else Return False 

     End Get 
    End Property 
End Class 

これは、1人のメンバーのための素晴らしい作品が、私はしたいとき700人のメンバーをリストアップし、彼らがアクティブなメンバーシップを持っているかどうかを判断すると、データベースへの700回以上の呼び出しを行います。

モデル/クラスを変更するにはどうすればよいですか?

私は、リスト全体のクエリーを1つのクエリーにすることができますが、これはかなり簡単ですが、できればそれを避けたいと思います。

答えて

2

いくつかのオプションがあります。たとえば、DataLoadOptions.LoadWithまたはDataLoadOptions.AssociateWithを使用してデータを熱心に取り出すことができますが、最適な方法は使用方法によって異なります。

たとえば、「アクティブメンバーシップを持つユーザー」クエリ(LINQでAnyを使用するか、SPROC/UDFを使用)を作成できます。それは1回の往復ですが、おそらくオブジェクト指向ではなく(よりクエリ中心です)。これはうまくいくかもしれません...

0

おそらく、テーブル間のFK関係のために、関連付けが定義されているようです。その場合、すでにクラスで定義されているエンティティ参照を使用してwhere句を使用して、メンバーシップクエリを単純に拡張することができます。

C#の例: - 彼らは実際にアクティブなメンバーシップを持っている場合は、真/偽の私が探しています何

var query = db.Members.Where(m => m.Memberships 
            .Any(ms => ms.StartDate > now 
               && ms.ExpirationDate < now)); 
+0

は、すべてのメンバーを表示する方法です。実際のアクティブメンバーシップを持つメンバーだけではありません。 :) – Kjensen

+0

DataLoadOptionsに関して@ Marcの答えを見てください。データが遅延ロードされていない場合、Membershipsに対するクエリはデータベースに対して返されません。これはLinqToObjectsになります。おそらくカウントを計算する代わりにAny()を使うべきでしょう。 LinqToObjectsで、最初のものが見つかった後に短絡することが予想されます。数えればすべてを調べる必要があります。おそらく小さなパフォーマンス上の利点ですが、その正しい使用方法です。 – tvanfosson

+0

短絡よりも優れています。多くの場合、実際にそれらをすべて取得するのではなく、EXISTS/COUNT/TOP 1などを使用します(どちらが覚えていないか)。 –

関連する問題