The Adventure of LINQ Language Integrated Query - PowerPoint PPT Presentation

1 / 79
About This Presentation
Title:

The Adventure of LINQ Language Integrated Query

Description:

Bennett Adelson. Back to the Future ... Bennett Adelson. In C# SELECT and ... new Person { Name = 'Bill', Age = 42}, new Person { Name = 'Namita', Age = 29} ... – PowerPoint PPT presentation

Number of Views:158
Avg rating:3.0/5.0
Slides: 80
Provided by: richard653
Category:

less

Transcript and Presenter's Notes

Title: The Adventure of LINQ Language Integrated Query


1
The Adventure of LINQ(Language Integrated Query)
  • Presented by
  • Richard Broida
  • Senior Architect

2
Visual Studio 2005 Team System Tour
  • Coming to Cleveland!
  • February 22, 2006
  • 900 AM 430 PM
  • Right Here
  • Free!
  • Sign Up
  • http//msevents.microsoft.com
  • Event Code 1032288761

3
Agenda
  • LINQs Quest Make Queries Easier
  • Hello, LINQ
  • LINQ Internals
  • DLINQ Using LINQ with Relational Data
  • XLINQ Using LINQ with XML
  • Resources on the Web
  • Q A

4
LINQs Quest Make Queries Easier
  • Make query syntax part of the programming
    language
  • Use the same query syntax for all types of data
  • Relational, hierarchical, or flat
  • Persistent or in-memory
  • Make query input and output always type-safe
  • Provide full tool support in IDE

5
Back to the Future
  • In 1991 FoxPro 2.0 had SQL SELECT, INSERT, UPDATE
    and DELETE integrated into the language
  • No command object just write the query
  • SQL statements could incorporate FoxPro
    expressions and functions and/or user-defined
    functions at will
  • Database data types were exactly the same as
    language data types
  • SELECT produced a table that knew its column
    names, data types and sizes

6
.NET 2.0 Still Hasnt Caught Up with FoxPro 2.0
  • SQL isnt part of your .NET language
  • No compile-time type checking
  • No IntelliSense
  • Set-based approach of SQL is foreign to
    procedural languages
  • Queries return typeless DataReaders and
    DataTables
  • Column names arent part of the object
  • Must identify by string or numeric index
  • Must cast column value to correct data type and
    size
  • Persisting objects to tables requires application
    code
  • Write it manually, or
  • Use code generator, or
  • Use runtime O/R mapper

7
What You Are -gt How You Query
  • Collections
  • Index Looping
  • IEnumerable (For Each looping)
  • Sort() and Find() methods
  • Relational Data
  • SQL
  • XML
  • XPATH
  • XQUERY
  • Active Directory
  • LDAP
  • ADSI
  • Etc

8
The Realms of LINQ
  • System.Query namespace
  • Provides default implementation of standard query
    operators for IEnumerable and IEnumerableltTgt
  • Uses in-memory iterators
  • System.Data.DLinq namespace
  • Translates standard query operators into SQL that
    executes on database server
  • System.Data.XLinq namespace
  • A new XML API that supports LINQ as alternative
    to XPath and XQuery
  • Third Party Extensions
  • Further specialization of standard query
    operators
  • Creation of new query operators

9
Hello, LINQ
10
History of LINQ
  • Conceived by Anders Hejlsberg, creator of C
  • September 2005 First technology preview for C
    2.0 (Beta 2) released at PDC
  • November 2005 Update of PDC CTP for C 2.0 RTM
  • January 2006 First technology preview for
    Visual Basic 8.0 RTM
  • ??? Future CTPs, Betas and RTM

