ユーザーがワイルドカードを含む検索文字列を指定できるテキストボックスがあります。次に例を示します。
Joh*
*Johnson
*mit*
*ack*on
LINQ to Entitiesを使用する前に、その文字列をパラメーターとして取り、実行するストアドプロシージャを用意しました。
SELECT * FROM Table WHERE Name LIKE @searchTerm
そして、それを渡す前に、String.Replace( '*'、 '%')を実行します。
LINQ to Entitiesを使用して、同じことを達成しようとしています。 StartsWith、EndsWith、Containsのサポートがあることは知っていますが、必要な方法ではサポートされません。
「SqlMethods.Like」について読んで、これを試してみました:
var people = from t in entities.People
where SqlMethods.Like(t.Name, searchTerm)
select new { t.Name };
ただし、次の例外が発生します。
LINQ to Entities does not recognize the method 'Boolean Like(System.String,
System.String)' method, and this method cannot be translated into a store
expression.
LINQ to Entitiesを使用してこれと同じ機能を取得するにはどうすればよいですか?
var people = entities.People.Where("it.Name LIKE @searchTerm", new ObjectParameter("searchTerm", searchTerm));
シームレスに機能させる方法:
eDMXモデルに、以下を追加します。
<Function Name="String_Like" ReturnType="Edm.Boolean">
<Parameter Name="searchingIn" Type="Edm.String" />
<Parameter Name="lookingFor" Type="Edm.String" />
<DefiningExpression>
searchingIn LIKE lookingFor
</DefiningExpression>
</Function>
始まるセクションの直後:
<edmx:ConceptualModels> <Schema Namespace="Your.Namespace"...
次に、コードの任意の場所に、この拡張メソッドを追加します。
//prior to EF 6 [System.Data.Objects.DataClasses.EdmFunction("Your.Namespace", "String_Like")]
//With EF 6
[System.Data.Entity.DbFunction("Your.Namespace", "String_Like")]
public static bool Like(this string input, string pattern)
{
/* Turn "off" all regular expression related syntax in
* the pattern string. */
pattern = Regex.Escape(pattern);
/* Replace the SQL LIKE wildcard metacharacters with the
* equivalent regular expression metacharacters. */
pattern = pattern.Replace("%", ".*?").Replace("_", ".");
/* The previous call to Regex.Escape actually turned off
* too many metacharacters, i.e. those which are recognized by
* both the regular expression engine and the SQL LIKE
* statement ([...] and [^...]). Those metacharacters have
* to be manually unescaped here. */
pattern = pattern.Replace(@"\[", "[").Replace(@"\]", "]").Replace(@"\^", "^");
return Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase);
}
そして、そこにあります。
今あなたはできる:
(from e in Entities
where e.Name like '%dfghj%'
select e)
または
string [] test = {"Sydney", "Melbourne", "adelaide", "ryde"};
test.Where(t=> t.Like("%yd%e%")).Dump();
まあ、あなたの選択肢は:
Contains
を使用します。私はあなたがそれを好きではないことを知っていますが、それはおそらく動作するように作られる可能性があります。あなたはこれを行うことができます:
_using System.Data.Entity; // EntityFramework.dll v4.3
var queryResult=db.Accounts.AsQueryable().Where(x => x.Name.Contains(queryKey));
_
linq to Entity
はメソッドContains()
をSQLに変換できませんが、Linq to SQLはこれを実行できるためです。キャストできるメソッドを見つけようとしましたが、ついにAsQueryable()
もジェネリックバージョンAsQueryable<T>()
になりました。私の場合、この方法でこれを使用してこれを行うことができることがわかりましたが、それによってわからない副作用があれば、Entity
で一部の機能が失われる可能性があります。
解決策は SQLFunctions.PatIndex を使用することです
var result = from c in items
where SqlFunctions.PatIndex(searchstring.ToLower(), c.fieldtoSearch) > 0
select c;
ここで、 'searchstring'は検索するパターンです 'fieldtoSearch'は検索するフィールドです
Patindex()は、文字列パターン検索を使用した検索をサポートしています。検索では大文字と小文字が区別されません。
あなたはこのようなLINQでこれらすべてのステートメントを行うことができます
string _search = "johnson";
// joh* OR joh%
items.Where(i => i.Name.StartsWith(_search, StringComparison.OrdinalIgnoreCase));
// *son OR %son
items.Where(i => i.Name.EndsWith(_search, StringComparison.OrdinalIgnoreCase));
// *hns* OR %hns%
items.Where(i => i.Name.ToLower().Contains(_search));
現在、EFは "LIKE"の使用をサポートしており、すべてのSQLワイルドカードを使用できます。これをチェックしてください。
var people = from t in entities.People
select new { t.Name };
people = people.Where(x => DbFunctions.Like(x.Name, searchTerm));
var people = from t in entities.People
where t.Name.ToLower().Contains(searchTerm.ToLower())
select new { t.Name };
編集-私は構文を混合しているかもしれません。私は通常、拡張メソッドを使用します。が含まれますが動作します。
Database FirstとEntityFrameworkを使用します。
「自分の機能をマッピングする」。アプローチは、nuget EntityFramework.CodeFirstStoreFunctions と一緒に機能します。
1ステップ:次のようにデータベースに関数を作成します。
CREATE FUNCTION [dbo].[StringLike]
(
@a nvarchar(4000),
@b nvarchar(4000)
)
RETURNS bit
AS
BEGIN
RETURN
(SELECT CASE
WHEN (SELECT 1 WHERE @a LIKE @b) = 1 THEN 1
ELSE 0
END)
END
2ステップ:nuget EntityFramework.CodeFirstStoreFunctionsをインストールする
3ステップ:次のようにコードでメソッドを作成します(私はDbContextクラスで作成します):
[DbFunction("CodeFirstDatabaseSchema", "StringLike")]
public static bool Like(string input, string pattern)
{
throw new NotSupportedException("Direct calls are not supported.");
}
4ステップ:EntityFramework.CodeFirstStoreFunctionsを初期化します。
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Add(new FunctionsConvention("dbo", this.GetType()));
}
5ステップ:これで、このメソッドをlinqクエリで使用できます。
フィルタリング中にパーセント記号を使用する必要はありません。例えば;
itemNameに「-」が含まれていないことを確認する場合は、次のようにします
!Item.ItemName.Contains( "-")
SQLでは、NOT LIKE '%-%'に変換されます
以下の方法で簡単に実現できます
var people = from t in entities.People
where t.Name.Contains(searchTerm)
select new { t.Name };
ワイルドカードを実現するには、次の仕様を使用します
LIKE 'a%' => StartsWith("a")
LIKE '%a' => EndsWith("a")
LIKE '%a%' => Contains("a")
LIKE 'a%b' => StartsWith("a") && EndsWith("b")
LIKE '%a%b%' => StartsWith("a") && Contains("b")