300 likes | 461 Views
C# 3.0 & LINQ. Raimond Brookman – IT Architect http://blogs.infosupport.com/raimondb. Outline. Linq Project DLinq XLinq C# 3.0 Language Enhancements. Problem: Data != Objects. Service based Solution. <book> <title/> <author/> <year/> <price/> </book>. Xml Read.
E N D
C# 3.0 & LINQ Raimond Brookman – IT Architect http://blogs.infosupport.com/raimondb
Outline • Linq Project • DLinq • XLinq • C# 3.0 Language Enhancements
Problem: Data != Objects
Service based Solution <book> <title/> <author/> <year/> <price/> </book> Xml Read Transform Msg Web Application Order Processing WS Databound grid Xml R/W XML Config Order Mgt WS BR Check Customer Mgt Service (HTTP + XML) ORM
The LINQ Project C# 3.0 VB 9.0 Others… .NET Language Integrated Query StandardQueryOperators DLinq(ADO.NET) XLinq (System.Xml) <book> <title/> <author/> <year/> <price/> </book> Objects SQL WinFS XML
Service based Solution with LINQ <book> <title/> <author/> <year/> <price/> </book> XLINQ Xml Read O-LINQ Transform Msg Web Application Order Processing WS O-LINQ Databound grid Xml R/W XLINQ XML Config Order Mgt WS BR Check O-LINQ Customer Mgt Service (HTTP + XML) DLINQ ORM
LINQ Style programming class Contact { … }; List<Contact> contacts = new List<Contacts>(); foreach(Customer c in customers) { if(c.State == “WA”) { Contact ct = new Contact(); ct.Name = c.Name; ct.Phone = c.Phone; contacts.Add(ct); } } var contacts = from c in customers where c.State == "WA" select new { c.Name, c.Phone };
Query Expressions • Language integrated query syntax fromidinsource { fromidinsource | wherecondition } [ orderbyordering, ordering, … ] selectexpr | groupexprbykey [ intoidquery ]
DLinq For Relational Data Accessing data today Queries in quotes SqlConnection c = new SqlConnection(…); c.Open(); SqlCommand cmd = new SqlCommand( @"SELECT c.Name, c.Phone FROM Customers c WHERE c.City = @p0"); cmd.Parameters.AddWithValue("@p0", "London“); DataReader dr = c.Execute(cmd); while (dr.Read()) { string name = dr.GetString(0); string phone = dr.GetString(1); DateTime date = dr.GetDateTime(2); } dr.Close(); Loosely bound arguments Loosely typed result sets No compile time checks
DLinq For Relational Data Accessingdata with DLinq Classes describe data public class Customer { … } public class Northwind: DataContext { public Table<Customer> Customers; … } Tables are like collections Strongly typed connection Northwind db = new Northwind(…); var contacts = from c in db.Customers where c.City == "London" select new { c.Name, c.Phone }; Integrated query syntax Strongly typed results
DLinq For Relational Data • Language integrated data access • Maps tables and rows to classes and objects • Builds on ADO.NET and .NET Transactions • Mapping • Encoded in attributes • Relationships map to properties • Persistence • Automatic change tracking • Updates through SQL or stored procedures
XLinq For XML Data Imperative model Programming XML today XmlDocument doc = new XmlDocument(); XmlElement contacts = doc.CreateElement("contacts"); foreach (Customer c in customers) if (c.Country == "USA") { XmlElement e = doc.CreateElement("contact"); XmlElement name = doc.CreateElement("name"); name.InnerText = c.CompanyName; e.AppendChild(name); XmlElement phone = doc.CreateElement("phone"); phone.InnerText = c.Phone; e.AppendChild(phone); contacts.AppendChild(e); } doc.AppendChild(contacts); Document centric No integrated queries Memory intensive <contacts> <contact> <name>Great Lakes Food</name> <phone>(503) 555-7123</phone> </contact> … </contacts>
XLinq For XML Data Programming XML with XLinq Declarative model XElement contacts = new XElement("contacts", from c in customers where c.Country == "USA" select new XElement("contact", new XElement("name", c.CompanyName), new XElement("phone", c.Phone) ) ); Elementcentric Integrated queries Smaller and faster
XLinq For XML Data • Language integrated query for XML • Expressive power of XPath / XQuery • But with C# or VB as programming language • Leverages 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 Query expressions var contacts = from c in customers where c.State == "WA" select new { c.Name, c.Phone }; Local variable type inference Lambda expressions var contacts = customers .Where(c => c.State == "WA") .Select(c => new { c.Name, c.Phone }); Extension methods Anonymous types Object initializers
Queries Through APIs Query operators are just methods public class List<T> { public List<T> Where(Func<T, bool> predicate) { … } public List<S> Select<S>(Func<T, S> selector) { … } … } Methods compose to form queries List<Customer> customers = GetCustomerList(); List<string> contacts = customers.Where(c => c.State == "WA").Select(c => c.Name); But what about other types? Declare operators in all collections? What about arrays?
Queries Through APIs Query operators are static methods public static class Sequence { public static IEnumerable<T> Where<T>(IEnumerable<T> source, Func<T, bool> predicate) { … } public static IEnumerable<S> Select<T, S>(IEnumerable<T> source, Func<T, S> selector) { … } … } Huh? Customer[] customers = GetCustomerArray(); IEnumerable<string> contacts = Sequence.Select( Sequence.Where(customers, c => c.State == "WA"), c => c.Name); Want methods on IEnumerable<T>
Solution: Extension Methods namespace System.Query { public static class Sequence { public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate) { … } public static IEnumerable<S> Select<T, S>(this IEnumerable<T> source, Func<T, S> selector) { … } … } } Extensionmethods obj.Foo(x, y) XXX.Foo(obj, x, y) Brings extensions into scope using System.Query; IEnumerable<string> contacts = customers.Where(c => c.State == "WA").Select(c => c.Name); IntelliSense!
Local Variable Type Inference int i = 5; string s = "Hello"; double d = 1.0; int[] numbers = new int[] {1, 2, 3}; Dictionary<int,Order> orders = new Dictionary<int,Order>(); var i = 5; var s = "Hello"; var d = 1.0; var numbers = new int[] {1, 2, 3}; var orders = new Dictionary<int,Order>(); “var” means same type as initializer
Anonymous Types public class Customer { public string Name; public Address Address; public string Phone; public List<Order> Orders; … } public class Contact { public string Name; public string Phone; } class ??? { public string Name; public string Phone; } Customer c = GetCustomer(…); Contact x = new Contact { Name = c.Name, Phone = c.Phone }; Customer c = GetCustomer(…); var x = new { Name = c.Name, Phone = c.Phone }; Projection style initializer Customer c = GetCustomer(…); var x = new { c.Name, c.Phone };
Anonymous Types var contacts = from c in customers where c.State == "WA" select new { c.Name, c.Phone }; class ??? { public string Name; public string Phone; } IEnumerable<???> var contacts = customers. .Where(c => c.State == "WA“) .Select(c => new { c.Name, c.Phone }); ??? foreach (var c in contacts) { Console.WriteLine(c.Name); Console.WriteLine(c.Phone); }
Lambda Expressions public delegate bool Predicate<T>(T obj); public class List<T> { public List<T> FindAll(Predicate<T> test) { … } … } Statement context Explicitlytyped List<Customer> customers = GetCustomerList(); List<Customer> x = customers.FindAll( delegate(Customer c) { return c.State == "WA"; } ); Implicitlytyped Expression context List<Customer> x = customers.FindAll(c => c.State == "WA");
Expression Trees public class Northwind: DataContext { public Table<Customer> Customers; public Table<Order> Orders; … } How does this become SQL ? Northwind db = new Northwind(…); var query = from c in db.Customers where c.State == "WA" select c; Method asks for expression tree Northwind db = new Northwind(…); var query = db.Customers.Where(c => c.State == "WA"); public class Table<T>: IEnumerable<T> { public Table<T> Where(Expression<Func<T, bool>> predicate); … } System.Expressions.Expression<T>
Expression Trees • Code as Data Func<Customer, bool> test = c => c.State == "WA"; Expression<Func<Customer, bool>> test = c => c.State == "WA"; ParameterExpression c = Expression.Parameter(typeof(Customer), "c"); Expression expr = Expression.EQ( Expression.Property(c, typeof(Customer).GetProperty("State")), Expression.Constant("WA") ); Expression<Func<Customer, bool>> test = Expression.Lambda<Func<Customer, bool>>(expr, c);
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!