96

私たちは、ログ ビューアーに取り組んでいます。使用には、ユーザー、重大度などでフィルター処理するオプションがあります。Sql の時代には、クエリ文字列に追加していましたが、Linq でそれを行いたいと考えています。条件付きで where 句を追加するにはどうすればよいですか?

4

13 に答える 13

164

特定の基準を満たした場合にのみフィルタリングする場合は、次のようにします

var logs = from log in context.Logs
           select log;

if (filterBySeverity)
    logs = logs.Where(p => p.Severity == severity);

if (filterByUser)
    logs = logs.Where(p => p.User == user);

このようにすることで、式ツリーをまさにあなたが望むものにすることができます。そうすれば、作成された SQL はまさに必要なものであり、それ以下ではありません。

于 2008-08-14T15:27:09.297 に答える
25

リスト/配列に基づいてフィルタリングする必要がある場合は、次を使用します。

    public List<Data> GetData(List<string> Numbers, List<string> Letters)
    {
        if (Numbers == null)
            Numbers = new List<string>();

        if (Letters == null)
            Letters = new List<string>();

        var q = from d in database.table
                where (Numbers.Count == 0 || Numbers.Contains(d.Number))
                where (Letters.Count == 0 || Letters.Contains(d.Letter))
                select new Data
                {
                    Number = d.Number,
                    Letter = d.Letter,
                };
        return q.ToList();

    }
于 2011-05-09T19:36:13.150 に答える
20

私はDarenと同様の答えを使用しましたが、IQueryableインターフェイスを使用しました。

IQueryable<Log> matches = m_Locator.Logs;

// Users filter
if (usersFilter)
    matches = matches.Where(l => l.UserName == comboBoxUsers.Text);

 // Severity filter
 if (severityFilter)
     matches = matches.Where(l => l.Severity == comboBoxSeverity.Text);

 Logs = (from log in matches
         orderby log.EventTime descending
         select log).ToList();

これにより、データベースにアクセスする前にクエリが構築されます。コマンドは、最後の.ToList()まで実行されません。

于 2008-08-21T13:50:32.143 に答える
14

条件付き言語クエリに関しては、フィルターとパイプのパターンが非常に好きです。
http://blog.wekeroad.com/mvc-storefront/mvcstore-part-3/

基本的に、IQueryableとパラメーターを受け取るフィルターケースごとに拡張メソッドを作成します。

public static IQueryable<Type> HasID(this IQueryable<Type> query, long? id)
{
    return id.HasValue ? query.Where(o => i.ID.Equals(id.Value)) : query;
}
于 2008-08-14T22:03:19.997 に答える
5

これを行う:

bool lastNameSearch = true/false; // depending if they want to search by last name,

これをwhereステートメントに含める:

where (lastNameSearch && name.LastNameSearch == "smith")

は、最終的なクエリが作成されるときに、lastNameSearchクエリfalseが姓検索の SQL を完全に省略することを意味します。

于 2011-06-13T12:20:12.010 に答える
4

もう1つのオプションは、ここで説明するPredicateBuilderのようなものを使用することです。これにより、次のようなコードを記述できます。

var newKids  = Product.ContainsInDescription ("BlackBerry", "iPhone");

var classics = Product.ContainsInDescription ("Nokia", "Ericsson")
                  .And (Product.IsSelling());

var query = from p in Data.Products.Where (newKids.Or (classics))
            select p;

これはLinq2SQLでのみ機能することに注意してください。EntityFrameworkは、このメソッドが機能するために必要なExpression.Invokeを実装していません。この問題についてここで質問があります。

于 2008-08-14T23:21:45.800 に答える
1

最近、同様の要件があり、最終的にこれを MSDN で見つけました。 Visual Studio 2008 の CSharp サンプル

ダウンロードの DynamicQuery サンプルに含まれているクラスを使用すると、実行時に次の形式で動的クエリを作成できます。

var query =
db.Customers.
Where("City = @0 and Orders.Count >= @1", "London", 10).
OrderBy("CompanyName").
Select("new(CompanyName as Name, Phone)");

これを使用すると、実行時にクエリ文字列を動的に構築し、それを Where() メソッドに渡すことができます。

string dynamicQueryString = "City = \"London\" and Order.Count >= 10"; 
var q = from c in db.Customers.Where(queryString, null)
        orderby c.CompanyName
        select c;
于 2008-08-18T13:12:06.440 に答える
1

それは最も美しいものではありませんが、ラムダ式を使用してオプションで条件を渡すことができます。TSQL では、パラメーターをオプションにするために次の多くのことを行います。

WHERE フィールド = @FieldVar OR @FieldVar IS NULL

次のラムダを使用して同じスタイルを複製できます (認証を確認する例)。

MyDataContext db = new MyDataContext();

void RunQuery(string param1, string param2, int? param3){

Func checkUser = ユーザー =>

((param1.Length > 0)? user.Param1 == param1 : 1 == 1) &&

((param2.Length > 0)? user.Param2 == param2 : 1 == 1) &&

((param3 != null)? user.Param3 == param3 : 1 == 1);

ユーザーが見つかりましたUser = db.Users.SingleOrDefault(checkUser);

}

于 2008-08-14T15:53:50.837 に答える
0

C# の && 演算子を使用するだけです。

var items = dc.Users.Where(l => l.Date == DateTime.Today && l.Severity == "Critical")

編集:ああ、もっと注意深く読む必要があります。条件付きで句を追加する方法を知りたいと思っていました。その場合、私にはわかりません。:) 私がおそらく行うことは、いくつかのクエリを準備し、最終的に必要なものに応じて適切なクエリを実行することです。

于 2008-08-14T15:26:12.780 に答える
0

外部メソッドを使用できます:

var results =
    from rec in GetSomeRecs()
    where ConditionalCheck(rec)
    select rec;

...

bool ConditionalCheck( typeofRec input ) {
    ...
}

これは機能しますが、式ツリーに分解することはできません。つまり、Linq to SQL はすべてのレコードに対してチェック コードを実行します。

または:

var results =
    from rec in GetSomeRecs()
    where 
        (!filterBySeverity || rec.Severity == severity) &&
        (!filterByUser|| rec.User == user)
    select rec;

これは式ツリーで機能する可能性があり、Linq to SQL が最適化されることを意味します。

于 2008-08-14T15:27:15.880 に答える
0

さて、私が考えたのは、フィルター条件を述語の一般的なリストに入れることができるということでした。

    var list = new List<string> { "me", "you", "meyou", "mow" };

    var predicates = new List<Predicate<string>>();

    predicates.Add(i => i.Contains("me"));
    predicates.Add(i => i.EndsWith("w"));

    var results = new List<string>();

    foreach (var p in predicates)
        results.AddRange(from i in list where p.Invoke(i) select i);               

その結果、「me」、「meyou」、および「mow」を含むリストが作成されます。

すべての述語を OR するまったく別の関数で述語を使用して foreach を実行することで、これを最適化できます。

于 2008-08-14T15:39:33.063 に答える