c# 3.0 & linq raimond brookman – it architect

30

Post on 19-Dec-2015

219 views

Category:

Documents


2 download

TRANSCRIPT

C# 3.0 & LINQ

Raimond Brookman – IT Architecthttp://blogs.infosupport.com/raimondb

Outline

- Linq Project- DLinq- XLinq- C# 3.0 Language Enhancements

Problem:Problem:Data != ObjectsData != Objects

Service based Solution

Customer Mgt Customer Mgt ServiceService

(HTTP + XML)(HTTP + XML)

WebWebApplicationApplication

Order MgtOrder MgtWSWS

Order ProcessingOrder ProcessingWSWS

ORM

Xml R/W

Databound grid

BR Check

TransformMsg

<book> <title/> <author/> <year/> <price/></book>

XML ConfigXML Config

XmlRead

The LINQ Project

StandardStandardQueryQuery

OperatorsOperators

ObjectsObjects

DLinqDLinq(ADO.NET)(ADO.NET)

XLinqXLinq(System.Xml)(System.Xml)

<book> <title/> <author/> <year/> <price/></book>

XMLXML

.NET Language Integrated Query.NET Language Integrated Query

C# 3.0C# 3.0 VB 9.0VB 9.0 Others…Others…

SQLSQL WinFWinFSS

Service based Solution with LINQ

Customer Mgt Customer Mgt ServiceService

(HTTP + XML)(HTTP + XML)

WebWebApplicationApplication

Order MgtOrder MgtWSWS

Order ProcessingOrder ProcessingWSWS

ORM

Xml R/W

Databound grid

BR Check

TransformMsg

<book> <title/> <author/> <year/> <price/></book>

XML ConfigXML Config

XmlRead

DLINQ

O-LINQ

O-LINQXLINQ

XLINQ

O-LINQ

LINQ Style programming

var contacts =var contacts = from c in customersfrom c in customers where c.State == "WA"where c.State == "WA" select new { c.Name, c.Phone };select new { c.Name, c.Phone };

class Contact { … };class Contact { … };List<Contact> contacts = new List<Contacts>();List<Contact> contacts = new List<Contacts>();foreach(Customer c in customers) foreach(Customer c in customers) {{

if(c.State == “WA”) if(c.State == “WA”) {{ Contact ct = new Contact();Contact ct = new Contact(); ct.Name = c.Name;ct.Name = c.Name; ct.Phone = c.Phone;ct.Phone = c.Phone; contacts.Add(ct);contacts.Add(ct);}}

}}

Query Expressions

Language integrated query syntax

fromfrom idid inin sourcesource{ { fromfrom idid inin sourcesource | | wherewhere conditioncondition } }[ [ orderbyorderby orderingordering, , orderingordering, … ], … ]selectselect exprexpr | | groupgroup exprexpr byby keykey[ [ intointo idid queryquery ] ]

Standard Query Operators

RestrictionRestriction WhereWhere

ProjectionProjection Select, SelectManySelect, SelectMany

OrderingOrdering OrderBy, ThenByOrderBy, ThenBy

GroupingGrouping GroupByGroupBy

QuantifiersQuantifiers Any, AllAny, All

PartitioningPartitioning Take, Skip, TakeWhile, SkipWhileTake, Skip, TakeWhile, SkipWhile

SetsSets Distinct, Union, Intersect, ExceptDistinct, Union, Intersect, Except

ElementsElements First, FirstOrDefault, ElementAtFirst, FirstOrDefault, ElementAt

AggregationAggregation Count, Sum, Min, Max, AverageCount, Sum, Min, Max, Average

ConversionConversion ToArray, ToList, ToDictionaryToArray, ToList, ToDictionary

CastingCasting OfType<T>OfType<T>

DLinq For Relational Data

