2013-08-09 7 views
5

私はデータベースを照会するためのラムダ関数を動的に作成する.Find(objects [] keys)メソッドを実行しています。Func <object []、Expression <Func<T,bool> >> dynamicを実行するにはどうすればよいですか?

基本的に私が欲しいものです:

var mykeys = new Guid("37ec1659-b35e-46c9-a7fc-e9802644ca1a"); 
IQueryable<T> database ; 
Func<object[],Expression<Func<T,bool>>> objectFinder = CreateKeyExpression(typeof(T)); 
var foundObject = database.FirstOrDefault(objectFinder(mykeys)); 

private LambdaExpression CreateKeyExpression(Type C1Type) 
{ 

    ParameterExpression instanceParameter = Expression.Parameter(C1Type); 
    ParameterExpression keyParameters = Expression.Parameter(typeof(object[])); 

    PropertyInfo[] objectKeys = C1Type.GetKeyProperties().ToArray(); 
    var expr = Expression.Equal(Expression.TypeAs(Expression.Property(instanceParameter,objectKeys[0]),typeof(object)), 
     Expression.ArrayIndex(keyParameters,Expression.Constant(0))); 


    for (int i = 1; i < objectKeys.Length; i++) 
    { 
     expr = Expression.AndAlso(expr, Expression.Equal(
      Expression.Property(instanceParameter,objectKeys[i]), 
      Expression.ArrayIndex(keyParameters,Expression.Constant(i)) 
      )); 

    } 

    var lmp= Expression.Lambda(expr, instanceParameter); 

    return Expression.Lambda(lmp, keyParameters); 
} 

私はこれを達成する方法の任意のアイデア?上記は私にを与え、IQueryableをIEnumerableにします。つまり、データベースの最後では実行しません。

答えて

2

FirstOrDefaultメソッドを使用してキー値で式配列に渡すことができないため、Expression.ArrayIndexの代わりにExpression.Constantメソッドを使用する必要があります。

private static LambdaExpression CreateKeyExpression(Type C1Type, object[] parameters) 
{ 
    var instanceParameter = Expression.Parameter(C1Type); 
    PropertyInfo[] objectKeys = C1Type.GetKeyProperties().ToArray(); 

    var expr = Expression.Equal(Expression.Property(instanceParameter, objectKeys[0]), 
     Expression.Constant(parameters[0], objectKeys[0].PropertyType)); 


    for (int i = 1; i < objectKeys.Length; i++) 
    { 
     expr = Expression.AndAlso(expr, Expression.Equal(
      Expression.Property(instanceParameter, objectKeys[i]), 
      Expression.Constant(parameters[i], objectKeys[i].PropertyType))); 
    } 
    return Expression.Lambda(expr, instanceParameter); 
} 

var parameters = new object[] { Guid.NewGuid(), Guid.NewGuid() }; 
var lambdaExpression = CreateKeyExpression(typeof(TestClass), parameters); 
var testClasses = new List<TestClass>() { new TestClass { Id = (Guid)parameters[0], Id1 = (Guid)parameters[1] } }; 
var testClass = testClasses.AsQueryable().FirstOrDefault((Expression<Func<TestClass, bool>>)lambdaExpression); 
+0

興味深い、私は少し違っそれを解決しました。 CreateKeyExpressionにobject []パラメータを入れることはオプションではありませんでした。私はFunc >を要求した理由として、与えられたC1Typeの式をキャッシュすることができたかったのです。どのタイプのキャッシュでも、新しいキーセットが使用されるたびに生成されません。ほかの人が望むだけで私のソリューションを投稿します。ありがとう –

0
private Expression<Func<object[], Expression<Func<C1Source, bool>>>> CreateKeyExpression<C1Source>() 
{ 

    ParameterExpression instanceParameter = Expression.Parameter(typeof(C1Source)); 
    ParameterExpression keyParameters = Expression.Parameter(typeof(object[])); 

    PropertyInfo[] objectKeys = typeof(C1Source).GetKeyProperties().ToArray(); 
    var expr = Expression.Equal(Expression.Property(instanceParameter,objectKeys[0]), 
    Expression.Convert( 
     Expression.ArrayIndex(keyParameters,Expression.Constant(0)), 
     objectKeys[0].PropertyType) 
     ); 

    for (int i = 1; i < objectKeys.Length; i++) 
    { 
     expr = Expression.AndAlso(expr, Expression.Equal(
      Expression.Property(instanceParameter,objectKeys[i]), 
      Expression.Convert(
       Expression.ArrayIndex(keyParameters,Expression.Constant(i)), 
       objectKeys[i].PropertyType) 
       ); 

    } 

    var lmp= Expression.Lambda(expr, instanceParameter); 

    return Expression.Lambda<Func<object[], Expression<Func<C1Source, bool>>>>(lmp, keyParameters); 

} 
関連する問題