如果给定一个包含“Id”属性的Person IDbSet,我该如何通用地执行以下命令:
var p = PersonDbSet.FirstOrDefault(i=>i.Id = 3);
我可以构建谓词,并获得对FirstOrDefault扩展方法的引用,但似乎无法将它们整合起来:
首先是谓词
ParameterExpression parameter = Expression.Parameter(entityType, "Id");
MemberExpression property = Expression.Property(parameter, 3);
ConstantExpression rightSide = Expression.Constant(refId);
BinaryExpression operation = Expression.Equal(property, rightSide);
Type delegateType = typeof (Func<,>).MakeGenericType(entityType, typeof (bool));
LambdaExpression predicate = Expression.Lambda(delegateType, operation, parameter);
现在是关于扩展方法的参考:
var method = typeof (System.Linq.Queryable).GetMethods(BindingFlags.Static | BindingFlags.Public)
.FirstOrDefault(m => m.Name == "FirstOrDefault" && m.GetParameters().Count() == 2);
MethodInfo genericMethod = method.MakeGenericMethod(new[] { entityType });
最后尝试执行该方法:
object retVal = genericMethod.Invoke(null, new object[] {dbSet, predicate});
抛出一个带有以下信息的ArgumentException:
"类型为'System.Reflection.RuntimePropertyInfo'的对象无法转换为类型为'System.Linq.IQuerable`1[Person]'的对象。"
有什么想法吗?
Queryable
类中的FirstOrDefault
,因为使用Enumeable.FirstOrDefault
会获取所有记录并在内存中进行过滤。 - Lee