1 / 63

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

Интегрированные в язык запросы (LINQ) в Microsoft Visual Studio 2008 . Роман Здебский Microsoft rzdebski@microsoft.com http://blogs.msdn.com/roman. Содержание. Зачем нужен LINQ ? – проблематика и постановка задачи Основные идеи LINQ Сценарии использования

mliss
Download Presentation

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

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Интегрированные в язык запросы (LINQ) в MicrosoftVisualStudio 2008 Роман Здебский Microsoft rzdebski@microsoft.com http://blogs.msdn.com/roman

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

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

  4. Отголоски старого единого мира T/SQL Oracle SQL*Plus ProductNameUnitPriceUnitsInStock -------------- ------------ -------------- Chai18,00 39 Chang 19,00 17 sum sum --------------------- ----------- 37,00 56 (3 row(s) affected) USE Northwind SELECT ProductName,UnitPrice,UnitsInStock FROM products WHERE 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} ...]

  5. Разработчик data-driven приложений на C# или VB • Должен знать и периодически использовать: • Relational Algebra • T/SQL (SQL Server) • API (ADO, OLE DB) • XQuery • …

  6. Нетипизированные острова DataSet DS=new DataSet(); XQueryNavigatorCollectionoXQ = 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> “ ; XQueryExpressionxExpression = new XQueryExpression(strQuery); strXML = xExpression.Execute(oXQ).ToXml(); StringReaderstrReader = new StringReader(strXML); XmlTextReader reader = new XmlTextReader(strReader); DS.ReadXml(reader); DataGrid1.DataSource = DS.Tables[0]; DataGrid1.DataBind(); SqlConnectionnwindConn = new SqlConnection("Data Source=localhost;Integrated Security=SSPI;Initial Catalog=northwind"); SqlCommandcatCMD = nwindConn.CreateCommand(); catCMD.CommandText = "SELECT CategoryID, CategoryName FROM Categories“; nwindConn.Open(); SqlDataReadermyReader = catCMD.ExecuteReader(); while (myReader.Read()) { Console.WriteLine("\t{0}\t{1}", myReader.GetInt32(0), myReader.GetString(1)); } myReader.Close(); nwindConn.Close(); 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")

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

  8. Custom Paging SQL Server 2005: 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 top (@pagesize) EmployeeID, LastName, FirstName FROM ( SELECT TOP (@pagesize*@pagenum) EmployeeID, LastName, FirstName FROM Employees ORDER BY LastName DESC, FirstName DESC ) as EmployeeInfo ORDER BY LastName ASC, FirstName ASC SQL Server 2000:

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

  10. LINQ Language Integrated Query

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

  12. <book> <title/> <author/> <year/> <price/> </book> Relational Objects XML The LINQ Project C# 3.0 VB 9.0 Others… .NET Language Integrated Query LINQ toObjects LINQ toDataSets LINQ toSQL LINQ toEntities LINQ toXML

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

  14. Linq запрос List<City> locations = GetLocations(); IEnumerable<City> places = from city in locations where city.DistanceFromSeattle > 1000 orderbycity.Country, city.Name select city; Name=Kazan Country=Russia DistanceFromSPB=2000 Name=Tver Country=Russia DistanceFromSPB=1100 Name=London Country=UK DistanceFromSPB=4000

  15. Два альтернативных способа записи запроса • Extension methods • Формат запроса varcitiesSPB2 = locations.Where(c => c.DistanceFromSPB > 1000).OrderBy(c => c.Name).OrderBy(c => c.Country).Select( c => new {Name= c.Name, Country = c.Country}); varcitiesSPB = from city in locations where city.DistanceFromSPB > 1000 orderbycity.Country, city.Name select new { city.Name, city.Country };

  16. Демонстрация

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

  18. LINQ возможности

  19. C# 3.0 в Visual Studio 2008 Implicitly typed local variables Anonymous types Extension methods Lambda expressions Object initializers Query expressions Expression trees

  20. C# 3.0 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 Object initializers Anonymous types

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

  22. Implicitly typed local variablesНеявно типизированные локальные переменные vartestVal = 2 * 2; vartestVal2 = "hello".ToUpper(); vartestVal3 = new City(); Console.WriteLine(testVal.GetType()); Console.WriteLine(testVal2.GetType()); Console.WriteLine(testVal3.GetType()); System.Int32 System.String ConsoleApplication1.City

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

  24. Anonymous typesАнонимные типы <>f__AnonymousType0`2[System.Int32,System.String]

  25. Extension MethodsМетоды расширения Extensionmethod namespace MyStuff { public static class Extensions { public static string Concatenate(this IEnumerable<string> strings, string separator) {…} } } Brings extensions into scope obj.Foo(x, y)  XXX.Foo(obj, x, y) using MyStuff; string[] names = new string[] { "Axel", "Mia", "Niels" }; string s = names.Concatenate(", "); IntelliSense!

  26. Extension methods Методы расширения static class StaticExtensionClass { public static inttoGoInMiles(this City ct) { return (int)(ct.DistanceFromSPB * 1.61) ; } } City ct = new City { Name = "Bor", Country = "RUS", DistanceFromSPB = 100 }; Console.WriteLine(ct.toGoInMiles()); 161

  27. Automatic propertiesАвтоматические свойства public class Product { public string Name; public decimal Price; }

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

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

  30. 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; } } } Field or property assignments Point a = new Point { X = 0, Y = 1 }; Point a = new Point(); a.X = 0; a.Y = 1;

  31. Collection InitializersИнициализаторы коллекций Must implement IEnumerable Must have public Add method List<int> numbers = new List<int> { 1, 10, 100 }; List<int> numbers = new List<int>(); numbers.Add(1); numbers.Add(10); numbers.Add(100); Add can take more than one parameter Dictionary<int, string> spellings = new Dictionary<int, string> { { 0, "Zero" }, { 1, "One" }, { 2, "Two" }, { 3, "Three" } };

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

  33. Expression Trees Func<int, bool> nonExprLambda = x => (x & 1) == 0; Expression<Func<int, bool>> exprLambda = x => (x & 1) == 0; ParameterExpressionxParam = 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 )

  34. LINQ Архитектура 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); Source implementsIEnumerable<T> Source implementsIQueryable<T> System.Query.EnumerableBased on Delegates System.Query.QueryableBased on Expression Trees Objects SQL DataSets Others…

  35. custs names Where Select ID Name Phone c => c.City == "London" c => c.Name Отложенное выполнение запросов Customer[] custs = SampleData.GetCustomers(); 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); string[] names = query.ToArray();

  36. 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); } } Allen Arthur

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

  38. Демонстрация

  39. LINQ to SQLAccessing data today Queries in quotes SqlConnection c = new SqlConnection(…); c.Open(); SqlCommandcmd = new SqlCommand( "SELECT c.Name, c.Phone FROM Customers c WHERE c.City = @p0"); cmd.Parameters.AddWithValue("@p0", "London“); DataReaderdr = 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

  40. LINQ to SQLAccessing data with LINQ Classes describe data public class Customer { … } public class Northwind : DataContext { public Table<Customer> Customers; … } Tables are like collections Strongly typed connections 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

  41. LINQ to SQL Mapping Database DataContext Table Class View Class Column Field / Property Relationship Field / Property Stored Procedure Method

  42. LINQ to SQL Архитектура Application from c in db.Customers where c.City == "London" select c.CompanyName db.Customers.Add(c1); c2.City = “Seattle"; db.Customers.Remove(c3); LINQ Query Objects SubmitChanges() LINQ to SQL SQL Query Rows DML or SProcs SELECT CompanyName FROM Cust WHERE City = 'London' INSERT INTO Cust … UPDATE Cust …DELETE FROM Cust … SQL Server

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

  44. Изменение данных • Add • Update NorthwindDataContext db = new NorthwindDataContext(); Supplier supplier = new Supplier{CompanyName = “ABC”}; db.Suppliers.Add(supplier); 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(); }

  45. Демонстрация

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

  47. LINQ при работеXMLПрограммированиеXML сегодня Imperativemodel 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); Documentcentric No integrated queries Memory intensive <contacts> <contact> <name>Great Lakes Food</name> <phone>(503) 555-7123</phone> </contact> … </contacts>

  48. LINQ to XMLПрограммированиеXML с LINQ 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 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");

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

More Related