Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to...

40
Putting it all together: LINQ as an Example

Transcript of Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to...

Page 1: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

Putting it all together:LINQ as an Example

Page 2: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

The Problem: SQL in Code

• Programs often connect to database servers.• Database servers only “speak” SQL.• Programs have to construct SQL strings.• PHP example:

if (some_condition()) {

$q = mysql_query(“select name from user were id = $id”)

...

}

• When will the problem be detected?

2

Page 3: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

3

Searching in Collections

• Begin with a simple array of, say, Customers.

Customer[] customers = new Customer[30];

customers[0] = new Customer(…);

customers[29] = new Customer(…);

Page 4: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

4

Searching in Collections:The Old Way

• Find the names of all London customers:

List<string> londoners = new List<string>();

foreach (Customer c in customers) {if (c.City == “London”) {

londoners.add(c.Name);}

}

Page 5: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

5

Searching in Collections:The LINQ Way

string[] londoners =

from c in customers

where c.City == “London”

select c.Name;Declarative!

SQL-like!

No loops!

Returns a simple array!

Page 6: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

Searching in Collections:The LINQ Way

• LINQ is a C# feature– Introduced in C# 3.0.

• LINQ = “Language INtegrated Query”

• So far, this is just list comprehension added to C#.

• What did it take to add list comprehension to the language?

Page 7: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

7

LINQ: How Does It Work?

• LINQ syntax = shorthand for method invocation.

• Syntactic sugar, using “Translation maps”

Page 8: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

8

Syntax Translation Example

string[] londoners =

from c in customers

where c.City == “London”

select c.Name;

string[] londoners =

customers.

Where(expression).

Select(expression);

Page 9: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

9

Expressions == Methods?

• Where() wants a Boolean method.

• The method acts as a filter.

• Likewise for Select(): a translation method.

Page 10: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

10

Translating Expressions

• Problem: Translating

“c.City == “London””

to a boolean expression e, such that Where(e) is valid?

Page 11: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

11

C# Delegates

• C# delegates: method pointers.• Since C# 1.0.

class Demo {delegate void Foo();void Bar() { … do something … };void Test() {

Foo myDelegate = new Foo(Bar); // “pointer” to Bar()myDelegate(); // invoke

}}

Page 12: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

12

Delegates as Arguments

• Delegates can be passed as arguments.– Event handlers, jobs for threads, etc.

class Demo {void Job() { … the job to carry out … };void Test() {

Thread worker = new Thread(new ThreadStart(Job));

worker.start();}

}

Page 13: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

13

Anonymous Methods

• Nameless methods = on-the-fly delegates:

class Demo {delegate void Foo();void Test() {

Foo myDelegate = delegate() { … do something …

}; myDelegate(); // invoke

}}

Page 14: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

14

Syntax Translation Example

string[] londoners =

from c in customers

where c.City == “London”

select c.Name;

string[] londoners =

customers.

Where(delegate(Customer c) {

return c.City == “London”; }).

Select(delegate(Customer c) {

return c.Name });

Page 15: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

15

Well, Not Really.

•Where(), etc. accept delegate methods.

• But LINQ creates lambda expressions.

• Seamless conversion via coercion.

Page 16: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

16

Syntax Translation Example

string[] londoners =

from c in customers

where c.City == “London”

select c.Name;

string[] londoners =

customers.

Where(c => c.City == “London”).

Select(c => c.Name);

Page 17: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

17

Lambda Expressions

• Lambda expression syntax:

(argumentList) => expressiononeArgument => expression

• Arguments optionally typed.– Type inference mechanism.– More on that later…

Shades of ML…

Page 18: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

18

Where’s Where()?

• We invoked Where() on Customers[].

• On the resulting Customers[], we invoked Select().

• New methods for arrays!?

Page 19: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

19

Extension Methods

class Utils {

public static firstChar(this string s)

{

return s.charAt(0);

}

}

• So far, just a simple static method.

• Can be used like any other.

Page 20: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

20

Extension Methods

• But now…

Using Utils;

class Demo {

void Foo() {

string s = “Hello”;

Console.WriteLine(s.firstChar());

}

}

Page 21: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

21

Extension Methods

• Static methods that seem to extend existing types.

• Where(), Select(), etc. extend array types in this manner.

Page 22: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

22

Query Your Own Types!

• LINQ can be applied to any type, not just built-in arrays and lists.

• Just implement Where(), Select(), etc.

Page 23: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

23

LINQ and Relational Data

• Let’s obtain a DB-table type, and query it.

DbCustomers customers = new DbCustomers(“my.mdb”);

string[] londoners =

