Dostaję następujący błądŁączenie wielu wyrażeń drzewa
Parametr „p” nie był związany w określonym LINQ podmiotom wyrażeniu kwerendy.
rozumiem problemu (sama instancja ParameterExpression
powinny być stosowane do wszystkich wyrażeń w drzewie) i próbowano stosować roztwory Znalazłem w Internecie, ale bez powodzenia.
To jest moja metoda
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;
}
}
Generuje wyrażenie dla odnośnika podmiotu w oparciu o szereg właściwości.
Działa dobrze dla pojedynczego wyrażenia, błąd występuje tylko podczas przekazywania w wielu.
Called tak:
SeedEntity(context, ref e, p=> p.Name);//Works
SeedEntity(context, ref e, p=> p.Name, p=> p.Age);//Fails
Generuje coś podobnego do mnie, wykonując następujące czynności:
context.Set<TEntity>().FirstOrDefault(p=>p.Name == e.Name && p.Age == e.Age);
Wymiana e.Name & & e.Age z ConstantExpression
Można zobacz w powyższej metodzie pobieram wszystkie unikalne parametry i przechowuję je w parameters
na p, a następnie użyj tej samej zmiennej w całym tekście. To jest początek, ale muszę wymienić instancje parametru w każdej z Expression<Func<TEntity, bool>>
przekazanej jako tablica params
, w tym miejscu zawodzę.
Próbowałem wyliczyć wyrażenia i użyć przejścia .Update()
metoda w params
Próbowałem również rozwiązanie używając 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;
}
}
Po prostu szybka myśl, czy próbowałeś użyć innej litery dla drugiego parametru? (tj. p => p.Nazwa, f => f.Age) –
Dzięki za wejście, to nigdy nie zadziałałoby, ponieważ masz tylko jeden parametr, ale twoje przejście na dwoje. Spowoduje to Niepoprawną liczbę parametrów dostarczonych dla lambda –
Zamiast łączenia zapytań, dlaczego nie zastosować ich kolejno? 'results =/* Pełny zestaw * /; foreach (expression) {results = results.Where (expression)}? Ponieważ EF używa 'IQueryable', struktura odracza wykonanie, dopóki nie będzie potrzebna, a następnie połączy wszystkie predykaty w jedno zapytanie dla SQL. – Basic