LINQ: Language Integrated Query ST Colloquium, 2008-05-15 Tom Lokhorst
Brief example
Brief example int[] nrs = {2, 3, 9, 1, 21, 3, 42};
Brief example int[] nrs = {2, 3, 9, 1, 21, 3, 42}; var q = from n in nrs where n < 5 select n * n;
Brief example int[] nrs = {2, 3, 9, 1, 21, 3, 42}; var q = from n in nrs where n < 5 select n * n; foreach (var i in q) { Console.WriteLine(i); }
Brief example int[] nrs = {2, 3, 9, 1, 21, 3, 42}; var q = from n in nrs where n < 5 LINQ select n * n; foreach (var i in q) { Console.WriteLine(i); }
Overview The problem space LINQ in .NET 3.5 Deconstructing expressions Usages of LINQ Comparisons with other stuff
Circles, Triangles and Rectangles
Circles, Triangles and Rectangles
Circles, Triangles and Rectangles Business software deals with lots of different types of data: Objects Tree structures (XML) Relational
Assignment A web server should show a list of the top 5 memory-intensive processes. Per process, show its name, and a description. There is a SQL database with descriptions for programs. The list should be in RSS format.
A bit of History
A bit of History .NET 1.0 released early 2002 CLR 1.0, C# 1.0, VB 7 .0 Delegates: managed function pointers
A bit of History .NET 1.0 released early 2002 CLR 1.0, C# 1.0, VB 7 .0 Delegates: managed function pointers .NET 2.0 released late 2005 CLR 2.0, C# 2.0, VB 8.0 Generics, iterators, anonymous delegates
A bit of History .NET 1.0 released early 2002 CLR 1.0, C# 1.0, VB 7 .0 Delegates: managed function pointers .NET 2.0 released late 2005 CLR 2.0, C# 2.0, VB 8.0 Generics, iterators, anonymous delegates .NET 3.5 released late 2007 CLR 2.0, C# 3.0, VB 9.0 Lambda expressions, local type inferencing, extension methods, LINQ
LINQ in .NET 3.5 Libraries LINQ to Objects LINQ to XML LINQ to SQL Language enhancements Lambda expressions Query syntax Compiler enhancements Expression trees
LINQ to Objects
Eating the sugar C# int[] nrs = {2, 3, 9, 1, 21, 3, 42}; 3.0 var q = from n in nrs where n < 5 select n * n;
Eating the sugar C# int[] nrs = {2, 3, 9, 1, 21, 3, 42}; 3.0 IEnumerable<int> q = from n in nrs where n < 5 select n * n;
Eating the sugar C# int[] nrs = {2, 3, 9, 1, 21, 3, 42}; 3.0 IEnumerable<int> q = nrs.Where<int>(n => n < 5) .Select<int, int>(n => n * n);
Eating the sugar C# int[] nrs = {2, 3, 9, 1, 21, 3, 42}; 3.0 IEnumerable<float> q = nrs.Where<int>(n => n < 5) .Select<int, float>(n => n * 0.5F);
Eating the sugar C# int[] nrs = {2, 3, 9, 1, 21, 3, 42}; 3.0 IEnumerable<float> q = Enumerable.Select<int, float>( Enumerable.Where<int>(nrs, n => n < 5), (n => n * 0.5F));
Eating the sugar C# int[] nrs = {2, 3, 9, 1, 21, 3, 42}; 3.0 IEnumerable<float> q = Enumerable.Select<int, float>( Enumerable.Where<int>(nrs, n => n < 5), (n => n * 0.5F)); public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate) { ... }
Eating the sugar C# int[] nrs = {2, 3, 9, 1, 21, 3, 42}; 3.0 IEnumerable<float> q = Enumerable.Select<int, float>( Enumerable.Where<int>(nrs, n => n < 5), (n => n * 0.5F)); public static IEnumerable<T> Where<T>(this IEnumerable<T> source, Func<T, bool> predicate) { foreach (var elem in source) if (predicate(elem)) yield return elem; }
Eating the sugar C# int[] nrs = {2, 3, 9, 1, 21, 3, 42}; 3.0 IEnumerable<float> q = Enumerable.Select<int, float>( Enumerable.Where<int>(nrs, n => n < 5), (n => n * 0.5F));
Eating the sugar C# int[] nrs = {2, 3, 9, 1, 21, 3, 42}; 2.0 IEnumerable<float> q = Enumerable.Select<int, float>( Enumerable.Where<int>(nrs, delegate(int n){ return n < 5; }), delegate(int n){ return n * 0.5F;} );
Eating the sugar C# int[] nrs = {2, 3, 9, 1, 21, 3, 42}; 1.0* IEnumerable<float> q = Enumerable.Select<int, float>( Enumerable.Where<int>(nrs, new Func<int, bool>(LessThanFive)), new Func<int, float>(TimesHalf) ); bool LessThanFive(int n) { return n < 5; } float TimesHalf(int n) { return n * 0.5F; }
Eating the sugar C# int[] nrs = {2, 3, 9, 1, 21, 3, 42}; 3.0 var q = from n in nrs where n < 5 select n * n;
LINQ to Objects Query comprehenssions More syntax; orderby, groupby, join Works on you data structures IEnumerable<T> Implement you own Where<T>, Select<T> More library functions
LINQ to XML
Dealing with angle brackets LINQ to XML is a replacement for the W3C Document Object Model, because: It’ s old It’ s ugly It’ s impractical New API, all library: System.Xml.LINQ
Document Object Model Imperative API Document-centric Weird data types
Document Object Model Imperative API Document-centric Weird data types <Company name=”Microsoft”> <Founders> <Person>Bill Gates</Person> </Founders> </Company>
Document Object Model XmlDocument doc = new XmlDocument(); XmlElement company = doc.CreateElement("Company"); doc.AppendChild(company); XmlAttribute name = doc.CreateAttribute("name"); name.Value = "Microsoft"; company.Attributes.Append(name); XmlElement founders = doc.CreateElement("Founders"); company.AppendChild(founders); XmlElement person = doc.CreateElement("Person"); founders.AppendChild(person); XmlText bill = doc.CreateTextNode("Bill Gates"); person.AppendChild(bill);
LINQ to XML Functional construction Element-centric (context free) CLR data types (collection friendly)
LINQ to XML Functional construction Element-centric (context free) CLR data types (collection friendly) XElement company = new XElement("Company", new XAttribute("name", "Microsoft"), new XElement("Founders", new XElement("Person", "Bill Gates") ) );
XML with queries
XML with queries string[] names = { “Anders”, “Erik”, “Amanda” };
XML with queries string[] names = { “Anders”, “Erik”, “Amanda” }; from n in names where n.StartsWith(“A”) select new XElement(“Person”, n)
XML with queries string[] names = { “Anders”, “Erik”, “Amanda” }; XElement employees = new XElement(“Employees”, from n in names where n.StartsWith(“A”) select new XElement(“Person”, n) );
XML with queries string[] names = { “Anders”, “Erik”, “Amanda” }; XElement employees = new XElement(“Employees”, from n in names where n.StartsWith(“A”) select new XElement(“Person”, n) ); company.Add(employees);
XML with queries string[] names = { “Anders”, “Erik”, “Amanda” }; XElement employees = new XElement(“Employees”, from n in names where n.StartsWith(“A”) select new XElement(“Person”, n) ); company.Add(employees); Console.WriteLine(company);
XML on the Console <Company name=”Microsoft”> <Founders> <Person>Bill Gates</Person> </Founders> <Employees> <Person>Anders</Person> <Person>Amanda</Person> </Employees> </Company>
Querying XML IEnumerable<string> persons = from p in company.Descendants(“Person”) select p.Value;
Querying XML IEnumerable<string> persons = from p in company.Descendants(“Person”) select p.Value; Bill Gates Anders Amanda
LINQ to SQL
Querying a SQL backend Use LINQ to query a relational database Strongly typed queries Remote the query to the DBMS C# must remain API/DB independent
LINQ to SQL Simple Object Relational Mapper Microsoft SQL Server Comes with tool to make classes out of tables in an existing database Certainly not the best ORM out there More advanced stuff: LINQ to Entities
LINQ to SQL example
LINQ to SQL example
LINQ to SQL example
LINQ to SQL example [DatabaseAttribute(Name="Northwind")] public partial class NorthwindDataContext : System.Data.LINQ.DataContext { public NorthwindDataContext() : base("Data Source=.;Initial Catalog=Northwind;" + "Integrated Security=True") { } public Table<Customer> Customers { get { return this.GetTable<Customer>(); } } }
LINQ to SQL example [Table(Name="dbo.Customers")] public partial class Customer : INotifyPropertyChanging, INotifyPropertyChanged { private string _CustomerID; [Column(Storage="_CustomerID", DbType="NChar(5) NOT NULL", CanBeNull=false, IsPrimaryKey=true)] public string CustomerID { get { return this._CustomerID; } set { /* Setter code removed */ } } /* More code be here */ }
LINQ to SQL example
LINQ to SQL example var db = new NorthwindDataContext(); var q = from c in db.Customers where c.City == “London” select c;
Recommend
More recommend