from c in customers

where c.City == “London”

select c.Name;

Page 24: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

24

This Makes No Sense!

• But… Where() applies the filter to every record.

• … on the client!

• SELECT * FROM CUSTOMERS, and filter with a simple loop!?

Page 25: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

25

Back To Lambda Expressions

• Lambda expressions can be converted to anonymous methods.

• Can also be coerced to expression trees.– A run-time representation of the

syntax tree.

Page 26: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

26

Example…• Our code yields:

string[] londoners = customers.

Where(c => c.City == “London”).

Select(c => c.Name);

where “customers” is of type DbCustomers.• No

DbCustomers.Where(delegate(Customer c)) method exists.

• However:

DbCustomers.Where(

Expression<Func<Customer,bool>> xt)

Page 27: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

27

What Are Expression Trees?

• Any valid expression is converted by the compiler to an expression tree.– a.k.a. the abstract syntax tree of the expression.– Normal part of the compilation process, in any language!

• Examples:

5 + 3 * 2 c.city == “London”+

5 *

3 2

==

. (dot) “London”

c city

Page 28: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

28

Expression Trees

• Normally, expression trees only exist at compile-time.

• In C#, the compiler can create a run-time representation of the expression tree.– The language has a data type for expression trees.

– Represents lambda expressions at runtime.

• Used for generating SQL at runtime.– Guaranteed to be syntactically valid, since it

was created from a valid C# expression.

Page 29: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

It’s Just Coercion

• So, LINQ converts into expressions that use Where(...), Select(...), etc.

• For some classes, Where(...) and Select(...) accept delegates; for other classes, they accept expression trees.

• Lambda expressions can be coerced into either.

29

Page 30: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

30

Projections

• Using LINQ’s select:

from c in customers

where c.City == “London”

select

new AddressBookEntry(c.Name, c.Phone);

Page 31: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

31

Pre-Defined Types Only?

• But…

The projection type (e.g., AddressBookEntry) must be pre-defined!

Page 32: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

32

Ad-Hoc Types

• new { [name1 =] expr1,…, [ namen =] exprn}

• Type implied by types of exprs.

• Example:

from c in customerswhere c.City == “London”select new { c.Name, c.Phone };

If name is not specified, and expr is either property or x.property, then property’s

name will be used.

Page 33: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

33

Ad-Hoc Types are Nameless

• How do we store the result???? q = from … select new {…};

• The ad-hoc type is nameless!

Page 34: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

34

Auto-Typed Variables

• var x = 7; // x will be of type int

• var q = from … select new {…};// q will be an array of the anonymous typeConsole.WriteLine(q[0].Name);

• Local variables only.– No auto-typing for fields or formal parameters.

Page 35: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

Summary

• LINQ adds static SQL expression correctness to C#.

• To do this, the following features were added to C#:– Lambda expressions.– Extension methods.– Expression types.– List comprehension.– Anonymous data types.– Type inference.

35

Page 36: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

There’s More

• There are several LINQ features we did not present here, such as:– Grouping (“GROUP BY” in SQL)– Joins (selecting from multiple tables)– ...

• These require even more language features, such as closures.

36

Page 37: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

What Is Happening to Languages?

• As new features are added to programming languages, the languages evolve.

• Many of the features come from research or experimental languages.

• Note how many of the new C# features discussed here come from functional languages like ML, Haskell or LISP:– Lambda expressions, expression types, list

comprehension, anonymous data types, type inference...

37

Page 38: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

“Confessions of a Used Programming Language Salesman”

• An 2007 essay by Eric Meijer (Microsoft).• Discusses how features from functional

languages slowly creep into “mainstream” languages.

• “Functional programming has finally reached the masses, except that it is called Visual Basic 9 instead of Haskell 98”.

38

Page 39: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

A Glimpse Into the Future: LISP (1958)

• We have seen the power of representing program source at runtime (expression trees).

• In LISP, program source can be represented at runtime, but also generated at runtime (or compile-time).– Source code itself is a data structure (a list).

• LISP macros are light-years ahead of C/C++ macros.

39

Page 40: Putting it all together: LINQ as an Example. The Problem: SQL in Code Programs often connect to database servers. Database servers only “speak” SQL. Programs.

A Glimpse Into the Future: LISP (1958)

• 50 years later, LISP features are slowly re-appearing in mainstream languages.– e.g., garbage collection, aspect-oriented

programming, and more.• Conclusions:

– a. Learn from history.– b. Know LISP, Haskell, etc: once you really

understand them, it will give you serious advantages over ignorant software engineers (even if you never use these languages in practice).

40