Роман Здебский Microsoft rzdebski@microsoft.com http://blogs.msdn.com/roman.

Презентация:



Advertisements
Похожие презентации
На основе доклада Романа Здебского на семинаре «Дни разработчика»
Advertisements

Microsoft TechDays Сергей Звездин
Проект Linq (C# 3.0, VB 10.0) – будущее языков программирования Title of the Presentation Дмитрий Никонов Program Manager Microsoft.
Info My name – Valera Kolupaev – Wave for questions -
Work with databases in Java. JDBC Tutorial for students of universities Author: Dudnik Oxana.
1/27 Chapter 9: Template Functions And Template Classes.
PDC Конференция в LA в сентябре 2005 Все материалы доступны свободно downloads.aspx
Unit II Constructor Cont… Destructor Default constructor.
© 2009 Avaya Inc. All rights reserved.1 Chapter Two, Voic Pro Components Module Two – Actions, Variables & Conditions.
Java Collections Framework (JCF) in Java Tutorial for students of universities Author: Oxana Dudnik.
© 2002 IBM Corporation Confidential | Date | Other Information, if necessary © Wind River Systems, released under EPL 1.0. All logos are TM of their respective.
Microsoft TechDays Евгений Марченков Эксперт по технологиям разработки ПО.
Operator Overloading Customised behaviour of operators Chapter: 08 Lecture: 26 & 27 Date:
Java Server Pages(JSP). JavaServer Pages (JSP) позволяют вам отделить динамическую часть ваших страниц от статического HTML. Вы, как обычно, пишете обычный.
Data Types in C. A Data Type A data type is –A set of values AND –A set of operations on those values A data type is used to –Identify the type of a variable.
© 2009 Avaya Inc. All rights reserved.1 Chapter Three, Voic Pro Advanced Functions Module Two – Database and IVR.
Workshop 7B-1 NAS101 Workshops Copyright 2001 MSC.Software Corporation WORKSHOP 7B Structure With Spring Support.
PAT312, Section 21, December 2006 S21-1 Copyright 2007 MSC.Software Corporation SECTION 21 GROUPS.
Running Commands & Getting Help. Running Commands Commands have the following syntax: command options arguments Each item is separated by a space Options.
© 2005 Cisco Systems, Inc. All rights reserved. IPTX v Configuring Additional Cisco CallManager Express Features Configuring Cisco CallManager Express.
Транксрипт:

Роман Здебский Microsoft

Зачем нужен LINQ? – проблематика и постановка задачи Основные идеи LINQ Сценарии использования Влияние LINQ на.NET языки программирования Демонстрации

Проблема: Data != Objects

T/SQL Oracle SQL*Plus USE Northwind SELECT ProductName,UnitPrice, UnitsInStock FROM products WHERE productID

Должен знать и периодически использовать: Relational Algebra T/SQL (SQL Server) API (ADO, OLE DB) XQuery …

SqlConnection nwindConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind"); SqlCommand catCMD = nwindConn.CreateCommand(); catCMD.CommandText = "SELECT CategoryID, CategoryName FROM Categories; nwindConn.Open(); SqlDataReader myReader = catCMD.ExecuteReader(); while (myReader.Read()) { Console.WriteLine("\t{0}\t{1}", myReader.GetInt32(0), myReader.GetString(1)); } myReader.Close(); nwindConn.Close(); SqlConnection nwindConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind"); SqlCommand catCMD = nwindConn.CreateCommand(); catCMD.CommandText = "SELECT CategoryID, CategoryName FROM Categories; nwindConn.Open(); SqlDataReader myReader = catCMD.ExecuteReader(); while (myReader.Read()) { Console.WriteLine("\t{0}\t{1}", myReader.GetInt32(0), myReader.GetString(1)); } myReader.Close(); nwindConn.Close(); DataSet DS=new DataSet(); XQueryNavigatorCollection oXQ = new XQueryNavigatorCollection(); string strXML = ""; string fileName1="c:\\Test\\T1.xml"; string alias1 = "MyDataTest.xml"; oXQ.AddNavigator( fileName1, alias1 ); string strQuery = " { " + " let $bb := document(\"MyDataTest.xml\")/*/* " + " let $cc := document(\"MyDatattt.xml\")/*/* " + " for $c in $cc " + " for $b in $bb " + " where $c/kod = $b/kod " + " return { $b/nazv,$b/dat,$c/naim } " + " } ; XQueryExpression xExpression = new XQueryExpression(strQuery); strXML = xExpression.Execute(oXQ).ToXml(); StringReader strReader = new StringReader(strXML); XmlTextReader reader = new XmlTextReader(strReader); DS.ReadXml(reader); DataGrid1.DataSource = DS.Tables[0]; DataGrid1.DataBind(); DataSet DS=new DataSet(); XQueryNavigatorCollection oXQ = new XQueryNavigatorCollection(); string strXML = ""; string fileName1="c:\\Test\\T1.xml"; string alias1 = "MyDataTest.xml"; oXQ.AddNavigator( fileName1, alias1 ); string strQuery = " { " + " let $bb := document(\"MyDataTest.xml\")/*/* " + " let $cc := document(\"MyDatattt.xml\")/*/* " + " for $c in $cc " + " for $b in $bb " + " where $c/kod = $b/kod " + " return { $b/nazv,$b/dat,$c/naim } " + " } ; XQueryExpression xExpression = new XQueryExpression(strQuery); strXML = xExpression.Execute(oXQ).ToXml(); StringReader strReader = new StringReader(strXML); XmlTextReader reader = new XmlTextReader(strReader); DS.ReadXml(reader); DataGrid1.DataSource = DS.Tables[0]; DataGrid1.DataBind(); Dim xmldoc As New System.Xml.XPath.XPathDocument("c:\books.xml") Dim nav As System.Xml.XPath.XPathNavigator = xmldoc.CreateNavigator() Dim expr As System.Xml.XPath.XPathExpression = nav.Compile( "//Publisher[. = 'MSPress']/parent::node()/Title" ) Dim xmldoc As New System.Xml.XPath.XPathDocument("c:\books.xml") Dim nav As System.Xml.XPath.XPathNavigator = xmldoc.CreateNavigator() Dim expr As System.Xml.XPath.XPathExpression = nav.Compile( "//Publisher[. = 'MSPress']/parent::node()/Title" )

Как сделать эффективный paging списка на web странице? ASP NET 1.x - AllowPaging property - True ASP NET Enable Paging option from the GridView's smart tag А если список большой… ???

USE Northwind SELECT RowNum, EmployeeID, LastName, FirstName FROM (SELECT EmployeeID, LastName, FirstName, ROW_NUMBER() OVER(ORDER BY LastName,FirstName) as RowNum FROM Employees ) as EmployeeInfo WHERE RowNum BETWEEN 1 and 5 USE Northwind SELECT RowNum, EmployeeID, LastName, FirstName FROM (SELECT EmployeeID, LastName, FirstName, ROW_NUMBER() OVER(ORDER BY LastName,FirstName) as RowNum FROM Employees ) as EmployeeInfo WHERE RowNum BETWEEN 1 and 5 SQL Server 2005: SQL Server 2000: USE Northwind SELECT top EmployeeID, LastName, FirstName FROM ( SELECT TOP EmployeeID, LastName, FirstName FROM Employees ORDER BY LastName DESC, FirstName DESC ) as EmployeeInfo ORDER BY LastName ASC, FirstName ASC USE Northwind SELECT top EmployeeID, LastName, FirstName FROM ( SELECT TOP EmployeeID, LastName, FirstName FROM Employees ORDER BY LastName DESC, FirstName DESC ) as EmployeeInfo ORDER BY LastName ASC, FirstName ASC

Language Integrated Query

Сделать возможности запросов неотъемлемой частью.NET языков Запрашивать, объединять, трансформировать: реляционные данные XML Объекты Коллекции и списки … - в развитии идеи - ВСЁ

Objects XML.NET Language Integrated Query C# 3.0VB 9.0Others… Relational LINQ to Objects LINQ to SQL LINQ to XML LINQ to Entities LINQ to DataSets

.NET Fx 2.0.NET Fx 2.0 Minor Update.NET Fx 2.0 Minor Update.NET Fx 2.0 Minor Update.NET Fx 3.0 Update Update.NET Fx 3.5 Whidbey Vista Orcas time Version = Assembly references + compilers Не создается новый CLR runtime

List locations = GetLocations(); IEnumerable places = from city in locations where city.DistanceFromSeattle > 1000 orderby city.Country, city.Name select city; List locations = GetLocations(); IEnumerable places = from city in locations where city.DistanceFromSeattle > 1000 orderby city.Country, city.Name select city; Name=Kazan Country=Russia DistanceFromSPB=2000 Name=Tver Country=Russia DistanceFromSPB=1100 Name=London Country=UK DistanceFromSPB=4000 Name=Kazan Country=Russia DistanceFromSPB=2000 Name=Tver Country=Russia DistanceFromSPB=1100 Name=London Country=UK DistanceFromSPB=4000

Extension methods Формат запроса var citiesSPB = from city in locations where city.DistanceFromSPB > 1000 orderby city.Country, city.Name select new { city.Name, city.Country }; var citiesSPB = from city in locations where city.DistanceFromSPB > 1000 orderby city.Country, city.Name select new { city.Name, city.Country }; var citiesSPB2 = locations.Where(c => c.DistanceFromSPB > 1000).OrderBy(c => c.Name).OrderBy(c => c.Country).Select( c => new {Name= c.Name, Country = c.Country});

Фактический порядок выполнения запроса Intellisence Уже используется (XQuery) Execution plan for $act in doc("hamlet.xml")//ACT let $speakers := distinct- values($act//SPEAKER) return … for $act in doc("hamlet.xml")//ACT let $speakers := distinct- values($act//SPEAKER) return …

RestrictionWhere ProjectionSelect, SelectMany OrderingOrderBy, ThenBy GroupingGroupBy JoinsJoin, GroupJoin QuantifiersAny, All PartitioningTake, Skip, TakeWhile, SkipWhile SetsDistinct, Union, Intersect, Except ElementsFirst, Last, Single, ElementAt AggregationCount, Sum, Min, Max, Average ConversionToArray, ToList, ToDictionary CastingOfType, Cast

Implicitly typed local variables Anonymous types Extension methods Lambda expressions Object initializers Query expressions Expression trees

var contacts = from c in customers where c.State == "WA" select new { c.Name, c.Phone }; var contacts = customers.Where(c => c.State == "WA").Select(c => new { c.Name, c.Phone }); Extension methods Lambda expressions Query expressions Object initializers Anonymous types Local variable type inference

Dim contacts = From c In customers _ Where c.State = "WA _ Select c.Name, c.Phone Dim contacts = _ customers _.Where(Function (c) c.State = "WA")_.Select(Function(c) New With { c.Name, c.Phone }) Extension methods Lambda expressions Query expressions Object initializers Anonymous types Local variable type inference

var testVal = 2 * 2; var testVal2 = "hello".ToUpper(); var testVal3 = new City(); Console.WriteLine(testVal.GetType()); Console.WriteLine(testVal2.GetType()); Console.WriteLine(testVal3.GetType()); var testVal = 2 * 2; var testVal2 = "hello".ToUpper(); var testVal3 = new City(); Console.WriteLine(testVal.GetType()); Console.WriteLine(testVal2.GetType()); Console.WriteLine(testVal3.GetType()); System.Int32 System.String ConsoleApplication1.City System.Int32 System.String ConsoleApplication1.City

Необходимость трансформации или модификации данных полученных от запроса LINQ позволяет осуществлять data shaping с помощью проекций Удобно использовать с анонимными типами anonymous type, поддерживаемыми компилятором

f__AnonymousType0`2[System.Int32,System.String]

namespace MyStuff { public static class Extensions { public static string Concatenate(this IEnumerable strings, string separator) {…} } using MyStuff; string[] names = new string[] { "Axel", "Mia", "Niels" }; string s = names.Concatenate(", "); Extension method Brings extensions into scope obj.Foo(x, y) XXX.Foo(obj, x, y) IntelliSense!

static class StaticExtensionClass { public static int toGoInMiles(this City ct) { return (int)(ct.DistanceFromSPB * 1.61) ; } static class StaticExtensionClass { public static int toGoInMiles(this City ct) { return (int)(ct.DistanceFromSPB * 1.61) ; } City ct = new City { Name = "Bor", Country = "RUS", DistanceFromSPB = 100 }; Console.WriteLine(ct.toGoInMiles()); City ct = new City { Name = "Bor", Country = "RUS", DistanceFromSPB = 100 }; Console.WriteLine(ct.toGoInMiles()); 161

public class Product { public string Name; public decimal Price; }

public class Product { string name; decimal price; public string Name { get { return name; } set { name = value; } } public decimal Price { get { return price; } set { price = value; } }

public class Product { public string Name { get; set; } public decimal Price { get; set; } } private string ; public string Name { get { return ; } set { = value; } } Must have both get and set

public class Point { private int x, y; public int X { get { return x; } set { x = value; } } public int Y { get { return y; } set { y = value; } } } Point a = new Point { X = 0, Y = 1 }; Point a = new Point(); a.X = 0; a.Y = 1; Field or property assignments

List numbers = new List { 1, 10, 100 }; Must implement IEnumerable List numbers = new List (); numbers.Add(1); numbers.Add(10); numbers.Add(100); Must have public Add method Dictionary spellings = new Dictionary { { 0, "Zero" }, { 1, "One" }, { 2, "Two" }, { 3, "Three" } }; Add can take more than one parameter

IEnumerable locals = EnumerableExtensions.Where(customers, delegate(Customer c) { return c.ZipCode == 98112; }); IEnumerable locals = EnumerableExtensions.Where(customers, delegate(Customer c) { return c.ZipCode == 98112; }); C# 2.0 C# 3.0 Lambda выражение locals.Where(c => c == 98112);

Func nonExprLambda = x => (x & 1) == 0; Expression > exprLambda = x => (x & 1) == 0; Func nonExprLambda = x => (x & 1) == 0; Expression > exprLambda = x => (x & 1) == 0; ParameterExpression xParam = Expression.Parameter(typeof(int), "x"); Expression > exprLambda = Expression.Lambda >( Expression.Equal( Expression.And(xParam, Expression.Constant(1)), Expression.Constant(0)), xParam); Console.WriteLine(exprLambda); ParameterExpression xParam = Expression.Parameter(typeof(int), "x"); Expression > exprLambda = Expression.Lambda >( Expression.Equal( Expression.And(xParam, Expression.Constant(1)), Expression.Constant(0)), xParam); Console.WriteLine(exprLambda); x => ( ( x & 1 ) = 0 )

System.Query.Enumerable Based on Delegates Source implements IEnumerable var query = from c in customers where c.State == "WA" select c.Name; var query = customers.Where(c => c.State == "WA").Select(c => c.Name); System.Query.Queryable Based on Expression Trees Source implements IQueryable SQLDataSetsObjectsOthers…

Customer[] custs = SampleData.GetCustomers(); custs PhoneNameID var query = from c in custs where c.City == "London" select c.Name; var query = custs.Where(c => c.City == "London").Select(c => c.Name); Select c => c.Name string[] names = query.ToArray(); names c => c.City == "London" Where

using System; using System.Query; using System.Collections.Generic; class app { static void Main() { string[] names = { "Allen", "Arthur", "Bennett" }; IEnumerable ayes = names.Where(s => s[0] == 'A'); foreach (string item in ayes) Console.WriteLine(item); names[0] = "Bob"; foreach (string item in ayes) Console.WriteLine(item); } Arthur using System; using System.Query; using System.Collections.Generic; class app { static void Main() { string[] names = { "Allen", "Arthur", "Bennett" }; IEnumerable ayes = names.Where(s => s[0] == 'A'); foreach (string item in ayes) Console.WriteLine(item); names[0] = "Bob"; foreach (string item in ayes) Console.WriteLine(item); } Arthur using System; using System.Query; using System.Collections.Generic; class app { static void Main() { string[] names = { "Allen", "Arthur", "Bennett" }; IEnumerable ayes = names.Where(s => s[0] == 'A'); foreach (string item in ayes) Console.WriteLine(item); names[0] = "Bob"; foreach (string item in ayes) Console.WriteLine(item); } Allen Arthur using System; using System.Query; using System.Collections.Generic; class app { static void Main() { string[] names = { "Allen", "Arthur", "Bennett" }; IEnumerable ayes = names.Where(s => s[0] == 'A'); foreach (string item in ayes) Console.WriteLine(item); names[0] = "Bob"; foreach (string item in ayes) Console.WriteLine(item); } Allen Arthur

Будьте осторожны с отложенным выполнением запросов и изменением данных // Don't do this! NullReferenceException foreach (var phone in contacts.Descendants("phone")) { phone.Remove(); } // Don't do this! NullReferenceException foreach (var phone in contacts.Descendants("phone")) { phone.Remove(); } foreach (var phone in contacts.Descendants("phone").ToList()) { phone.Remove(); } foreach (var phone in contacts.Descendants("phone").ToList()) { phone.Remove(); }

SqlConnection c = new SqlConnection(…); c.Open(); SqlCommand cmd = new SqlCommand( "SELECT c.Name, c.Phone FROM Customers c WHERE c.City "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(); Queries in quotes Loosely bound arguments Loosely typed result sets No compile time checks

public class Customer { … } public class Northwind : DataContext { public Table Customers; … } Northwind db = new Northwind(…); var contacts = from c in db.Customers where c.City == "London" select new { c.Name, c.Phone }; Classes describe data Strongly typed connections Integrated query syntax Strongly typed results Tables are like collections

Database Table View Column Relationship Stored Procedure DataContext Class Field / Property Method

Application SQL Server LINQ to SQL from c in db.Customers where c.City == "London" select c.CompanyName LINQ Query SQL Query SELECT CompanyName FROM Cust WHERE City = 'London' Rows ObjectsSubmitChanges() DML or SProcs db.Customers.Add(c1); c2.City = Seattle"; db.Customers.Remove(c3); INSERT INTO Cust … UPDATE Cust … DELETE FROM Cust …

Интегрированный в язык доступ к данным Связывает таблицы и записи с классами и объектами Построен поверх ADO.NET и.NET Transactions Соответствия (Mapping) Определяются атрибутами или во внешнем XML файле Отношения (relations) соответствуют свойствам (Свойство Products у Category и Category у Product) Возможность отложенной или одновременной загрузки данных через отношения (relations) Сохраняемость (Persistence) Автоматическое отслеживание изменений Обновление через SQL или stored procedures

Update Product product = db.Products.Single(p => p.ProductName== "Chai " ); product.UnitsInStock = 11; product.ReorderLevel = 10; product.UnitsOnOrder = 2; db.SubmitChanges(); Product product = db.Products.Single(p => p.ProductName== "Chai " ); product.UnitsInStock = 11; product.ReorderLevel = 10; product.UnitsOnOrder = 2; db.SubmitChanges(); Delete var supplier = db.Suppliers.FirstOrDefault(s=>s.CompanyName == ABC"); if ((supplier != null) && (supplier.Products.Count == 0)) { db.Suppliers.Remove(supplier); db.SubmitChanges(); } var supplier = db.Suppliers.FirstOrDefault(s=>s.CompanyName == ABC"); if ((supplier != null) && (supplier.Products.Count == 0)) { db.Suppliers.Remove(supplier); db.SubmitChanges(); } NorthwindDataContext db = new NorthwindDataContext(); Supplier supplier = new Supplier{CompanyName = ABC}; db.Suppliers.Add(supplier); db.SubmitChanges(); NorthwindDataContext db = new NorthwindDataContext(); Supplier supplier = new Supplier{CompanyName = ABC}; db.Suppliers.Add(supplier); db.SubmitChanges(); Add

Встроенный в C# и VB синтаксис запросов SQL-подобные запросы по любым.NET collection (Все реализующие IEnumerable) Мощный язык запросов Результаты LINQ запросов легко использовать в DataBinding

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); Great Lakes Food (503) … Imperative model Document centric No integrated queries Memory intensive

XDocument loaded = contacts var q = from c in loaded.Descendants("contact") where (int)c.Attribute("contactId") < 4 select (string)c.Element("firstName") + + (string)c.Element("lastName"); 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) ) ); Declarative model Element centric Integrated queries Smaller and faster

Language integrated query для XML Мощь выражений XPath / XQuery Но на C# или VB как языках программирования Использует опыт работы с DOM Element centric, не document centric Быстрее и компактнее

Часть ParallelFX LINQ to Objects LINQ to XML Распараллеливание LINQ to SQL – SQL Server Использование: Reference System.Concurrency.dll Wrap your data source in an IParallelEnumerable with a call to the System.Linq.ParallelEnumerable.AsParallel extension method.

Подходы к распараллеливанию: pipelined processing stop-and-go processing inverted enumeration IEnumerable leftData =..., rightData =...; var q = from x in leftData.AsParallel() join y in rightData on x.a == y.b select f(x, y); IEnumerable leftData =..., rightData =...; var q = from x in leftData.AsParallel() join y in rightData on x.a == y.b select f(x, y);

Language Integrated Query для.NET Встроенный в C# 3.0 и VB 9.0 синтаксис запросов LINQ to Objects SQL-like запросы к любым.NET коллекциям LINQ to SQL Инфраструктура запросов к реляционным данным LINQ to XML Компактный, быстрый XML DOM с поддержкой запросов LINQ to Entities LINQ to Datasets

Унифицированный подход к запросам и трансформации объектов, реляционных данных и XML Мощь запросов SQL и XQuery встроенная в C# и VB Проверка типов, IntelliSense, refactoring запросов Модель расширения для других языков программирования и APIs

LINQ to WebQueries (MSDN Web sites) LINQ to WebQueries LINQ to Amazon (books search) LINQ to Amazon LINQ to RDF Files. LINQ to RDF Files LINQ to MySQL LINQ to NHibernate LINQ to LDAP LINQ to Google Desktop LINQ to SharePoint LINQ to Streams (SLinq, Streaming LINQ) LINQ to Streams LINQ to Expressions (MetaLinq) LINQ to Expressions

Что бы мы сделали с paging в LINQ?

Ключевое слово – LINQ Вводим в поиск microsoft.com второй результат – The LINQ Project Anders Hejlsberg Chief Designer of C# Architect of LINQ project

Для большого числа типовых задач LINQ освобождает от необходимости тратить время на написание запросов Оптимизация запросов и индексирования – по прежнему профессиональная и нужная задача Каждый может более фокусно заниматься тем, что ему интереснее и в чем он видит свое профессиональное развитие и интерес

Роман Здебский Microsoft Зона «Спроси Эксперта» 14:00 – 15:00