【发布时间】:2023-04-08 08:22:01
【问题描述】:
我收到以下错误
参数“p”未绑定在指定的 LINQ to Entities 中 查询表达式。
我了解问题(ParameterExpression 的同一实例应该与树中的所有表达式一起使用)并尝试使用我在网上找到的解决方案,但没有成功。
这是我的方法
private void SeedEntity<TEntity>(DatabaseContext context, ref TEntity entity, params Expression<Func<TEntity, object>>[] identifierExpressions) where TEntity : class
{
Expression<Func<TEntity, bool>> allExpresions = null;
var parameters = identifierExpressions.SelectMany(x => x.Parameters).GroupBy(x => x.Name).Select(p => p.First()).ToList();
foreach (Expression<Func<TEntity, object>> identifierExpression in identifierExpressions)
{
Func<TEntity, object> vv = identifierExpression.Compile();
object constant = vv(entity);
ConstantExpression constExp = Expression.Constant(constant, typeof(object));
BinaryExpression equalExpression1 = Expression.Equal(identifierExpression.Body, constExp);
Expression<Func<TEntity, bool>> equalExpression2 = Expression.Lambda<Func<TEntity, bool>>(equalExpression1, parameters);
if (allExpresions == null)
{
allExpresions = equalExpression2;
}
else
{
BinaryExpression bin = Expression.And(allExpresions.Body, equalExpression2.Body);
allExpresions = Expression.Lambda<Func<TEntity, bool>>(bin, parameters);
}
}
TEntity existingEntity = null;
if (allExpresions != null)
{
existingEntity = context.Set<TEntity>().FirstOrDefault(allExpresions);
}
if (existingEntity == null)
{
context.Set<TEntity>().Add(entity);
}
else
{
entity = existingEntity;
}
}
它会根据许多属性生成一个用于查找实体的表达式。
单个表达式可以正常工作,只有传入多个时才会出错。
这样称呼:
SeedEntity(context, ref e, p=> p.Name);//Works
SeedEntity(context, ref e, p=> p.Name, p=> p.Age);//Fails
它会生成类似于我执行以下操作的内容:
context.Set<TEntity>().FirstOrDefault(p=>p.Name == e.Name && p.Age == e.Age);
将 e.Name && e.Age 替换为 ConstantExpression
您可以在上面的方法中看到,我获取了所有唯一参数并将它们存储在顶部的parameters 中,然后始终使用相同的变量。这是开始,但是我需要替换每个Expression<Func<TEntity, bool>> 中的参数作为params 数组传入,这就是我失败的地方。
我尝试枚举表达式并使用.Update() 方法传入参数
我还尝试了使用ExpressionVisitor的解决方案
public class ExpressionSubstitute : ExpressionVisitor
{
public readonly Expression from, to;
public ExpressionSubstitute(Expression from, Expression to)
{
this.from = from;
this.to = to;
}
public override Expression Visit(Expression node)
{
if (node == from) return to;
return base.Visit(node);
}
}
public static class ExpressionSubstituteExtentions
{
public static Expression<Func<TEntity, TReturnType>> RewireLambdaExpression<TEntity, TReturnType>(Expression<Func<TEntity, TReturnType>> expression, ParameterExpression newLambdaParameter)
{
var newExp = new ExpressionSubstitute(expression.Parameters.Single(), newLambdaParameter).Visit(expression);
return (Expression<Func<TEntity, TReturnType>>)newExp;
}
}
【问题讨论】:
-
想一想,您是否尝试过为第二个参数使用不同的字母? (即 p=> p.Name, f=> f.Age)
-
感谢您的输入,这永远不会起作用,因为您只有一个参数,但您传入了两个参数。它会抛出为 lambda 提供的参数数量不正确
-
与其合并查询,不如依次应用它们?
results = /*Full set*/; foreach(expression) {results = results.Where(expression)}?由于 EF 使用IQueryable,框架将推迟执行直到需要,然后将所有谓词组合成一个 SQL 查询。 -
您是否尝试将多个属性传递给一种方法?检查stackoverflow.com/questions/33630945/…更新部分。
-
@StevenYates 我曾经写过“And”和“Or”谓词组合器(当时我还不太了解 L2E)。我已经为它做了一个 LinqToElasticsearch 提供程序,所以我绝对理解你来自哪里。只是想确保你是故意绕远路的。
标签: c# .net entity-framework expression-trees