2016-09-30 8 views
1

C#のLINQクエリにいくつか問題があります。LINQクエリと述語の結合

私は同じ構造を持つ同じテーブルをデータベースに持っています。 今日、私はLINQクエリに悩まされています。

詳細については、述部を使用していくつかのテーブルを結合したいと考えています。

私は2つのパラメータを持つ関数を持っています。 最初のパラメータは何らかの種類のContextです(たとえば、ProductContext、CarContext、CatContextなど)。

第2パラメータは、最初のパラメータであるコンテキストと結合するList<something>です。

私は一連のメソッドが必要ないです。

私はサンプルを追加しました:クエリが正しい場合

public Element[] GetByIds(MyPredicateContext, Guid[] ids) 
    { 
     return 
      from id in ids 
      join element in MyPredicateContext on id equals element.Id 
      select 
       new Element 
       { 
        Id = element.Id, 
        Description = element.JobDescription, 
       }; 
    } 
+1

は、なぜあなたは、パラメータとしてのコンテキストではなく、テーブルをしたいですか?または、両方をしたいですか?そして私はあなたのすべての要素が 'JobDescription'プロパティを持っていないと思いますか? –

答えて

0

、私が見ることができる1つの基本的な問題は、IEnumerableをを返却しようとしているのに対し、戻り値の型は、要素の配列です。おそらく、結果セットで.ToArray()を実行すると問題が解決する可能性があります。

+0

この質問には関係ありません – Andrew

+0

申し訳ありませんが、ここで問題が発生しなかった可能性があります。 –

+0

ガイ、それは誤りではありません。あなたは説明を読んだことがありますか? – Andrew

0

なぜあなたはこれがメモリとフィルタリングのすべてを引っ張っに戻ります配列から新しいのIQueryableを作成することはできませんすべての

return MyPredicateContext.Where(element=>ids.Contains(element.Id)) 
      .Select(e=>new Element() 
      { 
       Id = element.Id, 
       Description = element.JobDescription 
      }).ToArray(); 
+0

注意が必要です、参加しました – Andrew

0

まず。式で作業していて、LINQをSQLで実行するとC#コードではなく、これはメモリの内容(IEnumerable)でのみ機能します。あなたはTがインタフェースまたはクラスでのIQueryableの種類ことを考えると、この

from element in MyPredicateContext 
where ids.Contains(element.Id) 
select new Element 
       { 
        Id = element.Id, 
        Description = element.JobDescription, 
       } 

のようにそれを行う場合 あなたのクエリがSQLで動作します。 endメソッドは、この

public interface IElement 
     { 
      Guid Id { get; } 
      string JobDescription { get; } 
     } 

     public Element[] GetByIds<T>(IQueryable<T> myPredicateContext, Guid[] ids) where T:IElement 
     { 
      return (from element in myPredicateContext 
        where ids.Contains(element.Id) 
        select new Element 
            { 
             Id = element.Id, 
             Description = element.JobDescription, 
            }).ToArray(); 

     } 

ようになりますなしジェネリックでそれを行うための方法がありますが、彼らはもう少し進んでいるし、維持するのは難しいだろう。

ここでは、すべてのT型で動作するメソッドであり、適切なIQueryableは良いsqlを生成します。私が指摘したように、少し高度なもので、式の動作を調べる必要があります。

public static Element[] GetById<T, Tkey>(IQueryable<T> items,Tkey[] ids) 
     { 
      var type = typeof(T); 
      ParameterExpression param = Expression.Parameter(type); 
      var list = Expression.Constant(ids); 
      //The names of the properties you need to get if all models have them and are named the same and are the same type this will work 
      var idProp = Expression.Property(param, "Id"); 
      var descriptionProp = Expression.Property(param, "JobDescription"); 

      var contains = typeof(Enumerable).GetMethods().First(m => m.Name == "Contains" && m.GetParameters().Count() == 2).MakeGenericMethod(typeof(Tkey)); 
      var where = Expression.Lambda<Func<T, bool>>(Expression.Call(contains, list, idProp), param); 

      return (items. 
       Where(where). 
       Select(Expression.Lambda<Func<T, Element>>(
        Expression.MemberInit(
        Expression.New(typeof(Element)), 
         Expression.Bind(typeof(Element).GetProperty("Id"), idProp), 
         Expression.Bind(typeof(Element).GetProperty("Description"), descriptionProp)), 
         param))).ToArray(); 
     } 

コールGetById(items, new Guid[] { Guid.NewGuid() })

+0

注意を払う、参加しました – Andrew

+0

@Andrewこの場合、「Contains」はあなたの参加と同じです。 –

+0

@Filip Cordas。はい、申し訳ありませんが、間違いですが、DataBaseのクラスをIElementから継承する方法はありますか? – Andrew