Роман Здебский microsoft [email protected]

63

Upload: shon-osborne

Post on 04-Jan-2016

218 views

Category:

Documents


3 download

TRANSCRIPT

Page 1: Роман Здебский Microsoft rzdebski@microsoft.com
Page 2: Роман Здебский Microsoft rzdebski@microsoft.com

Интегрированные в язык запросы (LINQ) в Microsoft Visual Studio 2008

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

[email protected] http://blogs.msdn.com/roman

Page 3: Роман Здебский Microsoft rzdebski@microsoft.com

Содержание

Зачем нужен LINQ? – проблематика и постановка задачи

Основные идеи LINQ Сценарии использования Влияние LINQ на .NET языки

программирования Демонстрации

Page 4: Роман Здебский Microsoft rzdebski@microsoft.com

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

Page 5: Роман Здебский Microsoft rzdebski@microsoft.com

Отголоски старого единого мира

T/SQL

Oracle SQL*Plus

USE NorthwindSELECT ProductName,UnitPrice, UnitsInStockFROM productsWHERE productID<3 COMPUTE SUM(UnitPrice),SUM(UnitsInStock)

REPF[OOTER] [PAGE] [printspec [text|variable] ...] | [OFF|ON]REPH[EADER] [PAGE] [printspec [text|variable] ...] | [OFF|ON]COMP[UTE] [function [LAB[EL] text] ...         OF {expr|column|alias} ...         ON {expr|column|alias|REPORT|ROW} ...]

ProductName UnitPrice UnitsInStock-------------- ------------ --------------Chai 18,00 39Chang 19,00 17

sum sum--------------------- -----------37,00 56

(3 row(s) affected)

Page 6: Роман Здебский Microsoft rzdebski@microsoft.com

Разработчик data-driven приложений на C# или VB

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

Page 7: Роман Здебский Microsoft rzdebski@microsoft.com

Нетипизированные острова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 = "<NewDataSet> { " +" let $bb := document(\"MyDataTest.xml\")/*/* " +" let $cc := document(\"MyDatattt.xml\")/*/* " +" for $c in $cc " +" for $b in $bb " +" where $c/kod = $b/kod " +" return <Table> { $b/nazv,$b/dat,$c/naim } </Table> " +" }</NewDataSet> “ ;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" )

Page 8: Роман Здебский Microsoft rzdebski@microsoft.com

Как собеседовали разработчиков data-driven приложений? Как сделать эффективный paging

списка на web странице? ASP NET 1.x - AllowPaging property -

True ASP NET 2.0 - Enable Paging option from

the GridView's smart tag

А если список большой… ???

Page 9: Роман Здебский Microsoft rzdebski@microsoft.com

Custom Paging

USE NorthwindSELECT RowNum, EmployeeID, LastName, FirstNameFROM (SELECT EmployeeID, LastName, FirstName, ROW_NUMBER() OVER(ORDER BY

LastName,FirstName) as RowNum FROM Employees ) as EmployeeInfoWHERE RowNum BETWEEN 1 and 5

SQL Server 2005:

SQL Server 2000:

USE NorthwindSELECT top (@pagesize) EmployeeID, LastName, FirstNameFROM (SELECT TOP (@pagesize*@pagenum) EmployeeID, LastName, FirstNameFROM Employees ORDER BY LastName DESC, FirstName DESC) as EmployeeInfoORDER BY LastName ASC, FirstName ASC

Page 10: Роман Здебский Microsoft rzdebski@microsoft.com

Стоит ли игра свеч?

Page 11: Роман Здебский Microsoft rzdebski@microsoft.com

LINQ

Language Integrated Query

Page 12: Роман Здебский Microsoft rzdebski@microsoft.com

Основная идея проекта LINQ

Сделать возможности запросов неотъемлемой частью .NET языков

Запрашивать, объединять, трансформировать:

реляционные данные XML Объекты Коллекции и списки … - в развитии идеи - ВСЁ

Page 13: Роман Здебский Microsoft rzdebski@microsoft.com

The LINQ Project

Objects

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

XML

.NET Language Integrated Query

C# 3.0 VB 9.0 Others…

Relational

LINQ toObjects

LINQ toSQL

LINQ toXML

LINQ toEntities

LINQ toDataSets

Page 14: Роман Здебский Microsoft rzdebski@microsoft.com

