2016-08-31 7 views
0

エンティティフレームワーククエリの結果を別のリストの要素のインデックスでソートする必要があります。列を別の `List <string>`変数で注文する

私は

.ThenBy(m=>list.IndexOf(m.Term)) 

のように、他の場所で見つかった提案を試みたが、私はHTTP 500エラーを取得するので、私は何かが欠けていた場合、私は思ったんだけど。デバッグするとき、私はこの内部例外を取得します。エンティティへ

LINQは方法「のInt32 IndexOfメソッド(可能System.String)」メソッドを認識しない、この方法は、ストア式に に翻訳することができません。

特に、私はこのシナリオを考えています。

private IEnumerable<MiaLog1A> PopulateQuery(string selectedCampus) 
{ 
    var list = new List<string> {"No Longer Alphabetical","Fall","Mid","Spring"}; 
    return _db.MiaLog1A.Where(m => m.Campus == selectedCampus) 
      .OrderBy(m => m.StudentName) 
      .ThenBy(m=>m.Term) 
        /* I would like to sort "Term" by the 
        * order of "list". 
        */ 
     .AsEnumerable(); 
} 

私は、このように並べ替えることができ方法はありますか、私は辞書で注文するか、参加の作成に制限していますか?

+1

[この質問](http://stackoverflow.com/questions/15275269/sort-a-list-from-another-listid)への回答が役に立ちます。 – sgbj

+1

@sbatいいえ、その質問はメモリ内でソートされています.OPはSQL文としてクエリ可能なものを書き直そうとしているEFを使用しています。 500エラーがこれを示しています。 – Will

+0

@それは古い質問だが、IQueryableを使って答えを投稿したことは分かっている。 –

答えて

3

これはトリックを行う必要があります。ここでは

private IEnumerable<MiaLog1A> PopulateQuery(string selectedCampus) 
{ 
    var list = new List<string> {"Fall","Mid","Spring"}; 
    return _db.MiaLog1A.Where(m => m.Campus == selectedCampus) 
     .AsEnumerable() 
     .OrderBy(m => m.StudentName) 
     .ThenBy(m=> list.IndexOf(m.Term)); 
} 
+0

デバッグ後、 "LINQ to Entitiesはメソッド 'Int32 IndexOf(System.String)'を認識せず、このメソッドをストア式に変換することはできません。 –

+0

ああ、そのSQL - Linqを使用しています。そこではどのように動作するのかわかりません。しかし、Enumberable-LINQで作業する必要があります。したがって、 '.AsEnumerable()'の後にソートすることを検討してください。 – keydon

+0

は、クエリがビルドされ処理された後にソートするように私の答えを編集しました。 – keydon

1

はそれを行うには怒っ方法ですが、それはあなたがBloggingContext hereの定義を見つけることができますIEnumerable

var db = new BloggingContext(); 

var list = (new List<string> { "FR", "EN" }). 
    Select((s,i)=> $"select '{s}' as {nameof(OrderIndex.Name)},{i} as {nameof(OrderIndex.Id)}"); 

var order = db.Set<OrderIndex>().FromSql(String.Join(" union ",list)); 

var orderedItems = from post in db.Posts 
        join ln in order on post.Lang equals ln.Name into lnPost 
        from od in lnPost.DefaultIfEmpty() 
        orderby od.Id 
        select post; 
var data = orderedItems.ToList(); 

にフォールバックしません。言語コードにLangフィールドを追加しました。これはSQLite、SqlServer、MySQLで動作します。追加する必要があるoracle from dual SQLビューの場合と同じように、OrderIndexと同じ手順を実行する必要があります。 EF 6では、SqlQueryを使用してこれを行うもっと良い方法があり、EFコアのように登録する必要はありません。 はちょうどそれを行うための別の方法を思い出し、それはのように怒っていないのですが、良いかもしれない: 作成したクエリは

SELECT "post"."PostId", "post"."BlogId", "post"."Content", "post"."Date", "post"."Lang", "post"."Title", "ln"."Id", "ln"."Name" 
    FROM "Posts" AS "post" 
    LEFT JOIN (
     select 'FR' as Name,0 as Id union select 'EN' as Name,1 as Id 
    ) AS "ln" ON "post"."Lang" = "ln"."Name" 
    ORDER BY "ln"."Id", "post"."Lang" 

EDITです。

var lang = new List<string> { "FR", "EN" };  
var orderedItems = from post in db.Posts 
        orderby (lang[0] == post.Lang) ? 
        0 :((lang[1] == post.Lang) ? 1 : 2) 
        select post; 

var param = Expression.Parameter(typeof(Post)); 

var order = lang.Select((s, i) => new { s, i }) 
    .Aggregate((Expression)Expression.Constant(lang.Count), (agg, i) => 
     Expression.Condition(
      Expression.Equal(Expression.Property(param,nameof(Post.Lang)), 
      Expression.Constant(i.s)), 
      Expression.Constant(i.i), 
      agg)); 
var exp = Expression.Lambda<Func<Post, int>>(order, param); 
var data = db.Posts.OrderBy(exp).ToList(); 

そしてSQL

SELECT "p"."PostId", "p"."BlogId", "p"."Content", "p"."Date", "p"."Lang", "p"."Title" 
    FROM "Posts" AS "p" 
    ORDER BY CASE 
     WHEN "p"."Lang" = 'EN' 
     THEN 1 ELSE CASE 
      WHEN "p"."Lang" = 'FR' 
      THEN 0 ELSE 2 
     END 
    END 

私はまだ怒っ方法は、私は何を知らない何かのために有用であると考えています。

関連する問題