質問

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;
}

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

役に立ちましたか?

解決

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

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;
}

仮定:

  • パーツ名は次のようになります。「ABC123XYZ」

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

他のヒント

より単純でより正しい解決策 (その後、leppie の解決策):

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>%';

また注目すべき点は、 StartsWith そして EndsWith に似ています Contains ただし、特定の場所で文字列を探します。

query.Contains(partName) SQLと同じです in 指示。結果の SQL は次と等価になります (<query0> は次の値です) query[0], 、<query1> は次の値です。 query[1], 、<queryN> はクエリ配列の最後の値です):

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

アップデート:
leppie の回答では、ワイルドカード文字を追加する前にエスケープしないことに注意することも重要です。 のように 声明。これは問題ではありません Contains これは、Linq がクエリを送信する前にエスケープするためです。のエスケープバージョン SqlMethods.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 がエスケープしてくれるため、心配する必要はありません。

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

public IQueryable<Part> SearchForParts(string[] query)
{
    return from part in db.Parts
           where query.All(term => part.partName.Contains(term))
           select part;
}
SQLにLINQは、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;
}
それはのようにきれいではありませんが、それは動作するはずです。あなたは、where句でANDsの多くのクエリを取得します。

あなたはこの

としてそれを書くことができます
var result = db.Parts.Where(p => query.All(q => p.partName.Contains(q)));
NinjaNye.SearchExtension のnugetパッケージを使用すると、簡単にこの検索を実行することができます:

string[] terms = new[]{"search", "term", "collection"};
var result = db.Parts.Search(terms, p => p.PartName);

また、複数の文字列プロパティを検索できます。

var result = db.Parts.Search(terms, p => p.PartName, p.PartDescription);

あるいは、単に検索語が出現した回数を示しプロパティが含まれRankedSearchを返すIQueryable<IRanked<T>>を実行します:

//Perform search and rank results by the most hits
var result = db.Parts.RankedSearch(terms, p => p.PartName, p.PartDescription)
                     .OrderByDescending(r = r.Hits);

プロジェクトGitHubのページでより広範なガイドがあります: https://github.com/ninjanye/SearchExtensions

ホープ、このことができます将来の訪問者

私はこれが私のためにややシンプルで働いていると感じます:

string[] product = products.Split(','); 
using (var context = new ProjectTrackerEntities()) 
{ var result = from part in context.DBAudits where product.Contains(part.TableName) select part; }

これを試してみてください。

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;
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top