17
www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

Embed Size (px)

Citation preview

Page 1: Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

www.itu.dk

Advanced C#, part IVNiels Hallenberg

IT University of Copenhagen(With thanks to

Peter Sestoft and Kasper Østerbye)

BAAAP – Spring 2009

Page 2: Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

www.itu.dk

Outline

Advanced C#, Part IV

• Basic LINQ– Deferred Queryies

Page 3: Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

www.itu.dk

Deferred Query• The following query is executed when iterating through

the list.

var xs = new string[] {"hii", "there", null, "are", "you"};Console.WriteLine("Before Where() is called.");IEnumerable<String> xs3 = xs.Where(s => s.Length == 3);Console.WriteLine("After Where() is called.");try { foreach (var x in xs3) Console.WriteLine("Processing " + x);} catch (Exception e) { Console.WriteLine("Got exception " + e);}

• Project example: LINQ04.sln

Page 4: Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

www.itu.dk

Deferred Query• Another example of a deferred query – where the

underlying data source is changed.

var intxs = new int[] { 1, 2, 3 };IEnumerable<int> ints = intxs.Select(i => i);foreach (var i in ints) Console.WriteLine("i = " + i);intxs[1] = 42;Console.WriteLine("-------------");foreach (var i in ints) Console.WriteLine("i = " + i);

• Project example: LINQ04.sln

Page 5: Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

www.itu.dk

Deferred Query

• The IEnumerable extension methods are lazy• So a query is executed only – and once every

time – the result is demanded:

int[] numbers = new int[] { 5, 4, 1, 3, 9 };int i = 0;var q = from n in numbers select new { n, i = ++i };foreach (var v in q) Console.WriteLine(v);foreach (var v in q) Console.WriteLine(v);

{ n = 5, i = 1 }{ n = 4, i = 2 }{ n = 1, i = 3 }{ n = 3, i = 4 }{ n = 9, i = 5 }{ n = 5, i = 6 }{ n = 4, i = 7 }{ n = 1, i = 8 }{ n = 3, i = 9 }{ n = 9, i = 10 }

Page 6: Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

www.itu.dk

Translation of group by

• The query

is expanded to

from x in xs group x by e

xs.GroupBy(x => e)

Page 7: Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

www.itu.dk

Extension methods for grouping

• As list comprehension– Compute ks = distinct([ h(x) | x <- xs ])– Return [ (k, [ x | x <- xs, h(x)=k ]) | k <- ks ]

• A grouping is an enumerable with a key:

IEnumerable<IGrouping<K,T>> GroupBy<T,K>(this IEnumerable<T> xs, Func<T,K> h)

interface IGrouping<K,T> : IEnumerable<T> { K Key { get; }}

var xs = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};var gs = xs.GroupBy(i => i < 5 ? "A" : "B");foreach (var g in gs) Console.WriteLine("g = (" + g.Key + ",[" + g.toString() + "])");

• Project example: LINQ05.sln

Page 8: Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

www.itu.dk

Translations of join

• The query

is expanded to

from x in xs join y in ys on kx equals kyselect e

xs.Join(ys, x => kx, y => ky, (x,y) => e)

• The query

is expanded to

from x in xs join y in ys on kx equals ky into zselect e

xs.GroupJoin(ys, x => kx, y => ky, (x,z) => e)

Page 9: Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

www.itu.dk

Extension methods for join 1

• As list comprehension: [ g(x,y) | x <- xs, y <- ys, fx(x)=fy(y) ]

• Efficient even on enumerables (I guess):– Make multidictionary fx(x) -> x for all x in xs– For each y in ys compute fy(y), look up matching

x values, for each of them yield g(x,y)

IEnumerable<V> Join<T,U,K,V>(this IEnumerable<T> xs, IEnumerable<U> ys,

Func<T,K> fx, Func<U,K> fy, Func<T,U,V> g)

Page 10: Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

www.itu.dk

Extension methods for join 2

• As list comprehension: [ g(x, [y | y <- ys, fx(x)=fy(y) ]) | x <- xs ]

IEnumerable<V> GroupJoin<T,U,K,V> (this IEnumerable<T> xs, IEnumerable<U> ys, Func<T,K> fx, Func<U,K> fy, Func<T,IEnumerable<U>,V> g)

Page 11: Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

www.itu.dk

Order weekday distribution by weekday

{ Key = Sunday, Count = 95 }{ Key = Monday, Count = 52 }{ Key = Tuesday, Count = 15 }{ Key = Wednesday, Count = 17 }{ Key = Thursday, Count = 60 }{ Key = Friday, Count = 61 }{ Key = Saturday, Count = 18 }

var holidayWeekDays = from dt in DateTimeExtensions.holidays.Keys group dt by dt.DayOfWeek into g orderby g.Key select new { g.Key, Count = g.Count() };

Page 12: Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

www.itu.dk

Translation of orderby

• The query

is expanded to

from x in xsorderby k1, k2, ...

xs.OrderBy(x => k1) .ThenBy(x => k2) . ...

Page 13: Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

www.itu.dk

Extension methods for ordering

• Order xs by ascending h(x)

• An ordered enumerable – remembers its previous ordering criteria– supports ordering by further (secondary) criteria

while respecting previous criteria

IOrderedEnumerable<T> OrderBy<T,K>(this IEnumerable<T> xs, Func<T,K> h)

IOrderedEnumerable<T> ThenBy<K>(this IOrderedEnumerable<T> xs, Func<T,K> h)

Page 14: Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

www.itu.dk

Expression trees• Covers C# expressions except assignment• An expression tree can be compiled into SQL• A function can be called but not inspected:

Func<int,int> f = x => 3*x;int res = f(7);

Expression<Func<int,int>> t = x => 3*x;

• An expression tree can be inspected:

=>

x

x3

*t =

Abstract syntax for lambdax => 3 * x

Page 15: Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

www.itu.dk

From lambda to expression tree

• A lambda may convert to expression tree at assignment to variable, field or parameter

bool Where(Expression<Func<int,bool>> p) {…}

bool foo = Where(z => z>42);

• p will be a tree, not a function

• The tree may be analysed by the Where method

=>

z

42z

>

Page 16: Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

www.itu.dk

Linq to relational databases

• For Linq to collections (or in-memory XML), enumerable extension methods are efficient

• For Linq to relational database, they aren’t• Instead,

– the query gets rewritten to method calls, as usual– the System.Linq.Data.Table.Where method is Where(Expression<Func<T,bool>> p)

– it captures the predicate p as an expression tree and rewrites it to an SQL fragment

– same for Select, Join, GroupBy, OrderBy, ThenBy– The DB server executes SQL and returns results

• Works even if the delegates involve local (client-side) computation, but may be slow

Page 17: Www.itu.dk Advanced C#, part IV Niels Hallenberg IT University of Copenhagen (With thanks to Peter Sestoft and Kasper Østerbye) BAAAP – Spring 2009

www.itu.dk

Linq samples in VS2008

• Go Help > Samples > CSharpSamples > LinqSamples > SampleQueries

• Build and run project SampleQueries• Shows the SQL generated by Linq to SQL• See 101+ Linq to Sql Query Samples

• If not installed, then first – go Help > Samples > local Samples folder > unzip CSharpSamples.zip

– install in Program Files\Microsoft Visual Studio 9.0\Samples\1033\CSharpSamples\