SqlConnection c = new SqlConnection(…);SqlConnection c = new SqlConnection(…);c.Open();c.Open();SqlCommand cmd = new SqlCommand(SqlCommand cmd = new SqlCommand( @"@"SELECT c.Name, c.PhoneSELECT c.Name, c.Phone FROM Customers cFROM Customers c WHERE c.City = @p0WHERE c.City = @p0");");cmd.Parameters.AddWithValue("cmd.Parameters.AddWithValue("@p0@p0", ", "London“);"London“);DataReader dr = c.Execute(cmd);DataReader dr = c.Execute(cmd);while (dr.Read()) {while (dr.Read()) { string name = dr.GetString(0);string name = dr.GetString(0); string phone = dr.GetString(1);string phone = dr.GetString(1); DateTime date = dr.GetDateTime(2);DateTime date = dr.GetDateTime(2);}}dr.Close();dr.Close();

Accessing data todayAccessing data todayQueries in Queries in

quotesquotes

Loosely bound Loosely bound argumentsarguments

Loosely typed Loosely typed result setsresult sets

No compile No compile time checkstime checks

public class Customer { … }public class Customer { … }

public class Northwind: DataContextpublic class Northwind: DataContext{{ public Table<Customer> Customers;public Table<Customer> Customers; … …}}

Northwind db = new Northwind(…);Northwind db = new Northwind(…);var contacts =var contacts = from c in db.Customersfrom c in db.Customers where c.City == "London"where c.City == "London" select new { c.Name, c.Phone };select new { c.Name, c.Phone };

DLinq For Relational Data

AccessingAccessing data with DLinqdata with DLinqClasses Classes

describe datadescribe data

Strongly typed Strongly typed connectionconnection

Integrated Integrated query syntaxquery syntax

Strongly typed Strongly typed resultsresults

Tables are Tables are like collectionslike collections

DLinq For Relational Data

Language integrated data access

Maps tables and rows to classes and objects

Builds on ADO.NET and .NET TransactionsMapping

Encoded in attributes

Relationships map to propertiesPersistence

Automatic change tracking

Updates through SQL or stored procedures

XLinq For XML Data

XmlDocument doc = new XmlDocument();XmlDocument doc = new XmlDocument();XmlElement contacts = doc.CreateElement("contacts");XmlElement contacts = doc.CreateElement("contacts");foreach (Customer c in customers)foreach (Customer c in customers) if (c.Country == "USA") {if (c.Country == "USA") { XmlElement e = doc.CreateElement("contact");XmlElement e = doc.CreateElement("contact"); XmlElement name = doc.CreateElement("name");XmlElement name = doc.CreateElement("name"); name.InnerText = c.CompanyName;name.InnerText = c.CompanyName; e.AppendChild(name);e.AppendChild(name); XmlElement phone = doc.CreateElement("phone");XmlElement phone = doc.CreateElement("phone"); phone.InnerText = c.Phone;phone.InnerText = c.Phone; e.AppendChild(phone);e.AppendChild(phone); contacts.AppendChild(e);contacts.AppendChild(e); }}doc.AppendChild(contacts);doc.AppendChild(contacts);

Programming XML todayProgramming XML today

<contacts> <contact> <name>Great Lakes Food</name> <phone>(503) 555-7123</phone> </contact> …</contacts>

Imperative Imperative modelmodel

Document Document centriccentric

No integrated No integrated queriesqueries

Memory Memory intensiveintensive

XLinq For XML Data

XElement contacts = new XElement("contacts",XElement contacts = new XElement("contacts", from c in customersfrom c in customers where c.Country == "USA"where c.Country == "USA" select new XElement("contact",select new XElement("contact", new XElement("name", c.CompanyName),new XElement("name", c.CompanyName), new XElement("phone", c.Phone)new XElement("phone", c.Phone) ))););

Programming XML with XLinqProgramming XML with XLinqDeclarative Declarative

modelmodel

ElementElementcentriccentric

Integrated Integrated queriesqueries

Smaller and Smaller and fasterfaster

XLinq For XML Data

Language integrated query for XML

Expressive power of XPath / XQuery

But with C# or VB as programming languageLeverages experience with DOM

Element centric, not document centric

Functional construction

Text nodes are just strings

Simplified XML namespace support

Faster and smaller

C# 3.0 Design Goals

• Integrate objects, relational, and XML

• Build on foundation laid in C# 1.0 and 2.0

• Run on the .NET 2.0 CLR

• Remain 100% backwards compatible

C# 3.0 Language Innovations

var contacts =var contacts = from c in customersfrom c in customers where c.State == "WA"where c.State == "WA" select new { c.Name, c.Phone };select new { c.Name, c.Phone };

var contacts =var contacts = customerscustomers .Where(c => c.State == "WA").Where(c => c.State == "WA") .Select(c => new { c.Name, .Select(c => new { c.Name, c.Phone });c.Phone });Extension Extension

methodsmethods

Lambda Lambda expressionsexpressions

Query Query expressionsexpressions

Object Object initializersinitializers

Anonymous Anonymous typestypes

Local variable Local variable type inferencetype inference

Queries Through APIs

public class List<T>public class List<T>{{ public List<T> Where(Func<T, bool> predicate) { … }public List<T> Where(Func<T, bool> predicate) { … } public List<S> Select<S>(Func<T, S> selector) { … }public List<S> Select<S>(Func<T, S> selector) { … } … …}}

List<Customer> customers = GetCustomerList();List<Customer> customers = GetCustomerList();List<string> contacts =List<string> contacts = customers.Where(c => c.State == "WA").Select(c => customers.Where(c => c.State == "WA").Select(c => c.Name);c.Name);

Query operators Query operators are just methodsare just methods

But what about But what about other types?other types?Declare operators Declare operators

in all collections?in all collections?

What about What about arrays?arrays?

Methods compose Methods compose to form queriesto form queries

Queries Through APIs

public static class Sequencepublic static class Sequence{{ public static IEnumerable<T> Where<T>(IEnumerable<T> public static IEnumerable<T> Where<T>(IEnumerable<T> source,source, Func<T, bool> predicate) { … }Func<T, bool> predicate) { … }

public static IEnumerable<S> Select<T, S>(IEnumerable<T> public static IEnumerable<S> Select<T, S>(IEnumerable<T> source,source, Func<T, S> selector) { … }Func<T, S> selector) { … } … …}} Customer[] customers = GetCustomerArray();Customer[] customers = GetCustomerArray();

IEnumerable<string> contacts = Sequence.Select(IEnumerable<string> contacts = Sequence.Select( Sequence.Where(customers, c => c.State == Sequence.Where(customers, c => c.State == "WA"),"WA"), c => c.Name);c => c.Name);

Query operators Query operators are static methodsare static methods

Huh?Huh?

Want methods on Want methods on IEnumerable<T>IEnumerable<T>

namespace System.Querynamespace System.Query{{ public static class Sequencepublic static class Sequence {{ public static IEnumerable<T> Where<T>(this IEnumerable<T> public static IEnumerable<T> Where<T>(this IEnumerable<T> source,source, Func<T, bool> predicate) { … }Func<T, bool> predicate) { … }

public static IEnumerable<S> Select<T, S>(this public static IEnumerable<S> Select<T, S>(this IEnumerable<T> source,IEnumerable<T> source, Func<T, S> selector) { … }Func<T, S> selector) { … } … … }}}}

Solution: Extension Methods

using System.Query;using System.Query;

ExtensionExtensionmethodsmethods

IEnumerable<string> contacts =IEnumerable<string> contacts = customers.Where(c => c.State == "WA").Select(c => customers.Where(c => c.State == "WA").Select(c => c.Name);c.Name);

Brings extensions Brings extensions into scopeinto scope

obj.Foo(x, y)obj.Foo(x, y)

XXX.Foo(obj, x, y)XXX.Foo(obj, x, y)

IntelliSense!IntelliSense!

Local Variable Type Inference

int i = 5;int i = 5;string s = "Hello";string s = "Hello";double d = 1.0;double d = 1.0;int[] numbers = new int[] {1, 2, 3};int[] numbers = new int[] {1, 2, 3};Dictionary<int,Order> orders = new Dictionary<int,Order> orders = new Dictionary<int,Order>();Dictionary<int,Order>();

var i = 5;var i = 5;var s = "Hello";var s = "Hello";var d = 1.0;var d = 1.0;var numbers = new int[] {1, 2, 3};var numbers = new int[] {1, 2, 3};var orders = new Dictionary<int,Order>();var orders = new Dictionary<int,Order>();

““var” means same var” means same type as initializertype as initializer

Anonymous Types

public class Customerpublic class Customer{{ public string Name;public string Name; public Address Address;public Address Address; public string Phone;public string Phone; public List<Order> Orders;public List<Order> Orders; … …}}

public class Contactpublic class Contact{{ public string Name;public string Name; public string Phone;public string Phone;}}

Customer c = GetCustomer(…);Customer c = GetCustomer(…);Contact x = new Contact { Name = c.Name, Phone = Contact x = new Contact { Name = c.Name, Phone = c.Phone };c.Phone };

Customer c = GetCustomer(…);Customer c = GetCustomer(…);var x = new { c.Name, c.Phone };var x = new { c.Name, c.Phone };

Customer c = GetCustomer(…);Customer c = GetCustomer(…);var x = new { Name = c.Name, Phone = c.Phone };var x = new { Name = c.Name, Phone = c.Phone };

class ???class ???{{ public string Name;public string Name; public string Phone;public string Phone;}}

Projection style Projection style initializerinitializer

var contacts =var contacts = from c in customersfrom c in customers where c.State == "WA"where c.State == "WA" select new { c.Name, c.Phone };select new { c.Name, c.Phone };

Anonymous Types

var contacts =var contacts = customers.customers. .Where(c => c.State == "WA“).Where(c => c.State == "WA“) .Select(c => new { c.Name, .Select(c => new { c.Name, c.Phone });c.Phone });

class ???class ???{{ public string Name;public string Name; public string Phone;public string Phone;}}

IEnumerable<???>IEnumerable<???>

foreach (var c in contacts) {foreach (var c in contacts) { Console.WriteLine(c.Name);Console.WriteLine(c.Name); Console.WriteLine(c.Phone);Console.WriteLine(c.Phone);}}

??????

public delegate bool Predicate<T>(T obj);public delegate bool Predicate<T>(T obj);

public class List<T>public class List<T>{{ public List<T> FindAll(Predicate<T> test) public List<T> FindAll(Predicate<T> test) { … }{ … } … …}}

Lambda Expressions

List<Customer> customers = List<Customer> customers = GetCustomerList();GetCustomerList();

List<Customer> x = customers.FindAll(List<Customer> x = customers.FindAll( delegate(Customer c) { return c.State == delegate(Customer c) { return c.State == "WA"; }"WA"; }););

List<Customer> x = customers.FindAll(c => c.State List<Customer> x = customers.FindAll(c => c.State == "WA");== "WA");

ExplicitlyExplicitlytypedtyped

Statement Statement contextcontext

ImplicitlyImplicitlytypedtyped

Expression Expression contextcontext

Expression Trees

public class Northwind: DataContextpublic class Northwind: DataContext{{ public Table<Customer> public Table<Customer> Customers;Customers; public Table<Order> Orders;public Table<Order> Orders; … …}}

Northwind db = new Northwind(…);Northwind db = new Northwind(…);var query = from c in db.Customers where c.State == "WA" var query = from c in db.Customers where c.State == "WA" select c;select c;

Northwind db = new Northwind(…);Northwind db = new Northwind(…);var query = db.Customers.Where(c => c.State == var query = db.Customers.Where(c => c.State == "WA");"WA");

How does this How does this become SQL ?become SQL ?

public class Table<T>: IEnumerable<T>public class Table<T>: IEnumerable<T>{{ public Table<T> Where(Expression<Func<T, bool>> public Table<T> Where(Expression<Func<T, bool>> predicate);predicate); … …}}

Method asks for Method asks for expression treeexpression tree

System.Expressions.System.Expressions.Expression<T>Expression<T>

Expression Trees

Code as Data

Func<Customer, bool> test = c => c.State == Func<Customer, bool> test = c => c.State == "WA";"WA";

Expression<Func<Customer, bool>> test = c => c.State Expression<Func<Customer, bool>> test = c => c.State == "WA";== "WA";

ParameterExpression c =ParameterExpression c = Expression.Parameter(typeof(Customer), "c");Expression.Parameter(typeof(Customer), "c");Expression expr =Expression expr = Expression.EQ(Expression.EQ( Expression.Property(c, Expression.Property(c, typeof(Customer).GetProperty("State")),typeof(Customer).GetProperty("State")), Expression.Constant("WA")Expression.Constant("WA") ););Expression<Func<Customer, bool>> test =Expression<Func<Customer, bool>> test = Expression.Lambda<Func<Customer, bool>>(expr, c);Expression.Lambda<Func<Customer, bool>>(expr, c);

stringConstant :Constant

Value = "WA"

stateProperty :Property

PropertyName = "State"

equality :EQ

customerParam :ParameterExpression

Type = typeof(Customer)Name = c

test :Lambda

righttarget left

parameterexpression

Benefits Of LINQ

Unified querying of objects, relational, XML

Type checking and IntelliSense for queries

SQL and XQuery-like power in C# and VB

Extensibility model for languages / APIs

Call to Action

- Get VS 2005- Download LINQ preview

http://msdn.microsoft.com/netframework/future/linq/

Play Around & See the power!

Q & A