11
Getting LINQ
  • Download latest version from
  • http//msdn.microsoft.com/netframework/future/linq
  • As of 2/14/2005, the latest versions are
  • C November 2005 Technology Preview
  • VB January 2006 Technology Preview
  • Both require
  • WinXP SP2
  • RTM of VS.NET 2005 (or C/VB Express)
  • RTM of SQL Server 2005 (or Express)
  • Dont install on a working box! Use a VM if
    possible.
  • C IDE integration doesnt install by default.
    See instructions in ReadMe.htm
  • Make sure Options - Project Templates are set to
    default locations under My Documents

12
Creating a LINQ Project in Visual Studio
  • With the current CTPs, you can only use LINQ in
    Visual Studio if you create a LINQ Project
  • Behind the scenes, this causes VS to use a
    special LINQ-enabled compiler

13
Hello, LINQ in C
  • using System.Query
  • int numbers 5, 4, 1, 3, 9, 8, 6, 7, 2, 0
  • var lowNums
  • from n in numbers
  • where n lt 5
  • select n
  • foreach (var num in lowNums )
  • Console.WriteLine(num)

14
Hello, LINQ in VB
  • Option Strict On
  • Imports System.Query
  • Dim numbers as Integer() _
  • 5, 4, 1, 3, 9, 8, 6, 7, 2, 0
  • Dim lowNums _
  • Select n _
  • From n In numbers _
  • Where n lt 5
  • For Each num In lowNums
  • Console.WriteLine(num)
  • Next

15
In C SELECT and FROM Reversed They Are
  • In C 3.0, the IDE still doesnt do background
    compilation, so it has to parse code line-by-line
  • Putting SELECT before FROM would prevent
    IntelliSense from knowing what can be SELECTed
  • Visual Basic can put SELECT first because its IDE
    supports background compilation

16
Standard Query Operators
  • These work similarly to their SQL counterparts
  • Select
  • Where
  • OrderBy/ThenBy
  • OrderByDescending/ThenByDescending
  • GroupBy
  • Count
  • Sum/Min/Max/Average

17
Positional Query Operators
  • First/FirstOrDefault
  • Returns first element satisfying a predicate
  • ElementAt
  • Returns element at a numeric position
  • Take/Skip
  • Returns all elements before/after a numeric
    position
  • TakeWhile/SkipUntil
  • Returns elements while predicate satisfied
  • Reverse
  • Returns elements in reverse order
  • Range
  • Returns subset of elements in a range

18
Set Based Query Operators
  • Combine two sets of elements
  • Union
  • Returns all distinct elements in both sets
  • Intersection
  • Returns only elements belonging to both sets
  • Except
  • Returns elements in Set A but not in Set B
  • Repeat
  • Returns multiple copies of a set of elements
  • Distinct
  • Removes duplicate elements

19
Projection Creating New Types To Hold Query
Results
  • The result of the query can be an IEnumerableltTgt
    of a new type custom-created to hold the data
  • int digits 0, 1, 2
  • string stooges Moe, Larry, Curly
  • var v from n in digits
  • select new Index n, Name stoogesn
  • foreach ( var stooge in v )
  • Console.WriteLine( Stooge 0 is 1,
  • stooge.Index, stooge.Name )

20
Projection That Creates a Nested 1-Many
Collection
  • A query can be nested inside another query to
    produce a 1-Many Collection
  • var q from c in db.Customers where c.City
    "London" select new c.CompanyName, c.Phone,
    OrderDates ( from o in c.Orders select
    o.OrderDate) .Take(5)
  • foreach( var c in q )
  • Console.WriteLine( c.CompanyName )
  • foreach( od in c.OrderDates )
  • Console.WriteLine( od )

21
What Can You Query with LINQ?
  • Any object that implements IEnumerableltTgt
  • Single-dimension arrays
  • ListltTgt
  • Etc
  • Any object that implements non-generic
    IEnumerable
  • Use OfTypeltTgt extension method to convert it to
    IEnumerableltTgt
  • ArrayList objectList GetAnArrayList()
  • IEnumerableltintgt ints objectList.OfTypeltintgt
  • IEnumerableltintgt smallInts ints.Whereltintgt(
  • i gt i lt 5 )

