2017-09-17 7 views
0

私はこれを何時間もプレイしており、新しい目を使うことができます。私よりも経験豊富な人が表現木について話しています。人は曲線が急です!ラムダを表現木に変換するのに助けが必要

以下を考慮してください。これは私がこれまで持っているものである

repo = repo.Where(x => x.Accounts.FirstOrDefault().Id == AccountId); 

(これは動作しますが、私はアカウントが文字列として渡される必要があります。アカウントは、アカウントのリストです)。

  var parameterExp = Expression.Parameter(typeof(Boat), "x"); 
      var propertyExp = Expression.Property(parameterExp, "Accounts"); 

      MethodInfo method1 = typeof(Queryable).GetMethods(BindingFlags.Public | BindingFlags.Static).First(m => m.Name == "FirstOrDefault"); 

      // This gives me a Queryable of Account FirstOrDefault 
      var specificMethod = method1.MakeGenericMethod(propertyExp.Type); 

      // right here is where I am getting stuck 
      var firstOrDefaultAccountExpression = // I need to get an Account so I can query against the Id ?? 


      MethodInfo method = typeof(long).GetMethod("Equals", new[] { typeof(long) }); 
      var someValue = Expression.Constant(AccountId, typeof(long)); 
      var containsMethodExp = Expression.Call(firstOrDefaultAccountExpression , method, someValue); 

      Expression<Func<Boat, bool>> predicate = Expression.Lambda<Func<Boat, bool>> 
         (containsMethodExp, parameterExp); 


      repo = repo.Where(predicate); 

このコードを通常の文字列メンバーで使用できるようにしました。私はリストを把握していないようだ。最終的に私はAccountId = longのBoatのリストを取得しようとしています

ありがとうございました!

+0

あなたはすべてのボートの最初のアカウントについてのみ気にしますか? –

+0

はい、実際にはFirstOrDefaultの代わりにSingeになる可能性があります。ボートには、それらに関連するアカウントが1つしかありません。アカウントはボートのオーナーです – th3monk3y

答えて

0
var parameterExp = Expression.Parameter(typeof(Boat), "x"); 
Expression propertyExp = Expression.Property(parameterExp, "Accounts"); 

Type elementType = propertyExp.Type.GetGenericArguments()[0]; 

MethodInfo method1 = typeof(Enumerable).GetMethods(BindingFlags.Public | BindingFlags.Static).First(m => m.Name == "FirstOrDefault"); 

// This gives me a Queryable of Account FirstOrDefault 
var specificMethod = method1.MakeGenericMethod(elementType); 

//propertyExp = Expression.TypeAs(propertyExp, typeof(IEnumerable<>).MakeGenericType(elementType)); 

var firstOrDefaultAccountExpression = Expression.Call(specificMethod, propertyExp); 

var idExpr = Expression.PropertyOrField(firstOrDefaultAccountExpression, "Id"); 

MethodInfo method = typeof(long).GetMethod("Equals", new[] { typeof(long) }); 
var someValue = Expression.Constant(AccountId, typeof(long)); 
var containsMethodExp = Expression.Call(idExpr, method, someValue); 

Expression<Func<Boat, bool>> predicate = Expression.Lambda<Func<Boat, bool>> 
      (containsMethodExp, parameterExp); 

repo = repo.Where(predicate); 

List<>FirstOrDefaultを呼び出すことができるようにIEnumerable<>にキャストする必要があります。私はそれがキャストなしではうまくいかなかったと誓っていましたが、今は奇妙です。だから私はその行をコメントアウトした。しかし、両方のバージョンでは、linq2sqlでsqlコードを生成することができます。 AccountsプロパティにアクセスするためにQueryableは必要ありません。コードの最初の行である非式クエリを見てください。そこにさえ、FirstOrDefaultEnumerableの方法です。その目的は、式を定義して変換を定義することです。実際には何もしません。

+0

あなたの投稿を更新しました。そうでなければ画像を追加できませんでした – th3monk3y

+0

作品!あなたは私のヒーローです!あなたAntoninありがとう! – th3monk3y

+0

"その目的は、式を定義して変換を定義することです。実際には何もしません。説明をありがとう。私は、Queryable vs Enumerableが式でDBに当たるかどうかはわかりませんでした。再び、急な学習曲線。 – th3monk3y

関連する問題