Pages

Tuesday, February 26, 2013

Slides + Code from LINQ Presentation



You can get the accompanying source from the presentation here (includes solution and project, just browse upward in the directory).

In the 10 examples you learn how to

1.  Create a query
2.  Create a query and have it produce a result
3.  Treat an expression predicate as a value
4.  Compile an expression tree to IL
5.  Use LINQ to objects
6.  Build a dynamic expression tree
7.  Compose Queries

Possible future additions : Discuss yield keyword, discuss LINQKit for composability

Code for main program embedded below as well



   1:  using System;
   2:  using System.Collections.Generic;
   3:  using System.Linq;
   4:  using System.Text;
   5:  using System.Threading.Tasks;
   6:  using System.Linq.Expressions;
   7:   
   8:  namespace PresentationV12
   9:  {
  10:      class Program
  11:      {
  12:          static void Main(string[] args)
  13:          {
  14:              #region Example 1 LINQ Query
  15:              using (var repository = new Database1Entities())
  16:              {
  17:                  var query = repository.Users.Where(user => user.UserId == 1);
  18:              }
  19:              #endregion
  20:   
  21:              #region Example 2 LINQ With Result
  22:   
  23:              using (var repository = new Database1Entities())
  24:              {
  25:                  var usr = repository.Users.Where(user => user.Username.EndsWith("Brian")).FirstOrDefault();
  26:              }
  27:              #endregion
  28:   
  29:              #region Example 3 Expression
  30:   
  31:              using (var repository = new Database1Entities())
  32:              {
  33:                  Expression<Func<User, bool>> expression = user => user.UserId != 5;
  34:   
  35:                  //Entity framework does similar parsing to the below and translates the expression to SQL
  36:                  ParameterExpression param = (ParameterExpression)expression.Parameters[0];
  37:                  BinaryExpression operation = (BinaryExpression)expression.Body;
  38:                  var left = operation.Left;
  39:                  var right = operation.Right;
  40:   
  41:                  var usr = repository.Users.Where(expression).FirstOrDefault();
  42:              }
  43:              #endregion
  44:   
  45:              #region Example 4 Not using Expressions - LINQ To objects
  46:              using (var repository = new Database1Entities())
  47:              {
  48:                  //Extension for IQueryable
  49:                  var usrs = repository.Users.Where(user => user.UserId != 5).ToList();
  50:   
  51:                  //Different extension method, IEnumerable.  
  52:                  var user2ndQuery = usrs.Where(user => user.UserId != 6);
  53:              }
  54:              #endregion
  55:   
  56:              #region Example 5 Compiling Expression Tree
  57:   
  58:              using (var repository = new Database1Entities())
  59:              {
  60:                  Expression<Func<User, bool>> expression = user => user.UserId != 5;
  61:   
  62:                  var usrs = repository.Users.ToList();
  63:   
  64:                  //Can't query objects with Expression<Func<User, bool>> expression
  65:                  //Error - var user2ndQuery = usrs.Where(expression);
  66:   
  67:                  //But you can reuse that expression like this to do that v
  68:                  var compiledExpression = expression.Compile();
  69:                  var user2ndQuery = usrs.Where(compiledExpression);
  70:              }
  71:              #endregion
  72:   
  73:              #region Example 6 Building a dynamic Expression tree 
  74:    
  75:              var param1 = Expression.Parameter(typeof(User), "user"); 
  76:              var prop = Expression.Property(param1, "UserId");
  77:              var Right = Expression.Constant(5);
  78:              BinaryExpression expr = Expression.MakeBinary(ExpressionType.NotEqual, prop, Right);
  79:   
  80:              var userExpression = Expression.Lambda<Func<User, bool>>(
  81:                  expr,
  82:                  param1
  83:                  ).Compile();
  84:   
  85:              using (var repository = new Database1Entities())
  86:              {
  87:                  var usr = repository.Users.Where(userExpression).ToList();
  88:              }
  89:   
  90:              #endregion
  91:   
  92:              #region My Number 1 Tip for writing good LINQ
  93:              //Compose your queries so you don't repeat yourself
  94:              //Lack of easy composability in SQL is the worst crux of writing SQL
  95:              //If you're copying and pasting a lot, you're doing it wrong
  96:              using (var repository = new Database1Entities())
  97:              {
  98:                  var userQuery = repository.Users
  99:                      .Where(UserNotTwo())
 100:                      .Where(UserNotBrian()).Where(NewMethod());
 101:   
 102:                  var usrList = userQuery.ToList(); //lazy evaluation "combines" both criteria 
 103:              }
 104:              #endregion
 105:   
 106:              #region SelectMany Flattening
 107:              //Flattens collections of collections
 108:              //Fairly common for a collection to contain collections with navigation properties in Entity Framework
 109:              //Necessary because there's no looping in a single LINQ expression--You'd have to bring the data down and loop yourself
 110:              //http://blog.falafel.com/Blogs/adam-anderson/2010/06/29/Flatten_Nested_Loops_with_LINQ_and_SelectMany
 111:   
 112:              using (var repository = new Database1Entities())
 113:              {
 114:                  var complexList = new List<List<string>>() { new List<string> { "test", "test2" }, new List<string> { "test3", "test4" } };
 115:                  var easyList = complexList.SelectMany(lst => lst);
 116:                  
 117:                  var superComplexList = new List<List<object>>() { new List<object> { "test", "test2", 25 }, new List<object> { "test3", "test4", new List<string>{ "test"} } };
 118:                  var kindOfEasyList = superComplexList.SelectMany(lst => lst);
 119:              }
 120:              #endregion
 121:          }
 122:   
 123:          private static Expression<Func<User, bool>> NewMethod()
 124:          {
 125:              return tt => tt.Email != "brian.rosamilia@gmail.com";
 126:          }
 127:   
 128:          #region Helper Functions
 129:          private static Expression<Func<User, bool>> UserNotBrian()
 130:          {
 131:              return usr => usr.FirstName != "brosamilia@example.com";
 132:          }
 133:   
 134:          private static Expression<Func<User, bool>> UserNotTwo()
 135:          {
 136:              return user => user.UserId != 2;
 137:          }
 138:          #endregion
 139:      }
 140:  }

2 comments:

  1. Nice coding presentation. It is simple and understandable.
    Learnpact
    php training

    ReplyDelete
  2. Great stuff.
    Keep it up.

    [url=http://www.learnpact.com]Learnpact[/url]

    ReplyDelete