43

linq-to-sql を使用して、アプリケーションに非常に基本的なキーワード検索を実装しようとしています。検索用語は文字列の配列であり、各配列項目は 1 つの単語であり、検索用語を含む行を見つけたいと考えています。検索用語以外のものが含まれていてもかまいませんが (ほとんどの場合、含まれる可能性があります)、すべての検索用語が存在する必要があります。

理想的には、以下のスニペットに似たものが欲しいのですが、これがうまくいかないことはわかっています。また、私はこの質問をここで見ましたが、その質問の作成者は逆のことをすることに満足しているようです ( query.Contains(part.partName))。これは私にはうまくいきません。

public IQueryable<Part> SearchForParts(string[] query)
{
    return from part in db.Parts
           where part.partName.Contains(query)
           select part;
}

このクエリを書き直して、必要なことを実行するにはどうすればよいですか?

4

7 に答える 7

45

他の試みを見ると、私は悲しくなります:(

public IQueryable<Part> SearchForParts(string[] query)
{
  var q = db.Parts.AsQueryable(); 

  foreach (var qs in query)
  { 
    var likestr = string.Format("%{0}%", qs);
    q = q.Where(x => SqlMethods.Like(x.partName, likestr));
  }

  return q;
}

仮定:

  • partName は次のようになります: 「ABC 123 XYZ」

  • クエリは { "ABC", "123", "XY" }

于 2010-03-03T06:21:30.097 に答える
22

よりシンプルでより正確な解決策(その後レピーの):

public IQueryable<Part> SearchForParts(string[] query)
{
    var q = db.Parts.AsQueryable(); 

    foreach (string qs in query)
    {
        q = q.Where(x => x.partName.Contains(qs));
    }

    return q;
}

partNameこれは、文字列 (または文字列に相当する SQL) である限り機能します。

注意すべき重要なことは、 とpartName.Contains(qs)は異なりquery.Contains(partName)ます。
partName.Contains(qs)partNameの出現を検索しますqs。結果の SQL は同等になります (ここで <qs> は の値ですqs)。

select * from Parts where partName like '%<qs>%';

また、StartsWithEndsWithに似てContainsいますが、特定の場所で文字列を探します。

query.Contains(partName)inSQLコマンドと同じです。結果の SQL は次のようになります (<query0> は の値query[0]、<query1> は の値、query[1]<queryN> はクエリ配列の最後の値):

select * from Parts where partName in ( <query0>, <query1>, ..., <queryN> );

更新: leppie の答えは、ワイルドカード文字をlikeステートメント
に追加する前にエスケープしないことに注意することも重要です。Linq はクエリを送信する前にエスケープするため、これはソリューションの問題ではありません。ソリューションのエスケープ バージョンは次のようになります。ContainsSqlMethods.Like

public IQueryable<Part> SearchForParts(string[] query)
{
    var q = db.Parts.AsQueryable(); 

    foreach (var qs in query)
    {
        string escaped_bs = qs.Replace("/", "//"),
            escaped_us = escaped_bs.Replace("_", "/_"),
            escaped_p = escaped_us.Replace("%", "/%"),
            escaped_br = escaped_p.Replace("[", "/["),
            likestr = string.Format("%{0}%", escaped_br);

        q = q.Where(x => SqlMethods.Like(x.partName, likestr, '/'));
    }

    return q;
}

' について心配する必要はありません。Linq がそれをエスケープしてくれるからです。

于 2012-02-29T03:56:03.547 に答える
1

あなたは試すことができます:

public IQueryable<Part> SearchForParts(string[] query)
{
    return from part in db.Parts
           where query.All(term => part.partName.Contains(term))
           select part;
}

ただし、LINQ to SQL がそれを T-SQL に変換できるかどうかはわかりません。別のオプションは次のとおりです。

public IQueryable<Part> SearchForParts(string[] query)
{
    var result = from part in db.Parts
                 select part;

    foreach(var term in query)
    {
        result = from part in result
                 where part.partName.Contains(term)
                 select part;
    }

    return result;
}

それほどきれいではありませんが、うまくいくはずです。ANDwhere 句に多くの s を含むクエリが得られます。

于 2010-03-03T05:50:32.873 に答える
1

このように書くことができます

var result = db.Parts.Where(p => query.All(q => p.partName.Contains(q)));
于 2010-03-03T06:05:51.050 に答える
0

これはややシンプルで、私にとってはうまくいっていると思います:

string[] product = products.Split(','); 
using (var context = new ProjectTrackerEntities()) 
{ var result = from part in context.DBAudits where product.Contains(part.TableName) select part; }
于 2012-12-17T17:34:28.870 に答える
-3

これを試してください:

public IQueryable<Part> SearchForParts(string[] query)
{
    return from part in db.Parts
           where Search(part.Name,query)
           select part;
}

public bool Search(string partName,string[] query)
{
    for (int i = 0; i < query.Length; i++)
    {
        if(partName.Contains(query[i]))
           return true;
    }

    return false;
}
于 2010-03-03T06:10:49.900 に答える