.NET Fx 2.0 .NET Fx 2.0Minor Update

.NET Fx 2.0Minor Update

.NET Fx 3.0.NET Fx 3.0

Update

.NET Fx 3.5

Whidbey Vista Orcas

time

Version = Assembly references + compilersНе создается новый CLR runtime

Framework Multitargeting

Page 15: Роман Здебский Microsoft rzdebski@microsoft.com

Linq запросList<City> locations = GetLocations();

IEnumerable<City> places = from city in locations where city.DistanceFromSeattle > 1000 orderby city.Country, city.Name select city;

Name=Kazan Country=Russia DistanceFromSPB=2000Name=Tver Country=Russia DistanceFromSPB=1100Name=London Country=UK DistanceFromSPB=4000

Page 16: Роман Здебский Microsoft rzdebski@microsoft.com

Два альтернативных способа записи запросаExtension methods

Формат запроса

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});

Page 17: Роман Здебский Microsoft rzdebski@microsoft.com

ДЕМОНСТРАЦИЯ

Page 18: Роман Здебский Microsoft rzdebski@microsoft.com

Почему Select в конце?Фактический порядок выполнения запросаIntellisenceУже используется (XQuery)

Execution plan

for $act in doc("hamlet.xml")//ACT let $speakers := distinct-values($act//SPEAKER) return …

Page 19: Роман Здебский Microsoft rzdebski@microsoft.com

LINQ возможностиRestriction Where

Projection Select, SelectMany

Ordering OrderBy, ThenBy

Grouping GroupBy

Joins Join, GroupJoin

Quantifiers Any, All

Partitioning Take, Skip, TakeWhile, SkipWhile

Sets Distinct, Union, Intersect, Except

Elements First, Last, Single, ElementAt

Aggregation Count, Sum, Min, Max, Average

Conversion ToArray, ToList, ToDictionary

Casting OfType<T>, Cast<T>

Page 20: Роман Здебский Microsoft rzdebski@microsoft.com

C# 3.0 в Visual Studio 2008

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

Page 21: Роман Здебский Microsoft rzdebski@microsoft.com

C# 3.0

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 initializersAnonymous

types

Local variable type

inference

Page 22: Роман Здебский Microsoft rzdebski@microsoft.com

VB 9

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

Page 23: Роман Здебский Microsoft rzdebski@microsoft.com

Implicitly typed local variablesНеявно типизированные локальные переменные

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.StringConsoleApplication1.City

Page 24: Роман Здебский Microsoft rzdebski@microsoft.com

Проекции данных

Необходимость трансформации или модификации данных полученных от запроса

LINQ позволяет осуществлять “data shaping” с помощью проекций

Удобно использовать с анонимными типами “anonymous type”, поддерживаемыми компилятором

Page 25: Роман Здебский Microsoft rzdebski@microsoft.com

Anonymous typesАнонимные типы

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

Page 26: Роман Здебский Microsoft rzdebski@microsoft.com

Extension MethodsМетоды расширения

namespace MyStuff{ public static class Extensions { public static string Concatenate(this IEnumerable<string> strings, string separator) {…} }}

using MyStuff;

string[] names = new string[] { "Axel", "Mia", "Niels" };string s = names.Concatenate(", ");

Extensionmethod

Brings extensions into scope obj.Foo(x, y)

XXX.Foo(obj, x, y)

IntelliSense!

Page 27: Роман Здебский Microsoft rzdebski@microsoft.com

Extension methods Методы расширения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());

161

Page 28: Роман Здебский Microsoft rzdebski@microsoft.com

Automatic propertiesАвтоматические свойства

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

Page 29: Роман Здебский Microsoft rzdebski@microsoft.com

Automatic properties Автоматические свойства

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; } }}

Page 30: Роман Здебский Microsoft rzdebski@microsoft.com

Automatic properties

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

Page 31: Роман Здебский Microsoft rzdebski@microsoft.com

Object InitializersИнициализаторы объектов

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

Page 32: Роман Здебский Microsoft rzdebski@microsoft.com

Collection InitializersИнициализаторы коллекций

List<int> numbers = new List<int> { 1, 10, 100 };

Must implement IEnumerable

List<int> numbers = new List<int>();numbers.Add(1);numbers.Add(10);numbers.Add(100);

Must have public Add method