22
LINQ Queries Are Lazy
  • Assigning a query to an IEnumerableltTgt variable
    doesnt execute the query
  • When user iterates over members of the
    collection, each query operator executes as many
    times as needed to retrieve the next element
  • Hence the data can change while elements are
    still being retrieved
  • Use .ToListltTgt or .ToArrayltTgt to force iteration
    over the entire query in one statement
  • Creates a snapshot copy of the original data

23
Modifying a Query Before Execution
  • Since execution is deferred, query can be
    modified any number of times before iteration
  • var v from city in cities
  • where city.Name.Length gt 3
  • select city
  • if (orderAscending)
  • v from city in v
  • orderBy city.Name
  • select city
  • foreach (city in v)

24
LINQ Internals
25
LINQ Internals
  • LINQ is built from language features that are
    useful in their own right
  • .NET 2.0 Features
  • Generics
  • Anonymous Methods
  • Iterators
  • Static Classes
  • SQL Data Types
  • New Language Features
  • Compile-Time Type Inference
  • Object and Array Initializers
  • Anonymous Types
  • Extension Methods
  • Lambda Expressions
  • Expression Trees

26
LINQ Is a Compiler Technology
  • LINQ depends on compiler and library technology,
    not CLR innovations
  • The current CTPs run on the standard .NET 2.0 CLR
  • At least theoretically LINQ could RTM before the
    .NET 3.0 CLR
  • Each compiler implements LINQ differently, if at
    all

27
Compile-Time Type Inference
  • No need to declare a variables type
  • Compiler infers it from the object assigned to it
  • Because the type inference happens at compile
    time, this is still 100 type-safe
  • C
  • var v Hello // v is type string
  • v 42 // ERROR, type mismatch
  • var w // ERROR, what type is it?
  • VB
  • dim v Hello v is type String
  • v 123 ERROR, type mismatch
  • dim w ERROR, even if Option Strict Off
  • VB late binding requires Option Strict Off and
    Object variable
  • dim o as Object World
  • o 123 no error

28
Object Initializers
  • Allow creation of an object and initialization of
    its public data in one line of code, without
    calling a multi-argument constructor
  • Used to create objects in lambda expressions and
    expression trees
  • C
  • Class Person
  • public string Name
  • public int Age
  • Person p new Person Name Ralph, Age 23
  • VB
  • Dim p New Person .Name Ralph, .Age 23

29
Array Initializers
  • Person people
  • new Person Name Bill, Age 42,
  • new Person Name Namita, Age 29,
  • new Person Name Juan, Age 47,
  • new Person Name Alice, Age 31,
  • new Person Name Al, Age 22,

30
Anonymous Types
  • Compiler creates a type that matches the
    arguments used in an initializer
  • Type has only public fields, no methods
  • C
  • var p new Name Ralph, Age 23
  • VB
  • Dim p New .Name Ralph, .Age 23

31
Anonymous Types and Type Safety
  • Though unnamed in the source code, the type is
    fully defined in the IL, so there is no loss of
    type safety or IDE tool support
  • However, the type cannot be referenced outside
    its assembly
  • var fred new Name "Fred", Age 23
  • var barney new Name "Barney", Age 24
  • fred barney // OK, types are the same
  • fred 42 // ERROR, type mismatch

32
Projection Creating Anonymous Types Out of Other
Types
  • var customer
  • Name Fred Blogs, Zip 44125
  • var product
  • Name Widget, Price 16.99
  • var order customer.Name,
  • Product product.Name,
  • product.Price,
  • Quantity 12
  • Console.WriteLine(
  • Customer 0, Product 1, Total 2,
  • order.Name, order.Product,
  • order.Price x order.Quantity )

33
Extension Methods
  • The Problem How to add a method to a type you
    dont control and cant subtype?
  • Example How to add Standard Query Operators to
    IEnumerableltTgt, without deriving a new interface?
  • Solution Extension methods arent really members
    of the target type, but the syntax makes them
    look that way
  • Compile-time type safety is preserved

