2015-11-19 19 views
5

Benbirleştiren birden ifadeler ağaçlar

parametre 'p' varlıkları için belirlenen LINQ sorgu ifadesi de bağlı değildi aşağıdaki hatayı alıyorum.

Sorunu (ParameterExpression aynı örneği ağacındaki bütün ifadeler kullanılmalıdır) anlamak ve çözümler online ama hiç şans ile buldum kullanmaya çalıştılar.

Bu

benim yöntem

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; 
    } 
} 

Bu özellikleri bir dizi dayalı bir varlığın arama için bir ifade oluşturur olduğunu.

Tek bir ifade için iyi çalışıyor, hata yalnızca birden çok iletimde gerçekleşiyor. Böyle denilen

: Bir ConstantExpression

yapabilirsiniz ile

context.Set<TEntity>().FirstOrDefault(p=>p.Name == e.Name && p.Age == e.Age); 

değiştirilmesi e.Name & & e.Age:

SeedEntity(context, ref e, p=> p.Name);//Works 
SeedEntity(context, ref e, p=> p.Name, p=> p.Age);//Fails 

Aşağıdaki gerçekleştirerek bana benzer bir şey üretir Yukarıdaki yönteme bakın, tüm benzersiz paramları yakalayın ve bunları parameters'da saklayın. p, daha sonra aynı değişkeni kullanın.Bu başlangıçtır, ancak params dizisi olarak geçirilen Expression<Func<TEntity, bool>> dizisinin her birindeki parametrelerin örneklerini değiştirmem gerekiyor; bu, başarısız olduğum yer.

Ben ifadeleri numaralandırmak ve ben de 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; 
    } 
} 
+0

Sadece hızlı bir düşünce, ikinci parametre için farklı bir harf kullanmayı denediniz mi? (örn. p => p.Adı, f => f.Age) –

+0

Girdiğiniz için bu, asla işe yaramaz, çünkü sadece bir parametreniz var, ancak ikisini geçiyorsunuz. Lambda –

+2

için verilen hatalı parametre sayısını atayacaktır. Sorguları birleştirmek yerine neden bunları arka arkaya uygulamıyorsunuz? 'results =/* Tam set * /; foreach (ifade) {results = sonuçlar.Where (expression)} '? EF, “IQueryable” ı kullandığı için, çerçeve gerekli olana kadar yürütmeyi erteler, ardından tüm yüklemleri SQL için tek bir sorguda birleştirir. – Basic

cevap

4

Gerçekten yakınsın kullanarak bir çözüm çalıştı params

yılında .Update() yöntem geçmesini kullanmak denedim. parameters değişkeninizin noktasını göremiyorum. Onları isimle gruplamak bir hatadır. Neden parametreleri sadece ifadeden geçirmiyorsunuz? Sonra gerekirse ziyaret edin. Ziyaretçi kodunuz iyi.

private static void SeedEntity<TEntity>(DbContext context, ref TEntity entity, params Expression<Func<TEntity, object>>[] identifierExpressions) 
     where TEntity : class 
    { 
     Expression<Func<TEntity, bool>> allExpresions = null; 

     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, identifierExpression.Parameters); 

      if (allExpresions == null) 
      { 
       allExpresions = equalExpression2; 
      } 
      else 
      { 
       var visitor = new ExpressionSubstitute(allExpresions.Parameters[0], identifierExpression.Parameters[0]); 
       var modifiedAll = (Expression<Func<TEntity,bool>>)visitor.Visit(allExpresions); 
       BinaryExpression bin = Expression.And(modifiedAll.Body, equalExpression2.Body); 
       allExpresions = Expression.Lambda<Func<TEntity, bool>>(bin, identifierExpression.Parameters); 
      } 
     } 

     TEntity existingEntity = null; 
     if (allExpresions != null) 
     { 
      existingEntity = context.Set<TEntity>().FirstOrDefault(allExpresions); 
     } 

     if (existingEntity == null) 
     { 
      context.Set<TEntity>().Add(entity); 
     } 
     else 
     { 
      entity = existingEntity; 
     } 
    } 
+1

Bu örneği, (yukarıdaki örnekte değil) parametreleri değiştirerek yeniden kullanabileceğimi düşünerek benzersiz izinleri yakaladım. Siz çözüm işleri, çok teşekkür ederim. Şimdi nerede yanlış gittiğimi görüyorum –