Dictionary<int, string> spellings = new Dictionary<int, string> { { 0, "Zero" }, { 1, "One" }, { 2, "Two" }, { 3, "Three" } };

Add can take more than one parameter

Page 33: Роман Здебский Microsoft rzdebski@microsoft.com

Lambda выражения

IEnumerable<Customer> locals = EnumerableExtensions.Where(customers, delegate(Customer c) { return c.ZipCode == 98112; });

C# 2.0

C# 3.0 Lambda выражение

locals.Where(c => c == 98112);

Page 34: Роман Здебский Microsoft rzdebski@microsoft.com

Expression TreesFunc<int, bool> nonExprLambda = x => (x & 1) == 0;Expression<Func<int, bool>> exprLambda = x => (x & 1) ==

0; ParameterExpression xParam = Expression.Parameter(typeof(int), "x"); Expression<Func<int, bool>> exprLambda = Expression.Lambda<Func<int, bool>>(

Expression.Equal( Expression.And(xParam, Expression.Constant(1)), Expression.Constant(0)),

xParam); Console.WriteLine(exprLambda);

x => ( ( x & 1 ) = 0 )

Page 35: Роман Здебский Microsoft rzdebski@microsoft.com

LINQ Архитектура

System.Query.EnumerableBased on Delegates

Source implementsIEnumerable<T>

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.QueryableBased on Expression Trees

Source implementsIQueryable<T>

SQL DataSetsObjects Others…

Page 36: Роман Здебский Microsoft rzdebski@microsoft.com

Отложенное выполнение запросов

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

Page 37: Роман Здебский Microsoft rzdebski@microsoft.com

using System;using System.Query;using System.Collections.Generic; class app { static void Main() { string[] names = { "Allen", "Arthur",

"Bennett" };  IEnumerable<string> 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<string> 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); }}

AllenArthur

Отложенное выполнение запросов

Page 38: Роман Здебский Microsoft rzdebski@microsoft.com

Halloween problemБудьте осторожны с отложенным выполнением запросов и изменением данных

// Don't do this! NullReferenceException foreach (var phone in contacts.Descendants("phone")) { phone.Remove(); }

foreach (var phone in contacts.Descendants("phone").ToList()) { phone.Remove(); }

Page 39: Роман Здебский Microsoft rzdebski@microsoft.com

ДЕМОНСТРАЦИЯ

Page 40: Роман Здебский Microsoft rzdebski@microsoft.com

LINQ to SQLAccessing data today

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();

Queries in quotes

Loosely bound

arguments

Loosely typed result sets

No compile time checks

Page 41: Роман Здебский Microsoft rzdebski@microsoft.com

public class Customer { … }

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

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

LINQ to SQLAccessing data with LINQ

Classes describe data

Strongly typed

connections

Integrated query syntax

Strongly typed results

Tables are like collections

Page 42: Роман Здебский Microsoft rzdebski@microsoft.com

LINQ to SQL Mapping

Database

Table

View

Column

Relationship

Stored Procedure

DataContext

Class

Class

Field / Property

Field / Property

Method

Page 43: Роман Здебский Microsoft rzdebski@microsoft.com

LINQ to SQL Архитектура

Application

SQL Server

LINQ to SQL

from c in db.Customerswhere c.City == "London"select c.CompanyName

LINQ Query

SQL Query

SELECT CompanyNameFROM CustWHERE City = 'London'

Rows

Objects SubmitChanges()

DML or SProcs

db.Customers.Add(c1);c2.City = “Seattle";db.Customers.Remove(c3);

INSERT INTO Cust …UPDATE Cust …DELETE FROM Cust …

Page 44: Роман Здебский Microsoft rzdebski@microsoft.com

LINQ to SQL

Интегрированный в язык доступ к данным Связывает таблицы и записи с классами и объектами Построен поверх ADO.NET и .NET Transactions

Соответствия (Mapping) Определяются атрибутами или во внешнем XML

файле Отношения (relations) соответствуют свойствам

(Свойство Products у Category и Category у Product) Возможность отложенной или одновременной

загрузки данных через отношения (relations) Сохраняемость (Persistence)

Автоматическое отслеживание изменений Обновление через SQL или stored procedures

Page 45: Роман Здебский Microsoft rzdebski@microsoft.com

Изменение данных

Update 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(); }

