30

まず、この質問をするためにどの用語を使用すればよいかわからないため、自分自身を検索しても答えが見つからなかったのかもしれません。

そこで、Linq to SQL(C#、. Net 4)を使用しており、基準に一致するすべてのユーザーのリストを取得したいと考えています。その基本は次のようになります。

var users = DataContext.Users.Where(x => x.Criteria1 == "something");

しかし、この場合、一致させたいフィールドがいくつかあります。これらの特定のフィールドは一般的なチェックであり、ユーザークエリ内でこれをチェックするために使用できる専用関数を作成できるようにしたいと思います。マッチ。

もう少し良いことを説明するために、例を挙げましょう。ユーザーに5つのフラグがあり、それらのフラグのいずれかが設定されているかどうかを確認するための一般的なチェックが必要だとします。したがって、次のようにクエリを記述できます。

var users = DataContext.Users.Where(x => x.Flag1 || x.Flag2 || x.Flag3 || x.Flag4 || x.Flag5);

しかし、私がやりたいのは、その「5フラグチェック」を分離して、他のクエリでも使用できるようにすることです。最終的には、次のようなものを使用したいと思います。

var users = DataContext.Users.Where(x => x.Criteria1 == "something" && CheckForFlags(x));

私はこのような関数を持ってこれを試しました:

static bool CheckForFlags(User user)
{
   return user.Flag1 || user.Flag2 || user.Flag3 || user.Flag4 || user.Flag5;
}

しかし、エラーが発生します:

「メソッド'BooleanCheckForFlags(User)'には、SQLへの変換がサポートされていません。」

...これは理にかなっていますが、この作業を希望どおりにするためにできることがありますか?または、Linq to SQLを使用していて、実際にはLinq to Objectsで機能するため、これは制限ですか?

4

4 に答える 4

53

LINQ to SQLが式を処理する方法の優れた点は、実際にコード内の他の場所で式を作成し、クエリでそれらを参照できることです。次のようなことを試してみませんか。

public static class Predicates
{
    public static Expression<Func<User, bool>> CheckForFlags()
    {
        return (user => user.Flag1 || user.Flag2 || user.Flag3 ||
                        user.Flag4 || user.Flag5);
    }

    public static Expression<Func<User, bool>> CheckForCriteria(string value)
    {
        return (user => user.Criteria1 == value);
    }
}

述語を定義したら、クエリでそれらを使用するのは非常に簡単です。

var users = DataContext.Users
    .Where(Predicates.CheckForFlags())
    .Where(Predicates.CheckForCriteria("something"));
于 2012-11-01T16:18:05.823 に答える
4

PredicateBuilderを試しましたか?1年以上使用していませんが、「OrWhere」クエリを作成するときに効果的であることがわかりました。

http://www.albahari.com/nutshell/predicatebuilder.aspx

彼らのページからの例:

IQueryable<Product> SearchProducts (params string[] keywords)
{
  var predicate = PredicateBuilder.False<Product>();

  foreach (string keyword in keywords)
  {
    string temp = keyword;
    predicate = predicate.Or (p => p.Description.Contains (temp));
  }
  return dataContext.Products.Where (predicate);
}
于 2012-11-01T16:10:49.337 に答える
0

これはうまくいくと思いますし、Linq-to-SQLプロジェクトで使用したと思いますが、手に負えない例を見つけることができません。そうでない場合は、私に知らせてください。


関数を作成するのではなく、Usersオブジェクトに新しいプロパティを作成します。

partial class Users {
   bool CheckForFlags
    {
       get { 
          return Flag1 || Flag2 || Flag3 || Flag4 || Flag5;
       }
    }
}

その後、あなたはできるはずです

var users = DataContext.Users.Where(x => x.CheckForFlags);
于 2012-11-01T16:08:23.633 に答える
0

私の知る限り、これを行うには2つの方法があります。

すばやく簡単に行う方法は、SQLの実行後に、次のように結果をフィルタリングすることです。

var users = DataContext.Users.Where(x => x.Criteria1 == "something");
    .ToEnumerable()
    .Where(x => CheckForFlags(x));

ただし、これはパフォーマンスの点で非常に劣っています。最初の基準のみに一致するデータベースからすべての行を返し、クライアントのメモリで結果をフィルタリングします。機能的ですが、最適にはほど遠いです。

2番目の、はるかにパフォーマンスの高いオプションは、データベース自体にUDFを作成し、それをLINQから呼び出すことです。たとえば、この質問を参照してください。明らかな欠点は、コードをデータベースに移動することです。これは、(多くの正当な理由により)誰もやりたくないことです。

他の実行可能な解決策があるかもしれませんが、私が知っているのはそれらだけです。

于 2012-11-01T16:08:56.850 に答える