34
Creating Extension Methods
  • Define a Static Class
  • Define a static method whose first argument is an
    object of type T
  • System.Runtime.CompilerServices.Extension
    attribute on first parameter tells CLR the method
    is an Extension
  • C binds the attribute to keyword this
  • Create a T object, and call the method as if it
    were a member of the object
  • When the compiler fails to find the method among
    Ts members, it searches for an extension method
    in scope with matching name and signature

35
Extension Method in C
  • public static class StringExtender
  • const string vowels "aeiouy"
  • // keyword this indicates the
    CompilerServices.ExtensionAttribute
  • public static string NoVowels( this string s )
  • StringBuilder sb new StringBuilder()
  • foreach ( char c in s )
  • if ( -1 vowels.IndexOf(c) )
  • sb.Append(c)
  • return sb.ToString()
  • static void Main()
  • string s "abcde"
  • // string appears to have a NoVowels() method
  • Console.WriteLine( s.NoVowels() ) // outputs
    bcd

36
Extension Method in VB
  • ltSystem.Runtime.CompilerServices.Extension()gt _
  • Public Module StringExtender
  • Const vowels As String "aeiouy"
  • ltSystem.Runtime.CompilerServices.Extension()gt _
  • Public Function NoVowels(ByVal Me As String)
    As String
  • Dim sb As New System.Text.StringBuilder()
  • For Each Dim c As Char In Me
  • If -1 vowels.IndexOf(c) Then
  • sb.Append(c)
  • End If
  • Next
  • Return sb.ToString()
  • End Function
  • End Module

37
LINQ Implements Standard Query Operators As
Extension Methods
  • namespace System.Query
  • public static class Sequence
  • public static IEnumerableltTgt WhereltTgt(
  • this IEnumerableltTgt source,
  • FuncltT, boolgt predicate)
  • foreach (T item in source)
  • if (predicate(item))
  • yield return item

38
Replacing LINQ Extension Methods
  • Extension Methods have lower priority of
    resolution than type members
  • So if a type has a member with same signature as
    a LINQ extension method, the types member will
    be called, and there is no ambiguity
  • class MyList IEnumerableltintgt
  • public IEnumerableltintgt Where(
  • Funcltint,boolgt filter)
  • // LINQ queries on MyList objects will call
    this
  • // instead of Sequence.Where()
  • This is how DLINQ and XLINQ replace the default
    LINQ implementations of the Standard Query
    Operators

39
Lambda Expressions
  • Extends .NET 2.0 Anonymous Methods with even
    simpler syntax
  • Like anonymous methods, theres no need to call
    an existing method on a type
  • Like anonymous methods, local variables stay in
    scope when the lambda expression executes
  • No need for delegate keyword
  • No need to restate the parameter types
  • Syntax
  • parameters gt expression
  • As of February 2006, C supports lambda
    expressions, but VB does not and may never