NorthwindDataContext db = new NorthwindDataContext(); Supplier supplier = new Supplier{CompanyName = “ABC”}; db.Suppliers.Add(supplier); db.SubmitChanges();

Add

Page 46: Роман Здебский Microsoft rzdebski@microsoft.com

ДЕМОНСТРАЦИЯ

Page 47: Роман Здебский Microsoft rzdebski@microsoft.com

LINQ to Objects

Встроенный в C# и VB синтаксис запросов

SQL-подобные запросы по любым .NET collection (Все реализующие IEnumerable)

Мощный язык запросов

Результаты LINQ запросов легко использовать в DataBinding

Page 48: Роман Здебский Microsoft rzdebski@microsoft.com

LINQ при работе XMLПрограммирование XML сегодня

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);

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

Imperativemodel

Documentcentric

No integrated queries

Memory intensive

Page 49: Роман Здебский Microsoft rzdebski@microsoft.com

XDocument loaded = XDocument.Load(@"C:\contacts.xml");contacts var q = from c in loaded.Descendants("contact")

where (int)c.Attribute("contactId") < 4

select (string)c.Element("firstName") + “ “ + (string)c.Element("lastName");

LINQ to XMLПрограммирование XML с LINQ

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

Elementcentric

Integrated queries

Smaller and faster

Page 50: Роман Здебский Microsoft rzdebski@microsoft.com

LINQ To XML

Language integrated query для XML Мощь выражений XPath / XQuery Но на C# или VB как языках

программирования Использует опыт работы с DOM

Element centric, не document centric Быстрее и компактнее

Page 51: Роман Здебский Microsoft rzdebski@microsoft.com

LINQ to XML objects

XAttributeXNode

XComment XContainer

XDeclaration

XDocument

XDocumentType

XElement

XName

XProcessingInstructionXText

XNamespace XStreamingElement

Page 52: Роман Здебский Microsoft rzdebski@microsoft.com

ДЕМОНСТРАЦИЯ

Page 53: Роман Здебский Microsoft rzdebski@microsoft.com

Parallel Language Integrated Query (PLINQ)Часть ParallelFX LINQ to Objects LINQ to XML Распараллеливание LINQ to SQL – SQL

Server Использование:

Reference System.Concurrency.dll Wrap your data source in an

IParallelEnumerable<T> with a call to the System.Linq.ParallelEnumerable.AsParallel extension method.

Page 54: Роман Здебский Microsoft rzdebski@microsoft.com

Parallel Language Integrated Query (PLINQ)

Подходы к распараллеливанию: pipelined processing stop-and-go processing inverted enumeration

IEnumerable<T> leftData = ..., rightData = ...; var q = from x in leftData.AsParallel() join y in rightData on x.a == y.b select f(x, y);

Page 55: Роман Здебский Microsoft rzdebski@microsoft.com

LINQ Компоненты 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

Page 56: Роман Здебский Microsoft rzdebski@microsoft.com

LINQ Инновации

Унифицированный подход к запросам и трансформации объектов, реляционных данных и XML

Мощь запросов SQL и XQuery встроенная в C# и VB

Проверка типов, IntelliSense, refactoring запросов

Модель расширения для других языков программирования и APIs

Page 58: Роман Здебский Microsoft rzdebski@microsoft.com

ДЕМОНСТРАЦИЯ

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

Page 59: Роман Здебский Microsoft rzdebski@microsoft.com

Ресурсы

Ключевое слово – LINQ Вводим в поиск microsoft.com второй результат – The LINQ

Project

Anders Hejlsberg Chief Designer of C# Architect of LINQ project

Page 60: Роман Здебский Microsoft rzdebski@microsoft.com

Нужно ли забыть T/SQL?

Для большого числа типовых задач LINQ освобождает от необходимости тратить время на написание запросов

Оптимизация запросов и индексирования – по прежнему профессиональная и нужная задача

Каждый может более фокусно заниматься тем, что ему интереснее и в чем он видит свое профессиональное развитие и интерес

Page 61: Роман Здебский Microsoft rzdebski@microsoft.com

Интегрированные в язык запросы (LINQ) в Microsoft Visual Studio 2008

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

[email protected]://blogs.msdn.com/roman

Зона «Спроси Эксперта»14:00 – 15:00

Page 62: Роман Здебский Microsoft rzdebski@microsoft.com
Page 63: Роман Здебский Microsoft rzdebski@microsoft.com