Contents tagged with LINQ

  • Mapping Non-Public Members With Entity Framework Code First

    This is a common request, and really makes sense; we need to use LINQ expressions and a bit of reflection magic. First, an helper function for returning an expression that points to a member:

       1: public static class ExpressionHelper
       2: {
       3:     public static Expression<Func<TEntity, TResult>> GetMember<TEntity, TResult>(String memberName)
       4:     {
       5:         ParameterExpression parameter = Expression.Parameter(typeof(TEntity), "p");
       6:         MemberExpression member = Expression.MakeMemberAccess(parameter, typeof(TEntity).GetMember(memberName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).Single());
       7:         Expression<Func<TEntity, TResult>> expression = Expression.Lambda<Func<TEntity, TResult>>(member, parameter);
       8:         return (expression);
       9:     }
      10: }

    Then, we call it on the DbContext.OnModelCreating method, as a parameter to StructuralTypeConfiguration<TStructuralType>.Property:

       1: protected override void OnModelCreating(DbModelBuilder modelBuilder)
       2: {
       3:     modelBuilder.Entity<Project>().Property(ExpressionHelper.GetMember<Project, Decimal>("Budget")).IsRequired();
       4:  
       5:     base.OnModelCreating(modelBuilder);
       6: }
    And that’s it!

    Read more...

  • Caching LINQ Queries

    Introduction

    Some days ago I wrote a post on comparing LINQ expressions where I shared my discoveries and general discontent on how difficult it is do right. The reason I was looking into it was because I wanted to write a LINQ query caching mechanism.

    There are actually three main problems involved:

    • Comparing two LINQ expressions;
    • Caching a LINQ expression for some time;
    • For cached instances, preventing them from executing when they are enumerated after the first time.

    Comparing LINQ Expressions

    I ended up writing my own comparer, which involved looking at all possible types of Expressions (around 20 classes). For some it is quite easy, because they have few relevant properties – take ConstantExpression, for instance, I only had to consider the Value property – while for others there are a few – BinaryExpression has Left, Right, Conversion and Method. OK, so here is the code:

       1: public sealed class ExpressionEqualityComparer : IEqualityComparer<Expression>
       2: {
       3:     #region Private fields
       4:     private Int32 hashCode;
       5:     #endregion
       6:  
       7:     #region Hash code
       8:     private void Visit(Expression expression)
       9:     {
      10:         if (expression == null)
      11:         {
      12:             return;
      13:         }
      14:  
      15:         this.hashCode ^= (Int32) expression.NodeType ^ expression.Type.GetHashCode();
      16:  
      17:         switch (expression.NodeType)
      18:         {
      19:             case ExpressionType.ArrayLength:
      20:             case ExpressionType.Convert:
      21:             case ExpressionType.ConvertChecked:
      22:             case ExpressionType.Negate:
      23:             case ExpressionType.UnaryPlus:
      24:             case ExpressionType.NegateChecked:
      25:             case ExpressionType.Not:
      26:             case ExpressionType.Quote:
      27:             case ExpressionType.TypeAs:
      28:                 this.VisitUnary((UnaryExpression) expression);
      29:                 break;
      30:  
      31:             case ExpressionType.Add:
      32:             case ExpressionType.AddChecked:
      33:             case ExpressionType.And:
      34:             case ExpressionType.AndAlso:
      35:             case ExpressionType.ArrayIndex:
      36:             case ExpressionType.Coalesce:
      37:             case ExpressionType.Divide:
      38:             case ExpressionType.Equal:
      39:             case ExpressionType.ExclusiveOr:
      40:             case ExpressionType.GreaterThan:
      41:             case ExpressionType.GreaterThanOrEqual:
      42:             case ExpressionType.LeftShift:
      43:             case ExpressionType.LessThan:
      44:             case ExpressionType.LessThanOrEqual:
      45:             case ExpressionType.Modulo:
      46:             case ExpressionType.Multiply:
      47:             case ExpressionType.MultiplyChecked:
      48:             case ExpressionType.NotEqual:
      49:             case ExpressionType.Or:
      50:             case ExpressionType.OrElse:
      51:             case ExpressionType.Power:
      52:             case ExpressionType.RightShift:
      53:             case ExpressionType.Subtract:
      54:             case ExpressionType.SubtractChecked:
      55:                 this.VisitBinary((BinaryExpression) expression);
      56:                 break;
      57:  
      58:             case ExpressionType.Call:
      59:                 this.VisitMethodCall((MethodCallExpression) expression);
      60:                 break;
      61:  
      62:             case ExpressionType.Conditional:
      63:                 this.VisitConditional((ConditionalExpression) expression);
      64:                 break;
      65:  
      66:             case ExpressionType.Constant:
      67:                 this.VisitConstant((ConstantExpression) expression);
      68:                 break;
      69:  
      70:             case ExpressionType.Invoke:
      71:                 this.VisitInvocation((InvocationExpression) expression);
      72:                 break;
      73:  
      74:             case ExpressionType.Lambda:
      75:                 this.VisitLambda((LambdaExpression) expression);
      76:                 break;
      77:  
      78:             case ExpressionType.ListInit:
      79:                 this.VisitListInit((ListInitExpression) expression);
      80:                 break;
      81:  
      82:             case ExpressionType.MemberAccess:
      83:                 this.VisitMemberAccess((MemberExpression) expression);
      84:                 break;
      85:  
      86:             case ExpressionType.MemberInit:
      87:                 this.VisitMemberInit((MemberInitExpression) expression);
      88:                 break;
      89:  
      90:             case ExpressionType.New:
      91:                 this.VisitNew((NewExpression) expression);
      92:                 break;
      93:  
      94:             case ExpressionType.NewArrayInit:
      95:             case ExpressionType.NewArrayBounds:
      96:                 this.VisitNewArray((NewArrayExpression) expression);
      97:                 break;
      98:  
      99:             case ExpressionType.Parameter:
     100:                 this.VisitParameter((ParameterExpression) expression);
     101:                 break;
     102:  
     103:             case ExpressionType.TypeIs:
     104:                 this.VisitTypeIs((TypeBinaryExpression) expression);
     105:                 break;
     106:  
     107:             default:
     108:                 throw (new ArgumentException("Unhandled expression type"));
     109:         }
     110:     }
     111:  
     112:     private void VisitUnary(UnaryExpression expression)
     113:     {
     114:         if (expression.Method != null)
     115:         {
     116:             this.hashCode ^= expression.Method.GetHashCode();
     117:         }
     118:  
     119:         this.Visit(expression.Operand);
     120:     }
     121:  
     122:     private void VisitBinary(BinaryExpression expression)
     123:     {
     124:         if (expression.Method != null)
     125:         {
     126:             this.hashCode ^= expression.Method.GetHashCode();
     127:         }
     128:  
     129:         this.Visit(expression.Left);
     130:         this.Visit(expression.Right);
     131:         this.Visit(expression.Conversion);
     132:     }
     133:  
     134:     private void VisitMethodCall(MethodCallExpression expression)
     135:     {
     136:         this.hashCode ^= expression.Method.GetHashCode();
     137:  
     138:         this.Visit(expression.Object);
     139:         this.VisitExpressionList(expression.Arguments);
     140:     }
     141:  
     142:     private void VisitConditional(ConditionalExpression expression)
     143:     {
     144:         this.Visit(expression.Test);
     145:         this.Visit(expression.IfTrue);
     146:         this.Visit(expression.IfFalse);
     147:     }
     148:  
     149:     private void VisitConstant(ConstantExpression expression)
     150:     {
     151:         if (expression.Value != null)
     152:         {
     153:             this.hashCode ^= expression.Value.GetHashCode();
     154:         }
     155:     }
     156:  
     157:     private void VisitInvocation(InvocationExpression expression)
     158:     {
     159:         this.Visit(expression.Expression);
     160:         this.VisitExpressionList(expression.Arguments);
     161:     }
     162:  
     163:     private void VisitLambda(LambdaExpression expression)
     164:     {
     165:         if (expression.Name != null)
     166:         {
     167:             this.hashCode ^= expression.Name.GetHashCode();
     168:         }
     169:  
     170:         this.Visit(expression.Body);
     171:         this.VisitParameterList(expression.Parameters);
     172:     }
     173:  
     174:     private void VisitListInit(ListInitExpression expression)
     175:     {
     176:         this.VisitNew(expression.NewExpression);
     177:         this.VisitElementInitializerList(expression.Initializers);
     178:     }
     179:  
     180:     private void VisitMemberAccess(MemberExpression expression)
     181:     {
     182:         this.hashCode ^= expression.Member.GetHashCode();
     183:         this.Visit(expression.Expression);
     184:     }
     185:  
     186:     private void VisitMemberInit(MemberInitExpression expression)
     187:     {
     188:         this.Visit(expression.NewExpression);
     189:         this.VisitBindingList(expression.Bindings);
     190:     }
     191:  
     192:     private void VisitNew(NewExpression expression)
     193:     {
     194:         this.hashCode ^= expression.Constructor.GetHashCode();
     195:  
     196:         this.VisitMemberList(expression.Members);
     197:         this.VisitExpressionList(expression.Arguments);
     198:     }
     199:  
     200:     private void VisitNewArray(NewArrayExpression expression)
     201:     {
     202:         this.VisitExpressionList(expression.Expressions);
     203:     }
     204:  
     205:     private void VisitParameter(ParameterExpression expression)
     206:     {
     207:         if (expression.Name != null)
     208:         {
     209:             this.hashCode ^= expression.Name.GetHashCode();
     210:         }
     211:     }
     212:  
     213:     private void VisitTypeIs(TypeBinaryExpression expression)
     214:     {
     215:         this.hashCode ^= expression.TypeOperand.GetHashCode();
     216:         this.Visit(expression.Expression);
     217:     }
     218:  
     219:     private void VisitBinding(MemberBinding binding)
     220:     {
     221:         this.hashCode ^= (Int32)binding.BindingType ^ binding.Member.GetHashCode();
     222:  
     223:         switch (binding.BindingType)
     224:         {
     225:             case MemberBindingType.Assignment:
     226:                 this.VisitMemberAssignment((MemberAssignment)binding);
     227:                 break;
     228:  
     229:             case MemberBindingType.MemberBinding:
     230:                 this.VisitMemberMemberBinding((MemberMemberBinding)binding);
     231:                 break;
     232:  
     233:             case MemberBindingType.ListBinding:
     234:                 this.VisitMemberListBinding((MemberListBinding)binding);
     235:                 break;
     236:             
     237:             default:
     238:                 throw (new ArgumentException("Unhandled binding type"));
     239:         }
     240:     }
     241:  
     242:     private void VisitMemberAssignment(MemberAssignment assignment)
     243:     {
     244:         this.Visit(assignment.Expression);
     245:     }
     246:  
     247:     private void VisitMemberMemberBinding(MemberMemberBinding binding)
     248:     {
     249:         this.VisitBindingList(binding.Bindings);
     250:     }
     251:  
     252:     private void VisitMemberListBinding(MemberListBinding binding)
     253:     {
     254:         this.VisitElementInitializerList(binding.Initializers);
     255:     }
     256:  
     257:     private void VisitElementInitializer(ElementInit initializer)
     258:     {
     259:         this.hashCode ^= initializer.AddMethod.GetHashCode();
     260:  
     261:         this.VisitExpressionList(initializer.Arguments);
     262:     }
     263:  
     264:     private void VisitExpressionList(ReadOnlyCollection<Expression> list)
     265:     {
     266:         if (list != null)
     267:         {
     268:             for (Int32 i = 0; i < list.Count; i++)
     269:             {
     270:                 this.Visit(list[i]);
     271:             }
     272:         }
     273:     }
     274:  
     275:     private void VisitParameterList(ReadOnlyCollection<ParameterExpression> list)
     276:     {
     277:         if (list != null)
     278:         {
     279:             for (Int32 i = 0; i < list.Count; i++)
     280:             {
     281:                 this.Visit(list[i]);
     282:             }
     283:         }
     284:     }
     285:  
     286:     private void VisitBindingList(ReadOnlyCollection<MemberBinding> list)
     287:     {
     288:         if (list != null)
     289:         {
     290:             for (Int32 i = 0; i < list.Count; i++)
     291:             {
     292:                 this.VisitBinding(list[i]);
     293:             }
     294:         }
     295:     }
     296:  
     297:     private void VisitElementInitializerList(ReadOnlyCollection<ElementInit> list)
     298:     {
     299:         if (list != null)
     300:         {
     301:             for (Int32 i = 0; i < list.Count; i++)
     302:             {
     303:                 this.VisitElementInitializer(list[i]);
     304:             }
     305:         }
     306:     }
     307:  
     308:     private void VisitMemberList(ReadOnlyCollection<MemberInfo> list)
     309:     {
     310:         if (list != null)
     311:         {
     312:             for (Int32 i = 0; i < list.Count; i++)
     313:             {
     314:                 this.hashCode ^= list[i].GetHashCode();
     315:             }
     316:         }
     317:     }
     318:     #endregion
     319:  
     320:     #region Equality
     321:     private Boolean Visit(Expression x, Expression y)
     322:     {
     323:         if (Object.ReferenceEquals(x, y) == true)
     324:         {
     325:             return (true);
     326:         }
     327:  
     328:         if ((x == null) || (y == null))
     329:         {
     330:             return (false);
     331:         }
     332:  
     333:         if ((x.NodeType != y.NodeType) || (x.Type != y.Type))
     334:         {
     335:             return (false);
     336:         }
     337:  
     338:         switch (x.NodeType)
     339:         {
     340:             case ExpressionType.ArrayLength:
     341:             case ExpressionType.Convert:
     342:             case ExpressionType.ConvertChecked:
     343:             case ExpressionType.Negate:
     344:             case ExpressionType.UnaryPlus:
     345:             case ExpressionType.NegateChecked:
     346:             case ExpressionType.Not:
     347:             case ExpressionType.Quote:
     348:             case ExpressionType.TypeAs:
     349:                 return (this.VisitUnary((UnaryExpression)x, (UnaryExpression)y));
     350:  
     351:             case ExpressionType.Add:
     352:             case ExpressionType.AddChecked:
     353:             case ExpressionType.And:
     354:             case ExpressionType.AndAlso:
     355:             case ExpressionType.ArrayIndex:
     356:             case ExpressionType.Coalesce:
     357:             case ExpressionType.Divide:
     358:             case ExpressionType.Equal:
     359:             case ExpressionType.ExclusiveOr:
     360:             case ExpressionType.GreaterThan:
     361:             case ExpressionType.GreaterThanOrEqual:
     362:             case ExpressionType.LeftShift:
     363:             case ExpressionType.LessThan:
     364:             case ExpressionType.LessThanOrEqual:
     365:             case ExpressionType.Modulo:
     366:             case ExpressionType.Multiply:
     367:             case ExpressionType.MultiplyChecked:
     368:             case ExpressionType.NotEqual:
     369:             case ExpressionType.Or:
     370:             case ExpressionType.OrElse:
     371:             case ExpressionType.Power:
     372:             case ExpressionType.RightShift:
     373:             case ExpressionType.Subtract:
     374:             case ExpressionType.SubtractChecked:
     375:                 return (this.VisitBinary((BinaryExpression)x, (BinaryExpression)y));
     376:  
     377:             case ExpressionType.Call:
     378:                 return (this.VisitMethodCall((MethodCallExpression)x, (MethodCallExpression)y));
     379:  
     380:             case ExpressionType.Conditional:
     381:                 return (this.VisitConditional((ConditionalExpression)x, (ConditionalExpression)y));
     382:  
     383:             case ExpressionType.Constant:
     384:                 return (this.VisitConstant((ConstantExpression)x, (ConstantExpression)y));
     385:  
     386:             case ExpressionType.Invoke:
     387:                 return (this.VisitInvocation((InvocationExpression)x, (InvocationExpression)y));
     388:  
     389:             case ExpressionType.Lambda:
     390:                 return (this.VisitLambda((LambdaExpression)x, (LambdaExpression)y));
     391:  
     392:             case ExpressionType.ListInit:
     393:                 return (this.VisitListInit((ListInitExpression)x, (ListInitExpression)y));
     394:  
     395:             case ExpressionType.MemberAccess:
     396:                 return (this.VisitMemberAccess((MemberExpression)x, (MemberExpression)y));
     397:  
     398:             case ExpressionType.MemberInit:
     399:                 return (this.VisitMemberInit((MemberInitExpression)x, (MemberInitExpression)y));
     400:  
     401:             case ExpressionType.New:
     402:                 return (this.VisitNew((NewExpression)x, (NewExpression)y));
     403:  
     404:             case ExpressionType.NewArrayInit:
     405:             case ExpressionType.NewArrayBounds:
     406:                 return (this.VisitNewArray((NewArrayExpression)x, (NewArrayExpression)y));
     407:  
     408:             case ExpressionType.Parameter:
     409:                 return (this.VisitParameter((ParameterExpression)x, (ParameterExpression)y));
     410:  
     411:             case ExpressionType.TypeIs:
     412:                 return (this.VisitTypeIs((TypeBinaryExpression)x, (TypeBinaryExpression)y));
     413:  
     414:             default:
     415:                 throw (new ArgumentException("Unhandled expression type"));
     416:         }
     417:     }
     418:  
     419:     private Boolean VisitUnary(UnaryExpression x, UnaryExpression y)
     420:     {
     421:         return ((x.Method == y.Method) &&
     422:                (this.Visit(x.Operand, y.Operand)));
     423:     }
     424:  
     425:     private Boolean VisitBinary(BinaryExpression x, BinaryExpression y)
     426:     {
     427:         return ((x.Method == y.Method) &&
     428:                (this.Visit(x.Left, y.Left)) &&
     429:                (this.Visit(x.Right, y.Right)) &&
     430:                (this.Visit(x.Conversion, y.Conversion)));
     431:     }
     432:  
     433:     private Boolean VisitMethodCall(MethodCallExpression x, MethodCallExpression y)
     434:     {
     435:         return ((x.Method == y.Method) &&
     436:                (this.Visit(x.Object, y.Object)) &&
     437:                (this.VisitExpressionList(x.Arguments, y.Arguments)));
     438:     }
     439:  
     440:     private Boolean VisitConditional(ConditionalExpression x, ConditionalExpression y)
     441:     {
     442:         return ((this.Visit(x.Test, y.Test)) &&
     443:                (this.Visit(x.IfTrue, y.IfTrue)) &&
     444:                (this.Visit(x.IfFalse, y.IfFalse)));
     445:     }
     446:  
     447:     private Boolean VisitConstant(ConstantExpression x, ConstantExpression y)
     448:     {
     449:         return (Object.Equals(x.Value, y.Value));
     450:     }
     451:  
     452:     private Boolean VisitInvocation(InvocationExpression x, InvocationExpression y)
     453:     {
     454:         return ((this.Visit(x.Expression, y.Expression)) &&
     455:                (this.VisitExpressionList(x.Arguments, x.Arguments)));
     456:     }
     457:  
     458:     private Boolean VisitLambda(LambdaExpression x, LambdaExpression y)
     459:     {
     460:         return ((this.Visit(x.Body, y.Body)) &&
     461:                (this.VisitParameterList(x.Parameters, y.Parameters)));
     462:     }
     463:  
     464:     private Boolean VisitListInit(ListInitExpression x, ListInitExpression y)
     465:     {
     466:         return ((this.VisitNew(x.NewExpression, y.NewExpression)) &&
     467:                (this.VisitElementInitializerList(x.Initializers, y.Initializers)));
     468:     }
     469:  
     470:     private Boolean VisitMemberAccess(MemberExpression x, MemberExpression y)
     471:     {
     472:         return ((x.Member == y.Member) &&
     473:                (this.Visit(x.Expression, y.Expression)));
     474:     }
     475:  
     476:     private Boolean VisitMemberInit(MemberInitExpression x, MemberInitExpression y)
     477:     {
     478:         return ((this.Visit(x.NewExpression, y.NewExpression)) &&
     479:                (this.VisitBindingList(x.Bindings, y.Bindings)));
     480:     }
     481:  
     482:     private Boolean VisitNew(NewExpression x, NewExpression y)
     483:     {
     484:         return ((x.Constructor == y.Constructor) &&
     485:                (this.VisitMemberList(x.Members, y.Members)) &&
     486:                (this.VisitExpressionList(x.Arguments, y.Arguments)));
     487:     }
     488:  
     489:     private Boolean VisitNewArray(NewArrayExpression x, NewArrayExpression y)
     490:     {
     491:         return (this.VisitExpressionList(x.Expressions, y.Expressions));
     492:     }
     493:  
     494:     private Boolean VisitParameter(ParameterExpression x, ParameterExpression y)
     495:     {
     496:         return ((x.Type == y.Type) && (x.IsByRef == y.IsByRef));
     497:     }
     498:  
     499:     private Boolean VisitTypeIs(TypeBinaryExpression x, TypeBinaryExpression y)
     500:     {
     501:         return ((x.TypeOperand == y.TypeOperand) &&
     502:                (this.Visit(x.Expression, y.Expression)));
     503:     }
     504:  
     505:     private Boolean VisitBinding(MemberBinding x, MemberBinding y)
     506:     {
     507:         if ((x.BindingType != y.BindingType) || (x.Member != y.Member))
     508:         {
     509:             return (false);
     510:         }
     511:  
     512:         switch (x.BindingType)
     513:         {
     514:             case MemberBindingType.Assignment:
     515:                 return (this.VisitMemberAssignment((MemberAssignment)x, (MemberAssignment)y));
     516:  
     517:             case MemberBindingType.MemberBinding:
     518:                 return (this.VisitMemberMemberBinding((MemberMemberBinding)x, (MemberMemberBinding)y));
     519:  
     520:             case MemberBindingType.ListBinding:
     521:                 return (this.VisitMemberListBinding((MemberListBinding)x, (MemberListBinding)y));
     522:  
     523:             default:
     524:                 throw (new ArgumentException("Unhandled binding type"));
     525:         }
     526:     }
     527:  
     528:     private Boolean VisitMemberAssignment(MemberAssignment x, MemberAssignment y)
     529:     {
     530:         return (this.Visit(x.Expression, y.Expression));
     531:     }
     532:  
     533:     private Boolean VisitMemberMemberBinding(MemberMemberBinding x, MemberMemberBinding y)
     534:     {
     535:         return (this.VisitBindingList(x.Bindings, y.Bindings));
     536:     }
     537:  
     538:     private Boolean VisitMemberListBinding(MemberListBinding x, MemberListBinding y)
     539:     {
     540:         return (this.VisitElementInitializerList(x.Initializers, y.Initializers));
     541:     }
     542:  
     543:     private Boolean VisitElementInitializer(ElementInit x, ElementInit y)
     544:     {
     545:         return ((x.AddMethod == y.AddMethod) &&
     546:                (this.VisitExpressionList(x.Arguments, y.Arguments)));
     547:     }
     548:  
     549:     private Boolean VisitExpressionList(ReadOnlyCollection<Expression> x, ReadOnlyCollection<Expression> y)
     550:     {
     551:         if (x == y)
     552:         {
     553:             return (true);
     554:         }
     555:  
     556:         if ((x != null) && (y != null) && (x.Count == y.Count))
     557:         {
     558:             for (Int32 i = 0; i < x.Count; i++)
     559:             {
     560:                 if (this.Visit(x[i], y[i]) == false)
     561:                 {
     562:                     return (false);
     563:                 }
     564:             }
     565:  
     566:             return (true);
     567:         }
     568:  
     569:         return (false);
     570:     }
     571:  
     572:     private Boolean VisitParameterList(ReadOnlyCollection<ParameterExpression> x, ReadOnlyCollection<ParameterExpression> y)
     573:     {
     574:         if (x == y)
     575:         {
     576:             return (true);
     577:         }
     578:  
     579:         if ((x != null) && (y != null) && (x.Count == y.Count))
     580:         {
     581:             for (Int32 i = 0; i < x.Count; i++)
     582:             {
     583:                 if (this.Visit(x[i], y[i]) == false)
     584:                 {
     585:                     return (false);
     586:                 }
     587:             }
     588:  
     589:             return (true);
     590:         }
     591:  
     592:         return (false);
     593:     }
     594:  
     595:     private Boolean VisitBindingList(ReadOnlyCollection<MemberBinding> x, ReadOnlyCollection<MemberBinding> y)
     596:     {
     597:         if (x == y)
     598:         {
     599:             return (true);
     600:         }
     601:  
     602:         if ((x != null) && (y != null) && (x.Count == y.Count))
     603:         {
     604:             for (Int32 i = 0; i < x.Count; i++)
     605:             {
     606:                 if (this.VisitBinding(x[i], y[i]) == false)
     607:                 {
     608:                     return (false);
     609:                 }
     610:             }
     611:  
     612:             return (true);
     613:         }
     614:  
     615:         return (false);
     616:     }
     617:  
     618:     private Boolean VisitElementInitializerList(ReadOnlyCollection<ElementInit> x, ReadOnlyCollection<ElementInit> y)
     619:     {
     620:         if (x == y)
     621:         {
     622:             return (true);
     623:         }
     624:  
     625:         if ((x != null) && (y != null) && (x.Count == y.Count))
     626:         {
     627:             for (Int32 i = 0; i < x.Count; i++)
     628:             {
     629:                 if (this.VisitElementInitializer(x[i], y[i]) == false)
     630:                 {
     631:                     return (false);
     632:                 }
     633:             }
     634:  
     635:             return (true);
     636:         }
     637:  
     638:         return (false);
     639:     }
     640:  
     641:     private Boolean VisitMemberList(ReadOnlyCollection<MemberInfo> x, ReadOnlyCollection<MemberInfo> y)
     642:     {
     643:         if (x == y)
     644:         {
     645:             return (true);
     646:         }
     647:  
     648:         if ((x != null) && (y != null) && (x.Count == y.Count))
     649:         {
     650:             for (Int32 i = 0; i < x.Count; i++)
     651:             {
     652:                 if (x[i] != y[i])
     653:                 {
     654:                     return (false);
     655:                 }
     656:             }
     657:  
     658:             return (true);
     659:         }
     660:  
     661:         return (false);
     662:     }
     663:     #endregion
     664:  
     665:     #region IEqualityComparer<Expression> Members
     666:     public Boolean Equals(Expression x, Expression y)
     667:     {
     668:         return (this.Visit(x, y));
     669:     }
     670:  
     671:     public Int32 GetHashCode(Expression expression)
     672:     {
     673:         this.hashCode = 0;
     674:  
     675:         this.Visit(expression);
     676:  
     677:         return (this.hashCode);
     678:     }
     679:     #endregion
     680: }

    This implementation disregards the lambda variable name, so that “x => …” is equal to “y => …”. Also, as you can see, this is not safe for multithreaded usage, because it uses an accumulator field (hashCode), where the hash for the expression currently being calculated is stored. Being an IEqualityComparer<Expression>, it implements both Equals and GetHashCode methods.

    Caching

    As for caching, I decided to use the MemoryCache implementation of an ObjectCache, available on .NET 4, this way I don’t have any external dependencies:

       1: public static class QueryableExtensions
       2: {
       3:     public static IQueryable<T> AsCacheable<T>(this IQueryable<T> queryable, TimeSpan duration)
       4:     {
       5:         return (AsCacheable(queryable, (Int32) duration.TotalSeconds));
       6:     }
       7:  
       8:     public static IQueryable<T> AsCacheable<T>(this IQueryable<T> queryable, Int32 durationSeconds)
       9:     {
      10:         ObjectCache cache = null;
      11:  
      12:         if (ObjectCache.Host != null)
      13:         {
      14:             cache = ObjectCache.Host.GetService(typeof(ObjectCache)) as ObjectCache;
      15:         }
      16:  
      17:         cache = cache ?? MemoryCache.Default;
      18:  
      19:         IQueryable<T> cachedQuery = new QueryableWrapper<T>(cache, queryable, durationSeconds);
      20:  
      21:         return (cachedQuery);
      22:     }
      23:  
      24:     public static IOrderedQueryable<T> AsCacheable<T>(this IOrderedQueryable<T> queryable, TimeSpan duration)
      25:     {
      26:         return (AsCacheable(queryable as IQueryable<T>, duration) as IOrderedQueryable<T>);
      27:     }
      28:  
      29:     public static IOrderedQueryable<T> AsCacheable<T>(this IOrderedQueryable<T> queryable, Int32 durationSeconds)
      30:     {
      31:         return (AsCacheable(queryable as IQueryable<T>, durationSeconds) as IOrderedQueryable<T>);
      32:     }
      33: }

    As you can see, we are free to supply out own ObjectCache implementation, provided we place a IServiceProvider implementation (UnityServiceLocator will do) on the ObjectCache.Host property and this implementation returns a valid ObjectCache instance. Feel free to replace this by any other similar mechanism!

    Preventing Multiple Query Executions

    So, when an IQueryable<T> is first executed, it will go to the database, or someplace else (just think WCF Data Services’ DataServiceQuery<T>), and return its results. If we are going to put that query in a cache, we want to prevent it from executing multiple times, otherwise the purpose of the cache would be defaced. For that, I built my own class that just inherits from IQueryable<T> (actually, from IOrderedQueryable<T>, for support of ordered queries) and overrides the IEnumerable<T> (of which IQueryable<T> descends) GetEnumerator method:

       1: sealed class QueryableWrapper<T> : IOrderedQueryable<T>
       2: {
       3:     private static readonly ExpressionEqualityComparer comparer = new ExpressionEqualityComparer();
       4:  
       5:     sealed class EnumeratorWrapper : IEnumerator<T>
       6:     {
       7:         private readonly LinkedList<T> list = new LinkedList<T>();
       8:         private QueryableWrapper<T> queryable;
       9:         private IEnumerator<T> enumerator;
      10:         private Boolean stored = false;
      11:         internal Boolean consumed;
      12:  
      13:         public EnumeratorWrapper(QueryableWrapper<T> queryable, IEnumerator<T> enumerator)
      14:         {
      15:             this.enumerator = enumerator;
      16:             this.queryable = queryable;
      17:         }
      18:  
      19:         internal IEnumerator<T> FromCache()
      20:         {
      21:             return (this.list.GetEnumerator());
      22:         }
      23:  
      24:         #region IEnumerator<T> Members
      25:  
      26:         public T Current
      27:         {
      28:             get
      29:             {
      30:                 T current = this.enumerator.Current;
      31:  
      32:                 if (this.stored == false)
      33:                 {
      34:                     this.list.AddLast(current);
      35:                     this.stored = true;
      36:                 }
      37:  
      38:                 return (current);
      39:             }
      40:         }
      41:  
      42:         #endregion
      43:  
      44:         #region IDisposable Members
      45:  
      46:         public void Dispose()
      47:         {
      48:             this.stored = false;
      49:             this.consumed = true;
      50:             this.enumerator.Dispose();
      51:         }
      52:  
      53:         #endregion
      54:  
      55:         #region IEnumerator Members
      56:  
      57:         Object IEnumerator.Current
      58:         {
      59:             get
      60:             {
      61:                 return (this.Current);
      62:             }
      63:         }
      64:  
      65:         public Boolean MoveNext()
      66:         {
      67:             Boolean result = this.enumerator.MoveNext();
      68:  
      69:             if (result == true)
      70:             {
      71:                 this.stored = false;
      72:             }
      73:  
      74:             return (result);
      75:         }
      76:  
      77:         public void Reset()
      78:         {
      79:             this.stored = false;
      80:             this.list.Clear();
      81:             this.enumerator.Reset();
      82:         }
      83:  
      84:         #endregion
      85:     }
      86:  
      87:     #region Private readonly fields
      88:     private readonly IQueryable<T> queryable;
      89:     private readonly ObjectCache cache;
      90:     private readonly Int32 durationSeconds;
      91:     #endregion
      92:  
      93:     #region Internal constructor
      94:     internal QueryableWrapper(ObjectCache cache, IQueryable<T> queryable, Int32 durationSeconds)
      95:     {
      96:         this.cache = cache;
      97:         this.queryable = queryable;
      98:         this.durationSeconds = durationSeconds;
      99:     }
     100:     #endregion
     101:  
     102:     #region IEnumerable<T> Members
     103:  
     104:     public IEnumerator<T> GetEnumerator()
     105:     {
     106:         IEnumerator<T> enumerator = null;
     107:         String key = this.GetKey(this.queryable).ToString();
     108:  
     109:         if (this.cache.Contains(key) == true)
     110:         {
     111:             //hit
     112:             enumerator = this.cache[key] as EnumeratorWrapper;
     113:             if ((enumerator as EnumeratorWrapper).consumed == true)
     114:             {
     115:                 return ((enumerator as EnumeratorWrapper).FromCache());
     116:             }
     117:         }
     118:         else
     119:         {
     120:             //miss
     121:             enumerator = new EnumeratorWrapper(this, this.queryable.GetEnumerator());
     122:             this.cache.Add(key, enumerator, DateTimeOffset.Now.AddSeconds(this.durationSeconds));
     123:         }
     124:  
     125:         return (enumerator);
     126:     }
     127:  
     128:     #endregion
     129:  
     130:     #region IEnumerable Members
     131:  
     132:     IEnumerator IEnumerable.GetEnumerator()
     133:     {
     134:         return (this.GetEnumerator());
     135:     }
     136:  
     137:     #endregion
     138:  
     139:     #region IQueryable Members
     140:  
     141:     public Type ElementType
     142:     {
     143:         get
     144:         {
     145:             return (this.queryable.ElementType);
     146:         }
     147:     }
     148:  
     149:     public Expression Expression
     150:     {
     151:         get
     152:         {
     153:             return (this.queryable.Expression);
     154:         }
     155:     }
     156:  
     157:     public IQueryProvider Provider
     158:     {
     159:         get
     160:         {
     161:             return (this.queryable.Provider);
     162:         }
     163:     }
     164:  
     165:     #endregion
     166:  
     167:     #region Private methods
     168:     private Int32 GetKey(IQueryable queryable)
     169:     {
     170:         return (comparer.GetHashCode(queryable.Expression));
     171:     }
     172:     #endregion
     173: }

    Putting It All Together

    This allows me to write code as this:

       1: //cache miss
       2: var q1 = ctx.Customers.Where(x => x.Orders.Any()).OrderBy(x => x.Name).AsCacheable(TimeSpan.FromSeconds(10)).ToList();
       3:  
       4: //cache hit
       5: var q2 = ctx.Customers.Where(o => o.Orders.Any()).OrderBy(x => x.Name).AsCacheable(TimeSpan.FromSeconds(10)).ToList();
       6:  
       7: //cache hit
       8: var q3 = (from c in ctx.Customers where c.Orders.Any() orderby c.Name select c).AsCacheable(TimeSpan.FromSeconds(10)).ToList();
       9:  
      10: Thread.Sleep(10000);
      11:  
      12: //cache miss
      13: var q4 = ctx.Customers.Where(x => x.Orders.Any()).OrderBy(x => x.Name).AsCacheable(TimeSpan.FromSeconds(10)).ToList();

    By calling the AsCacheable extension method, our LINQ queries get cached for the specified duration. This will work with any LINQ implementation.

    Read more...

  • Dynamic LINQ Extension Method

    Remember those old posts on Dynamic LINQ? You are probably aware that Microsoft has made its implementation available as a Nuget package, but, like I said, you already have it in your machine, hidden inside the System.Web.Extensions assembly.

    In order to make it easier to use, I wrote a simple extension method that works with plain old IQueryable<T>. And here it is:

       1: public static IQueryable<T> Where<T>(this IQueryable<T> query, String restriction, params Object[] values)
       2: {
       3:     Assembly asm = typeof(UpdatePanel).Assembly;
       4:     Type dynamicExpressionType = asm.GetType("System.Web.Query.Dynamic.DynamicExpression");
       5:     MethodInfo parseLambdaMethod = dynamicExpressionType.GetMethods(BindingFlags.Public | BindingFlags.Static).Where(m => (m.Name == "ParseLambda") && (m.GetParameters().Length == 2)).Single().MakeGenericMethod(typeof(T), typeof(Boolean));
       6:     Expression<Func<T, Boolean>> expression = parseLambdaMethod.Invoke(null, new Object[] { restriction, values }) as Expression<Func<T, Boolean>>;
       7:  
       8:     return (query.Where(expression));
       9: }

    It even supports parameters! Just two simple examples – I am using Entity Framework, but you can use whatever you like, this is totally generic:

       1: //without parameters
       2: var productsWithPriceGreaterThan100 = ctx.Products.Where("Price > 100").ToList();
       3:  
       4: //with parameters
       5: var productsWithPriceLowerThan100 = ctx.Products.Where("Price < @0", 100).ToList();

    To make it clear, all parameters must be indicated as @0, @1, and so on. It is better to use them, because the database engine can reuse the execution plan.

    There’s one limitation, though: you can’t compare each value on its own, you have to specify one of its properties. For example, you can’t have:

       1: var productNames = ctx.Products.Select(x => x.Name).Where("@it != @0", "Some Name").ToList();

    The @it parameter is not recognized, which is a pity.

    Make sure you have references to both System.Web and System.Web.Extensions, this is required, and won’t affect anything.

    As always, glad to be of service! Winking smile

    Read more...

  • Comparing LINQ Expressions

    Introduction

    I recently came upon this problem: how to calculate a hash from a LINQ expression so that I can safely compare two expressions for equality? I had naively assumed that the Expression class – and their descendants – would have implemented GetHashCode in an appropriate way, so as to make developer’s lifes easier, but unfortunately Microsoft thought otherwise.

    After looking it up on the Internet, I could see two “solutions”:

    • Convert the Expression to its string representation and get the hash code of it;
    • Use an ExpressionVisitor to visit all contained expressions and calculate their individual hash – if this seems recursive to you, that’s because it is!

    Comparing the String Representation

    The first “solution” doesn’t actually work, because two expressions might represent exactly the same and yet have different string representations. For example, consider:

       1: Expression<Func<Int32, Boolean>> isEven = x => (x % 2) == 0;

    and

       1: Expression<Func<Int32, Boolean>> isEven = n => (n % 2) == 0;

    The only thing that differentiates these two expressions is the name of the lambda parameter, unfortunately it causes their string representations to be different.

    One possible solution might be to use a regular expression to get all occurrences of lambda expressions, capture the name of the lambda variables, and then do a search and replace for some well known name:

       1: var original = expression.ToString();
       2: var replaced = original;
       3: var reParameterDeclaration = new Regex(@"(?<it>\w+)\s=>\s");
       4: var matches = reParameterDeclaration.Matches(original);
       5:  
       6: for (var i = 0; i < matches.Count; ++i)
       7: {
       8:     var match = matches[i];
       9:     var it = match.Groups[1].Value;
      10:  
      11:     replaced = Regex.Replace(replaced, String.Format(@"\b{0}\b", it), "it");
      12: }
      13:  
      14: Int32 hashCode = replaced.GetHashCode();

    At first sight – at least, for me! – this seemed to work, however, the replacement pattern – “get me all words composed of only the lambda variable” -  might match something that it wasn’t supposed to, for instance:

       1: //here it works
       2: Expression<Func<Int32, Boolean>> isEven = x => ((x % 2) == 0);
       3:  
       4: //here it doesn't, because the x inside the string is also matched
       5: Expression<Func<String, String>> x => "x y z";

    I might use a different replacement regular expression, for example, I could check for “all lambda variables followed by a dot (.)”:

       1: replaced = Regex.Replace(replaced, String.Format(@"\b{0}\.", it), "it");

    But this wouldn’t get code like this:

       1: //won't work because there's no dot after the lambda variable x
       2: var sortedNames = names.OrderBy(x => x);

    To call it off, I think it might be possible, but it is more complicated than it seems.

    Using an ExpressionVisitor

    The next approach involves using an ExpressionVisitor to visit all expressions contained in an Expression, something that I have talked before. The thing here is, an Expression is typically composed of several other expressions, of various kinds, so appropriate code must be used for each in order to get an univocal hash out of it. For example, for a ConstantExpression, we might consider its NodeType, Type and Value properties. The problem is, there are more than 20 Expression subclasses, and we need to do this for each.

    To cut things short, suppose we have implemented an hash code extractor for each Expression kind. We can’t simply have a big hash code by adding all hash codes calculated for each Expression fragment, because the order by which they appear is also important:

       1: //first take 10 elements and then sort them
       2: var pagedSortedNames = names.Take(10).OrderBy(x => x);
       3:  
       4: //first sort all elements then take 10 of them
       5: var sortedPagedNames = names.OrderBy(x => x).Take(10);

    So, each individual hash code must be take in order, and then we must get the hash code of the entire list of hash codes. Uff!

    Existing Implementations

    This problem exists since there are LINQ expressions, and, of course, other folks have come up with solutions. The NHibernate project has one, probably LINQ to SQL and Entity Framework have too, just to name those more close to me. However, I don’t think any of these solutions might be ready for external, general purpose usage outside their source projects. It would be great to have one such library that we could pick up and use, but I haven’t so far found any. Might be something to work on, though.

    What are your thoughts?

    Read more...

  • Intercepting LINQ Queries

    A common request when working with LINQ queries (Entity Framework, NHibernate, etc) is the ability to intercept them, that is, inspect an existing query and possibly modify something in it. This is not extremely difficult to do “by hand”, but Microsoft has a nice class called ExpressionVisitor which makes the job easier. It basically has virtual methods that get called whenever the class visits each expression contained in a greater expression, which may come from a query (the IQueryable interface exposes the underlying Expression in its Expression property). The virtual methods even allow returning a replacement for each expression found, the only problem is that you must subclass ExpressionVisitor to make even the slightest change, so I wrote my own class, which exposes all node traversal as events, one event for each kind of expression, where you can return an alternative expression, thus changing the original query. Here is the code for it:

       1: public sealed class ExpressionInterceptor : ExpressionVisitor
       2: {
       3:     #region Public events
       4:     public event Func<BinaryExpression, BinaryExpression> Binary;
       5:     public event Func<BlockExpression, BlockExpression> Block;
       6:     public event Func<CatchBlock, CatchBlock> CatchBlock;
       7:     public event Func<ConditionalExpression, ConditionalExpression> Conditional;
       8:     public event Func<ConstantExpression, ConstantExpression> Constant;
       9:     public event Func<DebugInfoExpression, DebugInfoExpression> DebugInfo;
      10:     public event Func<DefaultExpression, DefaultExpression> Default;
      11:     public event Func<DynamicExpression, DynamicExpression> Dynamic;
      12:     public event Func<ElementInit, ElementInit> ElementInit;
      13:     public event Func<Expression, Expression> Expression;
      14:     public event Func<Expression, Expression> Extension;
      15:     public event Func<GotoExpression, GotoExpression> Goto;
      16:     public event Func<IndexExpression, IndexExpression> Index;
      17:     public event Func<InvocationExpression, InvocationExpression> Invocation;
      18:     public event Func<LabelExpression, LabelExpression> Label;
      19:     public event Func<LabelTarget, LabelTarget> LabelTarget;
      20:     public event Func<LambdaExpression, LambdaExpression> Lambda;
      21:     public event Func<ListInitExpression, ListInitExpression> ListInit;
      22:     public event Func<LoopExpression, LoopExpression> Loop;
      23:     public event Func<MemberExpression, MemberExpression> Member;
      24:     public event Func<MemberAssignment, MemberAssignment> MemberAssignment;
      25:     public event Func<MethodCallExpression, MethodCallExpression> MethodCall;
      26:     public event Func<MemberInitExpression, MemberInitExpression> MemberInit;
      27:     public event Func<NewExpression, NewExpression> New;
      28:     public event Func<NewArrayExpression, NewArrayExpression> NewArray;
      29:     public event Func<ParameterExpression, ParameterExpression> Parameter;
      30:     public event Func<RuntimeVariablesExpression, RuntimeVariablesExpression> RuntimeVariables;
      31:     public event Func<SwitchExpression, SwitchExpression> Switch;
      32:     public event Func<TryExpression, TryExpression> Try;
      33:     public event Func<TypeBinaryExpression, TypeBinaryExpression> TypeBinary;
      34:     public event Func<UnaryExpression, UnaryExpression> Unary;
      35:     #endregion
      36:  
      37:     #region Public methods
      38:     public IQueryable<T> Visit<T>(IQueryable<T> query)
      39:     {
      40:         return (this.Visit(query as IQueryable) as IQueryable<T>);
      41:     }
      42:  
      43:     public IQueryable<T> Visit<T, TExpression>(IQueryable<T> query, Func<TExpression, TExpression> action) where TExpression : Expression
      44:     {
      45:         EventInfo evt = this.GetType().GetEvents(BindingFlags.Public | BindingFlags.Instance).Where(x => x.EventHandlerType == typeof(Func<TExpression, TExpression>)).First();
      46:         evt.AddEventHandler(this, action);
      47:  
      48:         query = this.Visit(query);
      49:  
      50:         evt.RemoveEventHandler(this, action);
      51:  
      52:         return (query);
      53:     }
      54:  
      55:     public IQueryable Visit(IQueryable query)
      56:     {
      57:         return (query.Provider.CreateQuery(this.Visit(query.Expression)));
      58:     }
      59:  
      60:     public IEnumerable<Expression> Flatten(IQueryable query)
      61:     {
      62:         Queue<Expression> list = new Queue<Expression>();
      63:         Func<Expression, Expression> action = delegate(Expression expression)
      64:         {
      65:             if (expression != null)
      66:             {
      67:                 list.Enqueue(expression);
      68:             }
      69:  
      70:             return (expression);
      71:         };
      72:  
      73:         this.Expression += action;
      74:  
      75:         this.Visit(query);
      76:  
      77:         this.Expression -= action;
      78:  
      79:         return (list);
      80:     }
      81:     #endregion
      82:  
      83:     #region Public override methods
      84:     public override Expression Visit(Expression node)
      85:     {
      86:         if ((this.Expression != null) && (node != null))
      87:         {
      88:             return(base.Visit(this.Expression(base.Visit(node))));
      89:         }
      90:         else
      91:         {
      92:             return (base.Visit(node));
      93:         }
      94:     }
      95:     #endregion
      96:  
      97:     #region Protected override methods
      98:     protected override Expression VisitNew(NewExpression node)
      99:     {
     100:         if ((this.New != null) && (node != null))
     101:         {
     102:             return (base.VisitNew(this.New(node)));
     103:         }
     104:         else
     105:         {
     106:             return (base.VisitNew(node));
     107:         }
     108:     }
     109:  
     110:     protected override Expression VisitNewArray(NewArrayExpression node)
     111:     {
     112:         if ((this.NewArray != null) && (node != null))
     113:         {
     114:             return (base.VisitNewArray(this.NewArray(node)));
     115:         }
     116:         else
     117:         {
     118:             return (base.VisitNewArray(node));
     119:         }
     120:     }
     121:  
     122:     protected override Expression VisitParameter(ParameterExpression node)
     123:     {
     124:         if ((this.Parameter != null) && (node != null))
     125:         {
     126:             return (base.VisitParameter(this.Parameter(node)));
     127:         }
     128:         else
     129:         {
     130:             return (base.VisitParameter(node));
     131:         }
     132:     }
     133:  
     134:     protected override Expression VisitRuntimeVariables(RuntimeVariablesExpression node)
     135:     {
     136:         if ((this.RuntimeVariables != null) && (node != null))
     137:         {
     138:             return (base.VisitRuntimeVariables(this.RuntimeVariables(node)));
     139:         }
     140:         else
     141:         {
     142:             return (base.VisitRuntimeVariables(node));
     143:         }
     144:     }
     145:  
     146:     protected override Expression VisitSwitch(SwitchExpression node)
     147:     {
     148:         if ((this.Switch != null) && (node != null))
     149:         {
     150:             return (base.VisitSwitch(this.Switch(node)));
     151:         }
     152:         else
     153:         {
     154:             return (base.VisitSwitch(node));
     155:         }
     156:     }
     157:  
     158:     protected override Expression VisitTry(TryExpression node)
     159:     {
     160:         if ((this.Try != null) && (node != null))
     161:         {
     162:             return (base.VisitTry(this.Try(node)));
     163:         }
     164:         else
     165:         {
     166:             return (base.VisitTry(node));
     167:         }
     168:     }
     169:  
     170:     protected override Expression VisitTypeBinary(TypeBinaryExpression node)
     171:     {
     172:         if ((this.TypeBinary != null) && (node != null))
     173:         {
     174:             return (base.VisitTypeBinary(this.TypeBinary(node)));
     175:         }
     176:         else
     177:         {
     178:             return (base.VisitTypeBinary(node));
     179:         }
     180:     }
     181:  
     182:     protected override Expression VisitUnary(UnaryExpression node)
     183:     {
     184:         if ((this.Unary != null) && (node != null))
     185:         {
     186:             return (base.VisitUnary(this.Unary(node)));
     187:         }
     188:         else
     189:         {
     190:             return (base.VisitUnary(node));
     191:         }
     192:     }
     193:  
     194:     protected override Expression VisitMemberInit(MemberInitExpression node)
     195:     {
     196:         if ((this.MemberInit != null) && (node != null))
     197:         {
     198:             return (base.VisitMemberInit(this.MemberInit(node)));
     199:         }
     200:         else
     201:         {
     202:             return (base.VisitMemberInit(node));
     203:         }
     204:     }
     205:  
     206:     protected override Expression VisitMethodCall(MethodCallExpression node)
     207:     {
     208:         if ((this.MethodCall != null) && (node != null))
     209:         {
     210:             return (base.VisitMethodCall(this.MethodCall(node)));
     211:         }
     212:         else
     213:         {
     214:             return (base.VisitMethodCall(node));
     215:         }
     216:     }
     217:  
     218:     
     219:     protected override Expression VisitLambda<T>(Expression<T> node)
     220:     {
     221:         if ((this.Lambda != null) && (node != null))
     222:         {
     223:             return (base.VisitLambda<T>(this.Lambda(node) as Expression<T>));
     224:         }
     225:         else
     226:         {
     227:             return (base.VisitLambda<T>(node));
     228:         }
     229:     }
     230:  
     231:     protected override Expression VisitBinary(BinaryExpression node)
     232:     {
     233:         if ((this.Binary != null) && (node != null))
     234:         {
     235:             return (base.VisitBinary(this.Binary(node)));
     236:         }
     237:         else
     238:         {
     239:             return (base.VisitBinary(node));
     240:         }
     241:     }
     242:  
     243:     protected override Expression VisitBlock(BlockExpression node)
     244:     {
     245:         if ((this.Block != null) && (node != null))
     246:         {
     247:             return (base.VisitBlock(this.Block(node)));
     248:         }
     249:         else
     250:         {
     251:             return (base.VisitBlock(node));
     252:         }
     253:     }
     254:  
     255:     protected override CatchBlock VisitCatchBlock(CatchBlock node)
     256:     {
     257:         if ((this.CatchBlock != null) && (node != null))
     258:         {
     259:             return (base.VisitCatchBlock(this.CatchBlock(node)));
     260:         }
     261:         else
     262:         {
     263:             return (base.VisitCatchBlock(node));
     264:         }
     265:     }
     266:  
     267:     protected override Expression VisitConditional(ConditionalExpression node)
     268:     {
     269:         if ((this.Conditional != null) && (node != null))
     270:         {
     271:             return (base.VisitConditional(this.Conditional(node)));
     272:         }
     273:         else
     274:         {
     275:             return (base.VisitConditional(node));
     276:         }
     277:     }
     278:  
     279:     protected override Expression VisitConstant(ConstantExpression node)
     280:     {
     281:         if ((this.Constant != null) && (node != null))
     282:         {
     283:             return (base.VisitConstant(this.Constant(node)));
     284:         }
     285:         else
     286:         {
     287:             return (base.VisitConstant(node));
     288:         }
     289:     }
     290:  
     291:     protected override Expression VisitDebugInfo(DebugInfoExpression node)
     292:     {
     293:         if ((this.DebugInfo != null) && (node != null))
     294:         {
     295:             return (base.VisitDebugInfo(this.DebugInfo(node)));
     296:         }
     297:         else
     298:         {
     299:             return (base.VisitDebugInfo(node));
     300:         }
     301:     }
     302:  
     303:     protected override Expression VisitDefault(DefaultExpression node)
     304:     {
     305:         if ((this.Default != null) && (node != null))
     306:         {
     307:             return (base.VisitDefault(this.Default(node)));
     308:         }
     309:         else
     310:         {
     311:             return (base.VisitDefault(node));
     312:         }
     313:     }
     314:  
     315:     protected override Expression VisitDynamic(DynamicExpression node)
     316:     {
     317:         if ((this.Dynamic != null) && (node != null))
     318:         {
     319:             return (base.VisitDynamic(this.Dynamic(node)));
     320:         }
     321:         else
     322:         {
     323:             return (base.VisitDynamic(node));
     324:         }
     325:     }
     326:  
     327:     protected override ElementInit VisitElementInit(ElementInit node)
     328:     {
     329:         if ((this.ElementInit != null) && (node != null))
     330:         {
     331:             return (base.VisitElementInit(this.ElementInit(node)));
     332:         }
     333:         else
     334:         {
     335:             return (base.VisitElementInit(node));
     336:         }
     337:     }
     338:  
     339:     protected override Expression VisitExtension(Expression node)
     340:     {
     341:         if ((this.Extension != null) && (node != null))
     342:         {
     343:             return (base.VisitExtension(this.Extension(node)));
     344:         }
     345:         else
     346:         {
     347:             return (base.VisitExtension(node));
     348:         }
     349:     }
     350:  
     351:     protected override Expression VisitGoto(GotoExpression node)
     352:     {
     353:         if ((this.Goto != null) && (node != null))
     354:         {
     355:             return (base.VisitGoto(this.Goto(node)));
     356:         }
     357:         else
     358:         {
     359:             return (base.VisitGoto(node));
     360:         }
     361:     }
     362:  
     363:     protected override Expression VisitIndex(IndexExpression node)
     364:     {
     365:         if ((this.Index != null) && (node != null))
     366:         {
     367:             return (base.VisitIndex(this.Index(node)));
     368:         }
     369:         else
     370:         {
     371:             return (base.VisitIndex(node));
     372:         }
     373:     }
     374:  
     375:     protected override Expression VisitInvocation(InvocationExpression node)
     376:     {
     377:         if ((this.Invocation != null) && (node != null))
     378:         {
     379:             return (base.VisitInvocation(this.Invocation(node)));
     380:         }
     381:         else
     382:         {
     383:             return (base.VisitInvocation(node));
     384:         }
     385:     }
     386:  
     387:     protected override Expression VisitLabel(LabelExpression node)
     388:     {
     389:         if ((this.Label != null) && (node != null))
     390:         {
     391:             return (base.VisitLabel(this.Label(node)));
     392:         }
     393:         else
     394:         {
     395:             return (base.VisitLabel(node));
     396:         }
     397:     }
     398:  
     399:     protected override LabelTarget VisitLabelTarget(LabelTarget node)
     400:     {
     401:         if ((this.LabelTarget != null) && (node != null))
     402:         {
     403:             return (base.VisitLabelTarget(this.LabelTarget(node)));
     404:         }
     405:         else
     406:         {
     407:             return (base.VisitLabelTarget(node));
     408:         }
     409:     }
     410:  
     411:     protected override Expression VisitListInit(ListInitExpression node)
     412:     {
     413:         if ((this.ListInit != null) && (node != null))
     414:         {
     415:             return (base.VisitListInit(this.ListInit(node)));
     416:         }
     417:         else
     418:         {
     419:             return (base.VisitListInit(node));
     420:         }
     421:     }
     422:  
     423:     protected override Expression VisitLoop(LoopExpression node)
     424:     {
     425:         if ((this.Loop != null) && (node != null))
     426:         {
     427:             return (base.VisitLoop(this.Loop(node)));
     428:         }
     429:         else
     430:         {
     431:             return (base.VisitLoop(node));
     432:         }
     433:     }
     434:  
     435:     protected override Expression VisitMember(MemberExpression node)
     436:     {
     437:         if ((this.Member != null) && (node != null))
     438:         {
     439:             return (base.VisitMember(this.Member(node)));
     440:         }
     441:         else
     442:         {
     443:             return (base.VisitMember(node));
     444:         }
     445:     }
     446:  
     447:     protected override MemberAssignment VisitMemberAssignment(MemberAssignment node)
     448:     {
     449:         if ((this.MemberAssignment != null) && (node != null))
     450:         {
     451:             return (base.VisitMemberAssignment(this.MemberAssignment(node)));
     452:         }
     453:         else
     454:         {
     455:             return (base.VisitMemberAssignment(node));
     456:         }
     457:     }
     458:     #endregion        
     459: }

    Yes, I know, I probably should have used properties instead of events, but that’s really not important.

    A simple example might be:

       1: ExpressionInterceptor interceptor = new ExpressionInterceptor();
       2: String[] lettersArray = new String[] { "A", "B", "C" };    //a data source
       3: IQueryable<String> lettersQuery = lettersArray.AsQueryable().Where(x => x == "A").OrderByDescending(x => x).Select(x => x.ToUpper());    //a silly query
       4: IQueryable<String> lettersInterceptedQuery = interceptor.Visit<String, MethodCallExpression>(lettersQuery, x =>
       5: {
       6:     if (x.Method.Name == "ToUpper")
       7:     {
       8:         //change from uppercase to lowercase
       9:         x = Expression.Call(x.Object, typeof(String).GetMethods().Where(y => y.Name == "ToLower").First());
      10:     }
      11:  
      12:     return (x);
      13: });
      14: lettersInterceptedQuery = interceptor.Visit<String, BinaryExpression>(lettersInterceptedQuery, x =>
      15: {
      16:     //change from qual to not equal
      17:     x = Expression.MakeBinary(ExpressionType.NotEqual, x.Left, x.Right);
      18:  
      19:     return (x);
      20: });
      21: IEnumerable<Expression> lettersExpressions = interceptor.Flatten(lettersQuery);    //all expressions found
      22: IEnumerable<String> lettersList = lettersQuery.ToList();    //"A"
      23: IEnumerable<String> lettersInterceptedList = lettersInterceptedQuery.ToList();    //"c", "b"

    You see, I have methods that visit both an IQueryable, an IQueryable<T> or an Expression, and there is even an inline version that takes a Func<TExpression, TExpression> for even easier usage.

    As always, hope you find it useful!

    Read more...

  • Querying Entity Framework Code First Inheritance

    This is a short post to complement my previous one on Entity Framework Code First Inheritance: how to query for a specific class. The options are:

    1. From the DbContext collection:
         1: IEnumerable<DerivedA> derived = ctx.Bases.OfType<DerivedA>().ToList();
    2. From the inner ObjectContext, using Entity SQL and the OFTYPE operator:
         1: IEnumerable<DerivedA> derived = (ctx as IObjectContextAdapter).ObjectContext.CreateQuery<DerivedA>("SELECT VAlUE b FROM OFTYPE(Bases, MyNamespace.DerivedA) AS b").OfType<DerivedA>().ToList();
    3. Also in Entity SQL, using TREAT and IS OF:
         1: IEnumerable<DerivedA> derived = (ctx as IObjectContextAdapter).ObjectContext.CreateQuery<DerivedA>("SELECT VAlUE TREAT(b AS MyNamespace.DerivedA) FROM Bases AS b WHERE b IS OF (ConsoleApplication1.DerivedA)").OfType<DerivedA>().ToList();
    4. Using LINQ to Entities:
         1: IEnumerable<DerivedA> derived = (from d in ctx.Bases where d is DerivedA select d as DerivedA).ToList();
    5. Using pure SQL:
         1: IEnumerable<DerivedA> derived = ctx.Database.SqlQuery<DerivedA>("SELECT * FROM Bases AS b WHERE b.Discriminator = 'DerivedA'").ToList();

    Read more...

  • My All Time Favorite Posts

    Since this blog started, back in 2008, I wrote a lot of posts. I’d say some are still up to date. I picked a few of them, those I’m more proud of, in no particular order.

    ASP.NET Web Forms:

    ASP.NET MVC:

    NHibernate:

    .NET:

    Let me know what you think of them! Are there others you particularly enjoyed?

    Read more...

  • Strongly Typed Delete With NHibernate

    To my great satisfaction, LINQ is nowadays present everywhere, from XML processing, to database querying, including SharePoint. The “Q” in it standing for Query, it’s not a surprise that is mainly being used for querying, but it would be interesting to use it for other scenarios, such as updating and deleting.

    Read more...