40
Comparing Delegates, Anonymous Methods and Lambda
Expressions
  • class LotsOfUppers
  • delegate string MyDelegate(string s)
  • private static string MyFunc(string s) return
    s.ToUpper()
  • static void Main()
  • Console.WriteLine( MyFunc(Calling a
    Function)
  • MyDelegate del
  • del new MyDelegate( MyFunc )
  • Console.WriteLine( del(Calling a .NET 1.0
    Delegate") )
  • del delegate( string s ) return
    s.ToUpper()
  • Console.WriteLine( del(Calling a .NET 2.0
    Anonymous Method") )
  • del s gt s.ToUpper()
  • Console.WriteLine( del(Calling a .NET 3.0
    Lambda Expression") )

41
Parameters to Lambda Expressions
  • Implicitly typed parameter
  • Parentheses optional for single implicitly typed
    parameter
  • x gt x 1
  • (x) gt x 1
  • Explicitly typed parameter
  • (int x) gt x 1
  • int x gt x 1 //ERROR, no parens
  • Implicitly typed, multiple parameters
  • (x, y) gt x y
  • x, y gt x y //ERROR, no parens
  • No parameters
  • Not supported in current CTP
  • () gt Console.WriteLine()

42
Lambda Body Can Be Single Expression or Statement
Block
  • Expression body
  • x gt x 1
  • Statement block body
  • x gt return x 1
  • Statement body can have arbitrarily many lines
  • As of February 2006, the current CTP does not
    support statement bodies in lambdas. You must use
    .NET 2.0 anonymous methods instead.
  • Only expression body lambdas can compile into
    expression trees

43
Hello, LINQ With Explicit Lamba Expressions
  • using System.Query
  • int numbers 5, 4, 1, 3, 9, 8, 6, 7, 2, 0
  • var lowNums
  • numbers
  • .Where(n gt n lt 5)
  • .Select (n gt n)

44
Expression Trees
  • When compiled as a delegate, lambda expression
    produces IL code just like a classic delegate or
    anonymous method
  • In that case, only benefit is simpler syntax
  • Or, lambda expression can be compiled to an
    expression tree
  • An efficient in-memory data structure that makes
    the structure of the expression transparent and
    explicit
  • This allows the expression to be evaluated,
    copied and modified without using reflection
  • DLINK uses expression trees to construct SQL
    statements that can execute on database server

45
Expression Tree Example
  • delegate bool MyDelegate(int i)
  • MyDelegate il n gt n lt 5
  • Console.WriteLine( il(7)) // OK, il is an
    executable delegate
  • ExpressionltMyDelegategt ex n gt n gt 4
  • Console.WriteLine( ex(7) ) // ERROR, ex not
    executable
  • BinaryExpression body (BinaryExpression)ex.Body
  • ParameterExpression left (ParameterExpression)
    body.Left
  • ConstantExpression right (ConstantExpression)b
    ody.Right
  • Console.WriteLine( "BODY 0, LEFT 1, RIGHT
    2",
  • body, left, right )
  • // BODY GT(n, 4), LEFT n, RIGHT 4

46
Types of Expression Tree Nodes
  • BinaryExpression
  • ConstantExpression
  • FuncletExpression
  • InvocationExpression
  • LambdaExpression
  • MemberExpression
  • MethodCallExpression
  • NAryExpression
  • NewArrayExpression
  • NewExpression
  • ParameterExpression
  • TernaryExpression
  • TypeBinaryExpression
  • UnaryExpression

47
DLINQ
48
DLINQ Using LINQ with Relational Databases
  • DLINQ is the next version of ADO.NET
  • DLINQ supports class-first design
  • Write classes
  • Use attributes to map classes to tables and
    properties to columns
  • DLINQ supports both data retrieval and updates
  • Currently DLINQ only supports SQL Server 2005

49
How DLINQ Works
  • DLINQ does not execute queries the database
    server does
  • DLINQ queries are compiled to expression trees
    rather than IL
  • At runtime DLINQ parses the expression trees,
    constructs equivalent T-SQL statements, and sends
    them to the server
  • Statements are not executed as SQL/CLR
  • Thus .NET expressions that cannot translate to
    T-SQL are disallowed
  • Cant call .NET functions with no T-SQL equivalent

50
Attribute-Based DLINQ Mapping
  • Table(NameCustomers)
  • class Customer
  • Column(IDtrue)
  • public string CustomerID
  • Column
  • public string City
  • Column
  • public string PostalCode

51
The DataContext
  • Like an xxxConnection in ADO.NET, the DataContext
    class binds table objects to a database
    connection
  • By making the tables members of a DataContext
    subclass, the binding takes place transparently
  • class NorthWind DataContext
  • public TableltCustomergt Customers
  • public TableltOrdergt Orders
  • public NorthWind( string connection )
  • base( connection )

52
Hello, DLINQ
  • NorthWind db new NorthWind(
  • connectonString )
  • var londonCustomers
  • from c in db.Customers
  • where c.City London
  • select c
  • foreach ( Customer c in londonCustomers )
  • Console.WriteLine( c.ContactName )

53
When Does the Query Go to the Database?
  • In the previous example, the query goes to the
    database at the first iteration of the foreach
    loop
  • All the rows come back, so subsequent iterations
    retrieve the data from memory
  • If the same query is iterated in a second foreach
    loop, the query will go to the database a second
    time
  • To prevent this, copy the result of the query
    with ToListltTgt() or ToArrayltTgt() and iterate over
    the copy

54
Declaring Parent-Child Relationship
  • Table(Name"Customers")
  • public class Customer
  • Column(Idtrue) public string
    CustomerID ...
  • private EntitySetltOrdergt _Orders
  • Association(Storage"_Orders",
    OtherKey"CustomerID")
  • public EntitySetltOrdergt Orders
  • get return this._Orders set
    this._Orders.Assign(value)

55
Declaring Child-Parent Relationship
  • Table(Name"Orders")
  • public class Order
  • Column(Idtrue)
  • public int OrderID
  • Column
  • public string CustomerID
  • private EntityRefltCustomergt _Customer
  • Association(Storage"_Customer",
    ThisKey"CustomerID")
  • public Customer Customer
  • get return this._Customer.Entity set
    this._Customer.Entity value

56
Attribute-Based Joins
  • // parent to children
  • var q
  • from c in db.Customers, o in c.Orders
  • where c.City "London
  • select new c, o
  • // child to parent
  • var q
  • from o in db.Orders
  • where o.Customer.City "London
  • select new c o.Customer, o

57
Controlling How Much Joined Data To Retrieve
  • By default, a DLINQ query only retrieves what is
    requested in Select clause.
  • Use .Including() method to retrieve data for
    related objects at same time
  • var q (
  • from c in db.Customers
  • where c.City London
  • select c)
  • .Including(c gt c.Orders)

58
Executing Part of a Query on Database Server and
Part Locally
  • .ToSequence() tells DLINK to run the query on the
    database server up to that point, then run the
    rest of the query locally
  • var q from c in db.Customers where c.City
    London select new c.ContactName, c.Phone
  • // cant call these functions on database server
  • var q2
  • from c in q.ToSequence()
  • select new MyType Name DoNameProcessing(c.C
    ontactName),
  • Phone DoPhoneProcessing(c.Phone)

59
Updating the Database
  • DataContext tracks changes to Tables in memory.
  • SubmitChanges() submits them to database.
  • Northwind db new Northwind("northwnd.mdf")
  • var cust db.Customers.First(c gt c.ID
    ACKE")
  • cust.ContactName "New Contact"
  • Order order cust.Orders0
  • db.Orders.Remove(order)
  • order new Order OrderId 12345
    cust.Orders.Add(order)
  • db.SubmitChanges()

60
The SQLMetal Utility
  • Command line utility provided with current CTP to
    automate creation of annotated entity classes to
    match a database schema
  • SqlMetal /server.\SQLExpress /databaseNorthwin
    d
  • /delayfetch
  • /pluralize
  • /namespacenwind
  • /codeNorthwind.cs

61
XLINQ
62
XLINQ Using LINQ with XML
  • Intended to be a complete XML API with all
    features of WC3 DOM
  • Simpler and more efficient
  • Integrates XML with other data sources supported
    by LINQ
  • Still supports traditional DOM-style programming

63
XLINQ (XElement) vs. DOM (XmlElement)
  • XElement neednt be part of a document object
  • An XDocument can be created if needed, but
    XElements can exist without it
  • XElement.Name property doesnt include a
    namespace prefixes
  • XLINQ resolves namespaces and prefixes at
    serialization time
  • Leaf elements can be cast directly into data
  • int age (int)xAge // XLINQ
  • int age (int)xAge.InnerText //DOM
  • XElement.ToString() outputs the underlying XML
  • doh!

64
Creating XML in Memory with WC3 DOM
  • XmlDocument doc new XmlDocument()XmlElement
    name doc.CreateElement("name")name.InnerText
    Fred Blogs"XmlElement phone1
    doc.CreateElement("phone")phone1.SetAttribute("t
    ype", "home")phone1.InnerText "206-555-0144"
    XmlElement postal doc.CreateElement("pos
    tal")postal.InnerText "68042"XmlElement
    address doc.CreateElement("address")address.Ap
    pendChild(postal)XmlElement contact
    doc.CreateElement("contact")contact.AppendChild(
    name)contact.AppendChild(phone1)contact.Append
    Child(address)XmlElement contacts
    doc.CreateElement("contacts")contacts.AppendChil
    d(contact)doc.AppendChild(contacts)

65
Creating XML in Memory with XLINQ in C
  • XElement contacts new XElement("contacts", new
    XElement("contact", new XElement("name", Fred
    Blogs"), new XElement("phone", "206-555-0144",
    new XAttribute("type", "home")), new
    XElement("phone", "425-555-0145", new
    XAttribute("type", "work")), new
    XElement("address", new XElement("street1",
    "123 Main St"), new XElement("city", "Mercer
    Island"), new XElement("state", "WA"), new
    XElement("postal", "68042") ) ))
  • This is accomplished thanks to the XElement
    constructor
  • public XElement(XName name, params object
    contents)

66
Traditional XML Programming with XLINQ
  • Populate from a string using XElement.Parse(), or
    from a file, XmlReader or TextReader using
    XElement.Load()
  • XDocument doc XElement.Load(_at_"c\myContactList.
    xml")
  • Traverse the object hierarchy and manipulate
    contents
  • XElement contacts doc.Element(root).Element(
    contacts)
  • foreach ( XElement contact in
    contacts.Content() )
  • if ( Joe (string)contact.Element(name)
  • contact.Element(zip").ReplaceContent(44125")

67
LINQ Query on XLINQ Object
  • XDocument doc XDocument.Load("customers.xml")
  • var query
  • from c in
  • doc.Element("Root")
  • .Elements("Customers")
  • where
  • c.Element("FullAddress")
  • .Element("Country")
  • .Value "Germany"
  • select c
  • foreach (XElement result in query)
  • Console.WriteLine(result)

68
Casting and Filtering on an Attribute
  • string xml "ltorder gt"
  • "ltitem price'150'gtMotorlt/item
    gt"
  • "ltitem price'50'gtCablelt/itemgt
    "
  • "ltitem price'50'gtModemlt/itemgt
    "
  • "ltitem price'250'gtMonitorlt/it
    emgt"
  • "ltitem price'10'gtMouselt/itemgt
    "
  • "lt/ordergt"
  • XElement order XElement.Parse(xml)
  • var query
  • from
  • i in order.Elements("item")
  • where
  • (int)i.Attribute("price") gt 100
  • select i
  • foreach(var result in query)
  • Console.WriteLine("Expensive Item 0 costs
    1",
  • (string)result,
  • (string)result.Attribute("pr
    ice"))

69
Transforms with XLINQ
  • XDocument doc XDocument.Load("customers.xml")
  • var header new
  • new XElement("th", "customer id"),
  • new XElement("th", "contact name")
  • var rows
  • from
  • customer in doc.Descendants("Customers")
  • where
  • (decimal)customer.Element(salesYTD) gt 500,000
  • select
  • new XElement("tr",
  • new XElement("td", (string)customer.Attribute("C
    ustomerID")),
  • new XElement("td", (string)customer.Element("Con
    tact")))
  • XElement html new XElement("html",
  • new XElement("table", header, rows))
  • Console.Write(html)

70
XLINQ Enhancement for VB Only XML Literals
  • VB can create XElements in memory with XElement
    constructors, same as in C
  • Dim contacts As XElement _ New
    XElement("contacts", _ New
    XElement("contact", _ New
    XElement("name", Fred Blogs"), _ New
    XElement("phone", "206-555-0144", _
    New XAttribute("type", "home")), _
    New XElement("phone", "425-555-0145", _
    New XAttribute("type", "work")), _
    New XElement("address", _ New
    XElement("street1", "123 Main St"), _
    New XElement("city", "Mercer Island"), _
    New XElement("state", "WA"), _
    New XElement("postal", "98040"))))

71
Creating an XElement from an XML Literal
  • Wouldnt you rather do this?
  • Dim contacts As XElement _ ltcontactsgt
    ltcontactgt ltnamegtFred
    Blogslt/namegt ltphone
    type"home"gt206-555-0144lt/phonegt
    ltphone type"work"gt425-555-0145lt/phonegt
    ltaddressgt ltstreet1gt123 Main
    Stlt/street1gt ltcitygtMercer
    Islandlt/citygt ltstategtWAlt/stategt
    ltpostalgt98040lt/postalgt
    lt/addressgt lt/contactgt
    lt/contactsgt
  • Compiler converts this to same code as previous
    slide
  • No need for line continuation characters within
    the XML

72
VB XML Literals Can Contain Expressions Evaluated
at Runtim
  • Element Value from Variable
  • Dim name As XElement
  • ltnamegtltsomeVariablegtlt/namegt
  • Element Value from Function Call
  • Dim name As XElement
  • ltnamegtltSomeFunction()gtlt/namegt
  • Attribute Value from Variable
  • Dim phone as XElement
  • ltphone type(someVariable)gt234-5678lt/phonegt
  • Element Name from Variable
  • Dim contact as XElement
  • ltcontactgt
  • lt(someVariable)gtFoolt/gt
  • lt/contactgt

73
Embedding XLINQ Query Inside XML Literal
  • Dim contacts as XElement _
  • ltcontactsgt
  • lt
  • _Select _
  • ltcontactgt
  • ltnamegtltCStr(c.name(0))gtlt/namegt
  • ltc.phone gt
  • ltaddressgtltc.addressgtlt/addressgt
    ltcontact/gt
  • From c In contacts
  • gt
  • lt/contactsgt

74
XLINQ Enhancement for VB Only Late Bound XML
  • VB can apply three XPath-style navigational
    operators to an XElement
  • Child axis operator .
  • Descendants axis operator
  • Attribute axis operator _at_
  • This makes the syntax simpler than the
    index-based XElement methods
  • However, VB applies these operators at runtime
    using late binding, so their use is not type-safe

75
Late Bound XML Example
  • For Each Dim phone In contact.phone
  • Console.WriteLine(CStr(phone._at_type))
  • Next
  • Console.WriteLine(CStr(contacts...city(0)))
  • which is equivalent to
  • For Each Dim phone In Contact.Element("phone")
  • Console.WriteLine(CStr(phone.Attribute("type"))
  • Next
  • Console.WriteLine( _
  • CStr(ElementAt(contact.Descendants("city"),0)))

76
Schema-Aware XLINQ?
  • Current XLINQ CTPs are unaware of XML structure
    at compile time
  • Nodes must be located at run time using indexes,
    and values must be cast to correct data type
  • string zip (string)name.Element(zip)
  • Microsoft is investigating possibility of using
    XML Schemas at compile time/design time to
    construct strongly typed XML objects
  • string zip name.zip

77
The Adventure Continues!
78
LINQ Resources on the Web
  • LINQ Official Site
  • http//msdn.microsoft.com/netframework/future/linq
  • Barry Gervins LINQ Resources
  • http//objectsharp.com/blogs/barry/archive/2005/09
    /13/3395.aspx

79
Q A
Write a Comment
User Comments (0)
About PowerShow.com