Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 动态构建用于调用LINQ Where方法的表达式_C#_.net_Entity Framework - Fatal编程技术网

C# 动态构建用于调用LINQ Where方法的表达式

C# 动态构建用于调用LINQ Where方法的表达式,c#,.net,entity-framework,C#,.net,Entity Framework,我正在使用一本书中的一些代码来实现EF数据访问的通用存储库类。代码使用以下两种方法通过其int-id主键获取单个实体,假设所有DB对象都有int-PK。但是,我使用的是以自然键为主的导入DB,我希望保留所有FK关系,即我不想重新设计DB以使用单列int-PK 如何调整下面的代码以使用多列键 protected Expression<Func<T, bool>> CreateGetExpression<T>(int id) { ParameterExpr

我正在使用一本书中的一些代码来实现EF数据访问的通用存储库类。代码使用以下两种方法通过其
int-id
主键获取单个实体,假设所有DB对象都有int-PK。但是,我使用的是以自然键为主的导入DB,我希望保留所有FK关系,即我不想重新设计DB以使用单列int-PK

如何调整下面的代码以使用多列键

protected Expression<Func<T, bool>> CreateGetExpression<T>(int id)
{
    ParameterExpression e = Expression.Parameter(typeof(T), "e");
    PropertyInfo propInfo = typeof(T).GetProperty(KeyPropertyName);
    MemberExpression m = Expression.MakeMemberAccess(e, propInfo);
    ConstantExpression c = Expression.Constant(id, typeof(int));
    BinaryExpression b = Expression.Equal(m, c);
    Expression<Func<T, bool>> lambda = Expression.Lambda<Func<T, bool>>(b, e);
    return lambda;
}

public override T Get<T>(int id)
{
    return List<T>().FirstOrDefault(CreateGetExpression<T>(id));           
}

基本上,您需要建立一个包含多个等式检查的表达式树。您可以使用构建单个相等性检查的代码,构建多个相等性检查,每个键对应一个相等性检查。然后,您需要使用
Expression.and多次组合它们-因此,如果您有单独的等式检查
e1
e2
e3
,您可以使用:

var e = Expression.AndAlso(Expression.AndAlso(e1, e2), e3);
需要注意的一点是:您需要为整个最终表达式使用一个
ParameterExpression
,因此您需要调整“build a single check”方法,以将
ParameterExpression
作为参数。。。你不需要使用Expression.Lambda,直到最后。因此,总体步骤如下所示:

  • 创建一个
    参数表达式
  • 对于每个键,使用刚刚创建的
    参数表达式
    创建一个
    二进制表达式
    ,使用
    表达式.Equals
  • 将相等表达式与对
    Expression.AndAlso的多个调用组合起来
  • 在最后调用
    Expression.Lambda
    创建
    表达式

基本上,您需要建立一个包含多个等式检查的表达式树。您可以使用构建单个相等性检查的代码,构建多个相等性检查,每个键对应一个相等性检查。然后,您需要使用
Expression.and多次组合它们-因此,如果您有单独的等式检查
e1
e2
e3
,您可以使用:

var e = Expression.AndAlso(Expression.AndAlso(e1, e2), e3);
需要注意的一点是:您需要为整个最终表达式使用一个
ParameterExpression
,因此您需要调整“build a single check”方法,以将
ParameterExpression
作为参数。。。你不需要使用Expression.Lambda,直到最后。因此,总体步骤如下所示:

  • 创建一个
    参数表达式
  • 对于每个键,使用刚刚创建的
    参数表达式
    创建一个
    二进制表达式
    ,使用
    表达式.Equals
  • 将相等表达式与对
    Expression.AndAlso的多个调用组合起来
  • 在最后调用
    Expression.Lambda
    创建
    表达式

谢谢你,乔恩。看来我是来找点乐子的。我几乎想实现单值键,并完成它,但这更令人兴奋:-)我认为递归指的是应用程序不能正常工作,导致多次诅咒(即递归),然后将监视器抛出窗口。总是发生在我身上…:)@Jon,我还没有解决实现一个解决方案的问题-现在我只是在类型特定的存储库中重写Get方法-但是要嵌套的代码
AndAlso
调用如下
Expression.AndAlso(Expression.AndAlso(e1,e2),e3)
至少对我来说大声建议递归。@ClarkeyBoy,我认为很多诅咒是标准的使用一个具有不一致结构的自然键的数据库。虽然可能比添加一致的代理键和重新定义所有FK来使用它们要少一些诅咒。@ProfK:如果你有一个表达式集合,它向我建议迭代而不是递归。以一个表达式作为“current”开始,并在集合设置上迭代
current=expression.AndAlso(current,next)
谢谢Jon。看来我是来找点乐子的。我几乎想实现单值键,并完成它,但这更令人兴奋:-)我认为递归指的是应用程序不能正常工作,导致多次诅咒(即递归),然后将监视器抛出窗口。总是发生在我身上…:)@Jon,我还没有解决实现一个解决方案的问题-现在我只是在类型特定的存储库中重写Get方法-但是要嵌套的代码
AndAlso
调用如下
Expression.AndAlso(Expression.AndAlso(e1,e2),e3)
至少对我来说大声建议递归。@ClarkeyBoy,我认为很多诅咒是标准的使用一个具有不一致结构的自然键的数据库。虽然可能比添加一致的代理键和重新定义所有FK来使用它们要少一些诅咒。@ProfK:如果你有一个表达式集合,它向我建议迭代而不是递归。以一个表达式作为“current”开始,并在集合设置上迭代
current=expression.AndAlso(current,next)