2017-10-26 13 views
2

私は大きな助けを必要としています。私は今これをやろうとしています。LINQが(SQL)LIKE範囲検索を実行する方法

だから私は、このクエリがあります

Select name from BlaBlaBla 

order by 

case when name like '9%' then 1 end, 
case when name like '8%' then 1 end, 
case when name like '7%' then 1 end, 
case when name like '6%' then 1 end, 
case when name like '5%' then 1 end, 
case when name like '4%' then 1 end, 
case when name like '3%' then 1 end, 
case when name like '2%' then 1 end, 
case when name like '1%' then 1 end, 
case when name like '0%' then 1 end, 

name 

をそして、私はそれがOrderTypeフィルターとなりますので、ドメインのプロジェクトに、私のソリューションでは、新しいC#、Asp.Net、クラスでそれを実装したいです

var param = Expression.Parameter(typeof(T), "item"); 

var paramName = Expression.Property(param, "Name"); 
var regexMatch = Expression.Constant("^[0-9]"); 
var startsWithDigit = Expression.Call(typeof(Regex), "IsMatch", 
              null, paramName); 

var lambda = Expression.Lambda<Func<T, bool>>(startsWithDigit, 
               param); 

return namesList.OrderBy(lambda) 
      .ThenBy(BlaBla1()) 
      .ThenByDescending(BlaBla2()) 
      .ThenByDescending(BlaBla3()) 
      .ThenBy(BlaBla4()); 

しかし、それは、その式は「IsMatch」メソッドが含まれていない私に語った:、いくつかの機能のために...のための

は今、私はこれを持っています。

私を助けてもらえますか? ありがとうございました!

+0

LINQをサポートしているORMで作業しているようです。どちらですか?また、なぜLINQ構文を使用する代わりに手動で式を構築していますか? –

+0

ORMまたはメモリを使用してこの順序をデータベースで実行しますか? –

+0

ここで使用されているORMはLinq to Sql –

答えて

1

ここでの問題は、Regexを含む式はSQLに変換できないため、正しい式を作成することができたとしても使用できませんLINQでSQLバックエンドに渡します。しかし、SQLのLIKEメソッドも[0-9]のような範囲ワイルドカードをサポートしているので、LINQをLIKEステートメントを含むSQLに変換することができます。

LINQツーSQLは、明示的 SQL文のLIKEを使用する可能性を提供しています:

return namesList.OrderBy(r => SqlMethods.Like(r.Name, "[0-9]%")) ... 

このSqlMethodsクラスはいえLINQツーSQLで使用することができます。 Entity Frameworkには、LIKE暗黙的にに変換される文字列関数がありますが、いずれも範囲ワイルドカード([x-y])を有効にしません。 EFでの文のような...

return namesList.OrderBy(r => r.Name.StartsWith("[0-9]")) ... 

...ナンセンスに変換します:

[Name] LIKE '~[0-9]%' ESCAPE '~' 

すなわち、リテラル文字列 "[0-9]"で始まる名前は無駄に探します。だからあなたがLINQ-to-SQL SqlMethods.Likeを使い続ける限り、これは道のりです。我々は同じ結果を得るために、わずかに異なる方法を使用する必要はEntity Frameworkの6.1.3(および以下)において

...

return namesList.OrderBy(r => SqlFunctions.PatIndex("[0-9]%", c.Name) == 1) ... 

... SqlFunctionsPatIndexも範囲パターンマッチングをサポートしているため。

しかし、エンティティFramwork 6.2で、私たちはので、新しいDbFunctions.Like機能のLINQからSQLへと戻って軌道に乗っている:

return namesList.OrderBy(r => DbFunctions.Like(r.Name, "[0-9]%")) ... 

は最後に、Entity FrameworkのコアはLike機能を持っています

return namesList.OrderBy(r => EF.Functions.Like(r.Name, "[0-9]%")) ... 
+1

ありがとう@Gert。これは私の問題を解決するのに本当に役立ちました。 –

0

以下に、注文のケースを処理するこの種の方法のサンプルを示します。

static void Main(string[] args) 
    { 
     List<Obvious> list = new List<Obvious>(); 
     for (int i = 0; i < 100; i++) 
     { 
      list.Add(new Obvious(i.ToString(), i)); 
     } 

     string name = list[30].name; 
     switch (name) 
     { 
      case "9": 
       list.OrderBy(o => o.perc) 
        .ThenByDescending(o => o.name); 
       break; 
      default: 
       list.OrderByDescending(o => o.name) 
        .ThenBy(o => o.perc); 
       break; 
     } 
    } 

    public class Obvious 
    { 
     public string name { get; set; } 
     public int perc { get; set; } 
     public Obvious(string _name, int _perc) 
     { 
      this.name = _name; 
      this.perc = _perc; 
     } 

    } 
+0

あなたはその質問を理解していないと思います。彼はLINQをサポートするORMに送ることのできる表現を作成したいと考えています。少なくとも、そうだと思う。 –

+0

こんにちは。これに遅れて申し訳ありません。はい、それは私が欲しいものを厳密にです!それは、それが他のものがどのように作られているかを正確に示しているからです。そして、リストの最後にある桁から始まる名前を、昇順に並べてください。 –

+0

そしてORMはLINQです –

0

私があなただったら、この問題を解決するために式を使用することはありませんが、複雑さが増します。

genericメソッドを使用したいので、別のドメインエンティティでも機能するようになっていますが、各エンティティにはNameというプロパティがあることを期待しています。 これを解決するには、Nameプロパティを含むインターフェイスを定義すると簡単です。このように:

public static void Main() 
    { 
     var test = new List<YourDomainEntity>() 
     { 
      new YourDomainEntity() { Name = "1test", OtherProperty = "1"}, 
      new YourDomainEntity() { Name = "2test", OtherProperty = "2" }, 
      new YourDomainEntity() { Name = "2test", OtherProperty = "1" } 
     }; 

     var k = Foo(test).ToList(); 
    } 

    public interface INameOrderable 
    { 
     string Name { get; set; } 
    } 

    public interface IOtherPropertyOrderable 
    { 
     string OtherProperty { get; set; } 
    } 

    public static IEnumerable<T> Foo<T>(IEnumerable<T> list) where T : INameOrderable, IOtherPropertyOrderable 
    { 
     return list.OrderBy(a => a.Name, new NamesDescComparer()).ThenBy(b => b.OtherProperty); 
    } 

    public class NamesDescComparer : IComparer<string> 
    { 
     public int Compare(string x, string y) => -String.CompareOrdinal(x, y); 
    } 

    class YourDomainEntity : INameOrderable, IOtherPropertyOrderable 
    { 
     public string OtherProperty { get; set; } 
     public string Name { get; set; } 
    } 

私は方法Fooはあなたが探していると信じています。

where T : INameOrderable部分に注意してください。このメソッドの使用をINameOrderableインタフェースを実装するエンティティに限定します

関連する問題