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

Post on 04-Jan-2016

218 views 3 download

Transcript of Роман Здебский Microsoft rzdebski@microsoft.com .

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

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

rzdebski@microsoft.com http://blogs.msdn.com/roman

Содержание

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

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

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

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

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

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)

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

Должен знать и периодически использовать: 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();

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

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

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

True ASP NET 2.0 - Enable Paging option from

the GridView's smart tag

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

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

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

LINQ

Language Integrated Query

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

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

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

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

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

.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

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

Два альтернативных способа записи запроса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});

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

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

Execution plan

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

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>

C# 3.0 в Visual Studio 2008

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

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

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

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

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

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

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

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

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

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

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!

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

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

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

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

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

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

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

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

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 )

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…

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

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

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

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

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

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

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

LINQ to SQL Mapping

Database

Table

View

Column

Relationship

Stored Procedure

DataContext

Class

Class

Field / Property

Field / Property

Method

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 …

LINQ to SQL

Интегрированный в язык доступ к данным Связывает таблицы и записи с классами и объектами Построен поверх 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();

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

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

LINQ to Objects

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

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

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

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

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

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

LINQ To XML

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

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

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

LINQ to XML objects

XAttributeXNode

XComment XContainer

XDeclaration

XDocument

XDocumentType

XElement

XName

XProcessingInstructionXText

XNamespace XStreamingElement

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

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.

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

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

LINQ Инновации

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

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

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

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

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

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

Ресурсы

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

Project

Anders Hejlsberg Chief Designer of C# Architect of LINQ project

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

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

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

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

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

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

rzdebski@microsoft.comhttp://blogs.msdn.com/roman

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