0% found this document useful (0 votes)
65 views

LINQ Demo Script

This document provides a summary of a demo script that introduces developers to LINQ (Language Integrated Query). The demo is progressive and covers LINQ concepts, using LINQ with objects, XML, typed datasets, SQL, mixing SQL and XML, and XML literals in Visual Basic 9. It includes setup instructions to install databases and code snippets. The step-by-step walkthrough compares writing queries in C# 2.0 versus new features in C# 3.0 like automatic properties, implicitly typed variables, lambda expressions, object and collection initializers that simplify the code. It also introduces LINQ as providing a more declarative way to query data without specifying how.

Uploaded by

wildcat9335
Copyright
© © All Rights Reserved
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
65 views

LINQ Demo Script

This document provides a summary of a demo script that introduces developers to LINQ (Language Integrated Query). The demo is progressive and covers LINQ concepts, using LINQ with objects, XML, typed datasets, SQL, mixing SQL and XML, and XML literals in Visual Basic 9. It includes setup instructions to install databases and code snippets. The step-by-step walkthrough compares writing queries in C# 2.0 versus new features in C# 3.0 like automatic properties, implicitly typed variables, lambda expressions, object and collection initializers that simplify the code. It also introduces LINQ as providing a more declarative way to query data without specifying how.

Uploaded by

wildcat9335
Copyright
© © All Rights Reserved
Available Formats
Download as DOC, PDF, TXT or read online on Scribd
You are on page 1/ 32

The .

NET Language Integrated


Query Framework
Demo Script
Prepared by: [Demo/Script Owner(s)]

Version: 1.1

2007-08-06

This is a progressive coding demo, targeted to developers, offers a


breadth introduction to LINQ. LINQ or the Language Integrated Query,
is a new technology included with Visual Studio 2008 and the .NET
Framework 3.5 that is designed to help integrate relational data, XML
and other data sources directly from C# 2.0, 3.0 and Visual Basic 9. In
short this progressive demo covers LINQ concepts, LINQ and objects,
LINQ and xml, LINQ and typed datasets, LINQ and SQL, LINQ mixing
SQL and XML, LINQ and XML literals in VB9.

Key Messages:
1. LINQ integrates the worlds of Data and Objects.
2. LINQ provides powerful natural language query syntax to access data and objects, with independence of the data source.
3. LINQ focuses on being declarative instead of imperative.

Key Technologies:
The following technologies are utilized within this demo:
Technology / Product

Version

1. Visual Studio 2008

RTM

2. LINQ

.NET 3.5 (included with Visual Studio 2008)

3. C# 3.0

(included with Visual Studio 2008)

4. Visual Basic 9

(included with Visual Studio 2008)

Setup and Configuration


Before starting the demo, be sure to have all of the resources and code for this demo script installed. By default these files will
be extracted to C:\VS2008TrainingKit\Demos\02 LINQ. After uncompressing the demo files, be sure to set up the
environment as follows.

Reset the demo


If you already demonstrated LINQ using this demo script, then you should reset the source code.
To do this:
1. Double-click on the Reset.bat file on the demo root folder.

Install the demo (database and Visual Studio Code Snippets)


If you still didnt demonstrate LINQ using this demo script, then you should run the setup.
To do this:
1. Double-click on the Setup.bat file on the demo root folder. When prompted, choose to install the Visual Studio Code
Snippets (extensively used through the demo).
Here is a sample of the expected output:

Setting up the Visual Studio environment


1. Open Visual Studio 2008.
2. In Server Explorer, add a data connection to the Northwind database. You will need the connection for later use.

3. After creating the connection, expand it until all tables are shown.

4. Open the solution C:\VS2008TrainingKit\Demos\02 LINQ\ LINQOverview \LINQOverview.sln.


5. Double click in Program.cs (located inside the Demo project).
6. Set full screen mode with Shift+Alt+Enter.

Opening Statement
Database-centric applications have traditionally two distinct programming languages: one for the database and one for the
application.
In this talk we will introduce LINQ, a component designed to help integrate relational data, XML and other data sources directly
from C# and Visual Basic.

Step-by-step Walkthrough
Estimated time for setting up and configuring the demo: 20 minutes.
Estimated time to complete the demo: 60 minutes.

Writing an object query in C# 2.0


Action

Script

1. Go to visual studio, set it full


screen

Let me see what we can do here.

I will be using snippets for my


presentation. Snippets are a way
to write a single word like
Exception and then some code to
appear on the screen.

I am going to write an application


using C# 2.0 and then convert it to
C# 3.0 to show you where LINQ
comes into place.

2. Insert the Exception snippet

3. Remove the code in the file.


Insert the use snippet

Screenshot

4. Insert the fullcust snippet

First I'm going to write a query


against customers. So the first
thing I want is a customer object.
This is a customer object. It has
customer ID, ContactName and
City, and properties to expose
those fields.

Then I want to write a class to


operate over those customers.

It will have a static void main and a


function to return a list of
customers.

5. Insert the class snippet and fill


the class name with Driver.
6. Insert the svm snippet
7. Insert the custlist snippet

1
0

8. Select the first line of the


LoadCustomers function
9. Select the relevant code lines
as you type

10.Go to a blank area (not in a


class) and insert the resultcust
snippet

Let's take a look at this function.

I'm creating a new list of


customers.

I'm creating a new customer,


assigning 3 properties, and adding
my customer to the list. And after
doing this several times, I finally
return my list of customers.

So then, I have a customer object


and something that creates a list
of customers.

Let's say I want to bring out a list


of cities and the number of
customers for each of these cities.
But I want to do that just for the
cities that start with the letter M.
Sounds easy to do, right?

The first thing I need to do is to


create something that stores the
result of my queries. So for
example I've created a Result class
that has City and the number of
customers for that particular city.
Then I can write the code to return
those results

The first thing I want is a list of


results

Then I want to foreach over all the


customers.

And then for each that its city

11.Go to the static void Main


method and type:
List<Result> results = new
List<Result>();

12.Type:
foreach(Customer c in LoadCustomers())
{
}

1
1

13.Type inside the foreach loop:


if (c.City.StartsWith("M"))

starts with M.

Here I'm trying to find if there is


already a city that matches the
current customer's city. If there is
none, I create a new result, set its
city and start the counter and add
the result to the list of results.

If there is such a result I increment


the counter for that particular
result.

{
}

14.Insert the gclausecust snippet

1
2

15.Insert the printresults snippet

Now I'll print out the results.

16.Run the code

These are all the cities that start


with M and the number of
customers for that particular city.

Using the new features in C# 3.0


Action

Script

17.Go to the beginning of the


code and select all of the using
directives

Now let's start from the top to see


how LINQ helps to write this
particular code.

18.Insert the linquse snippet

The first thing I want to do is


adding all the USINGs we will be
using in the demo. They are not all
necessary every time, but we want
to avoid going back to this line.

19.Select all of the Customer


fields and properties

Let's take a look at this. Notice that


you are not doing anything
business-related in those property
accessors, just setting and
returning the property values. But
you still need to write all of this C#
code in 2.0.

What we did in C# 3.0 is this.


Those are called automatically
properties. Essentially the compiler

20.Replace all of the Customer


fields and properties with the
custprop snippet

Screenshot

1
3

generates all of the remaining


code.
21.Select the first line of the
static void Main method

Then look at this line of code. I


have a list of results on both sides
of the instruction. The compiler
already knows by looking at the
right side that this is a list of
results so you can just say var.
And by saying var the compiler
introduces the type from the right
side.

In fact you will see that the


compiler knows the type of the list
and inserts it there at compile
time. This is strongly typed, not
dynamic.

I can use this feature even here in


my foreach statement and you see
that the compiler knows that is a
customer.

Let's take a look at this delegate.


Delegates are a way to pass some
code to a method as if it were
something else. The syntax is
particularly cumbersome.

In C# 3 you can write it in a much


easier way by doing this. This is a
new syntax to write delegates
which is quite simple to the eye,
and it is named lambda
expressions.

22.Replace the first occurrence of


List<Customer> with var
23.Point to var and wait for the
tooltip to pop up
24.Replace Customer with var in
the foreach statement and
then point to var in the code
(wait for the tooltip to pop up)

25.Select the delegate declaration


and the delegate body
26.Type:
cust=> cust.City == c.City

1
4

Let's take a look at this. I need to


create a class for storing the
results, create and assign
properties, and just to create a
new result you need to write 4
lines of code.

In C# 3 you can do all of it in a


single line of code with what is
called object initializers (ie. create
an object using a public
constructor, setting public
properties).

29.Select all of the


LoadCustomers method body.
Replace its contents with the
newcustlist snippet

You can do something similar here.


You can initialize not only objects
but also collections.

For example, here I'm creating a


new list and in the same
instruction that creates the list I'm
assigning all the items in the list
and initializing each item in the
list. You don't need a complex
structure to initialize objects. This
feature is named collection
initializers.

30.Select the last statement from


the static void main method.
Replace it with the dump
snippet

Then let me replace this foreach


statement that is hardcoded for a
more professional way.

Let me use a little tool called


object dumper (the code is in the
sample). It does the foreach
statement, looking by Reflection
the properties and outputting its

27.Point to the then block in


the if res
28.Replace the selected code with
the addcustres snippet

31.Run the sample again (Ctrl+F5)

1
5

values with coloring.

If I execute this you will see that


the result is the same.

LINQ Object queries


Action

Script

32.Select all of the static void


main code with the exception
of the last line.

Screenshot

So far I've shown you features that


will make your life easier but it's
not a revolution. The real problem
with this thing is here. The real
problem is that you have to
represent something that is simple
and you need to tell the compiler
not only what you want it to do but
also HOW to do it. I would like a
more declarative way to express
what in your mind is. Here is where
LINQ comes into place.

1
6

Let's take a look on how it looks


like in LINQ.

35.Run the sample

Let's run it. You see that the results


are the same. This is the real
power of LINQ. This expression
looks a lot like what I said. Notice
that there is no detail on how to do
it. It looks like a query. In fact, we
took the power that is inside query
languages and brought it to C#,
being able to query independently
of the data source.

36.Select the LoadCustomers


invocation in the static void
Main method.

Let's focus on this. Just by


returning IEnumerable of
something it means that you can
query against that particular type.
If you think about it, all of the
collections in .net are
IEnumerable<T>. With no need to
change any code in every .NET
collection you can use LINQ to
query all of that. Almost everything
returned by a library (built-in or
custom) is an IEnumerable, so it's
queryable with no need to change

33.Type and explain line by line


var query = from c in LoadCustomers()
where c.City.StartsWith("M")
group c by c.City into g
select new Result {City = g.Key, Count
= g.Count()};

34.Replace results by query


in the last statement

1
7

nothing of that code.

37.Select the Result word from


the LINQ query

This may look similar to SQL with


the select inverted. There are
reasons for that. One is to support
IntelliSense (if you don't declare
what you are going to use first
then IntelliSense won't be able to
help), like first declaring your
variable and then using it.

There is still some wrong code here


(select the word Result). Note that
Result is not part of the business
domain, and I've been forced to
introduce it just to store the results
of my query. But it does not have
any business meaning.

So let's just remove it, and it will


still work.

The reason why this works is a new


feature called anonymous types.
The compiler here creates a new
type at compile time with some
crazy name that you will not be
able to use in the program, and it
will create 2 properties: City and
Count. So if you have an
application with many queries, you
don't need to create a type for
each of the queries, just let the
compiler do it.

38.Remove the Result word from


the LINQ query and the Result
class from the code
39.Run the sample

40.Select the last part from the


LINQ query (from new to } )

1
8

LINQ: Querying an XML file


Action

Script

41.Open the Customers.xml file

Until now we've done queries to


objects in memory. But most of the
time your data is not in memory,
it's somewhere else, for example,
in an XML file.

For example I have this XML file


representing the customer list you
saw in the previous example. So
lets write the code to achieve
that.

In LoadCustomers I'm going to


change how to obtain the query
elements.

I'm using LINQ to XML here. I'm


opening customers.xml,
obtaining the Customer elements
and for each Customer element,
I'm creating a new Customer
object based on the element's
attributes, and I'm returning the
list of customers. Notice that this is
all I need to do in LINQ to XML for
parsing an XML file and return a
list of objects out of it.

Notice that my query here hasn't


changed at all because I'm still
returning a list of customers so
what I'm doing stays the same.

42.Switch back to Program.cs.


43.Select the first statement from
the static void main method.
Replace it with the following
statement
var custs = from x in
XElement.Load("customers.xml").Elements
("Customer")
select new Customer {
City = x.Attribute("City").Value,
ContactName =
x.Attribute("ContactName").Value
};

44.Replace query by custs as


a parameter for ObjectDumper
45.Select the query in the static
void Main method

Screenshot

1
9

46.Run the sample (Ctrl+F5)


(after closing the example,
switch back to the previous
query)

If I run this the result is obviously


the same.

This is what I wanted from the


start, this ability to do a complex
thing fluently.

This is how to read in the XML file,


we will see in a moment how to
produce an xml file out of it with
the same simplicity.

LINQ: Querying a Typed Dataset


Action

Script

47.Replace the LoadCustomers


method declaration and body
with the dsload snippet

Let's say that I already have an


application that returns datasets,
typed datasets. Can I now query
over these datasets? Let's see how
I can do this.

Now I have a LoadCustomers


function that returns a typed
Customers DataTable. Let's
assume that I already have the
DataSet in scope.

I'm selecting data from the


database. This is the connection
string. I'm creating a new typed

48.Select the line that starts with


select *, then select the
connection string, and then
select the following lines (as
you explain)

Screenshot

2
0

DataTable and I'm filling the table.

49.Select the query from the


static void Main method and
then run the application
(Ctrl+F5)

This is code that just obtains the


typed dataset.

Now that I have a typed DataSet,


and all of my query stays the same
and also do my results. I'm
querying the database and
returning the dataset, and I'm
querying the dataset and returning
objects. And my query stays the
same because I'm still querying
objects.

If I write a new application I'd


probably not write this code. Why
should I go to the effort and
overhead of creating a typed
DataSet and then converting it to
Objects. I'm still living in 2 worlds.
In one world there is the database,
and in the other I have my objects.
I still have to think in SQL to do my
queries, so I still need to know C#
and SQL. I would really like to think
of my programs really in terms of
objects.

LINQ to SQL
Action

Script

Screenshot

2
1

50.Remove the LoadCustomers


method and the Customer
class.

So let's remove it and do


something else. So now I'm in the
situation where I have a database
and would like to access that
database in a purely strongly typed
fashion, as if it were objects, and
query them.

(Explain as you type).

Now I'm presented with a designer


surface and I can Drag and drop
for example Customers and Orders
as well. Notice that the tool infers
the one to many relationship.

I can also drag and drop stored


procedures like SalesByCategory or
Sales by Year into the tool's right
pane.

What is happening here is that my


tool is generating a strongly typed
object model from the database
that allows me to access my
database as if it were an object
model in memory.

51.In Visual Studio, go to Project |


New Item.
52.In the dialog that opens, go to
Visual C# items | Data, and
choose LINQ to SQL classes.
Name the file Northwind.dbml

53.Expand the Tables node from


the Northwind data connection
(which was previously added
to the Server Explorer) and
drag the Customers table to
the center pane. Then do the
same with the Orders table
54.Expand the Stored Procedures
node from the Northwind data
connection. Then drag and
drop the SalesByCategory
Stored Procedure to the right
pane, and then do the same
with Sales by Year

2
2

55.Return to the static void Main


method

If I go to the code and create a


new NorthwindDataContext (the
NorthwindDataContext is the
object that was created by the
designer), I can see all the tables
that were dragged and dropped
into my designer.

I can just say db.Customers and


if execute this, the results will be
the same, but this time coming
from the relational database.

Let me show the query that we


submit there. I add this little log
that brings out the queries that the
framework is doing to the console
and if I run this now you will see at
the top the query that we
submitted. Essentially, what the
Framework is doing, is taking the
object query, translating into SQL,
returning data and creating objects
out of the returned data.

56.Insert the ndc snippet before


the first statement
57.Replace the query from:
Write db. after from c in
58.Type Customers right after
db.
59.The resulting query statement
should look like this
var query = from c in db.Customers
where c.City.StartsWith("M")
group c by c.City into g
select new {city = g.Key, Count =
g.Count()};

60.Ensure that query is the


parameter for ObjectDumper
61.Run the sample
62.Insert the log snippet in the
line after the query
63.Run the sample

2
3

64.Select db.Customers from


the query

How it is doing so? The enabler is


here. This doesn't return an
IEnumerable<T> as in the
previous case. If that were the
case, then the compiler would
have generated the foreach
statement and loop through all of
the items in the database. That
would be very inefficient, and not
what youd like. But this guy
returns an IQueryable<T>.

So the compiler looks here, sees


an IQueryable<T> and translates
the query to an expression tree (an
object model that represents the
query), and gives this
representation to whatever
implementation of IQueryable<T>
I have here.

LINQ to SQL is just one possible


implementation of IQueryable<T>.
You can create your own
implementation of IQueryable<T>,
as some people already did, and
the compiler will just create an
object model that represents the
query and give it to your
implementation. The compiler only
knows that it is giving the query to
an object that implements
IQueryable<T>.

The only thing that is static here is


the shape of this query that is
compiled to an expression tree,

2
4

which is given to the


implementation. Parameters, such
as the QueryString, are not.

In LINQ to SQL, if you added or


removed a column, you'd have to
regenerate the object model, but
by doing so you wouldn't lose any
of your business logic because the
object model is created as a partial
class so the partial classes that
were not generated will be kept
when you regenerate the object
model. This is the pain and
pleasure of being strongly typed.

65.Remove the log sentence


and the query text (just leave
var query=)

Do you remember that I dragged


and dropped Stored Procedures as
well in my designer surface?

66.Type db.Sa, wait for the


IntelliSense to pop up and then
select SalesByCategory

I can call them here for example.

(type as you say)

67.Type:

And if I go and execute this the


stored procedure is executed and
the result is returned. There are
many ways to plug stored
procedures and do inserts, deletes
and updates as well.

SalesByCategory("Seafood", "");
68.Run the sample (Ctrl+F5)

2
5

LINQ to XML
Action

Script

69.Remove the static void Main


method inner statements

Now I want to talk about LINQ to


XML.

Let me introduce this.

Console.WriteLine(xml);

Let's print out the XML.

72.Run the sample (Ctrl+F5)

So this is the simplest xml


document you can create.

73.Add a second parameter to the


XElement passing the string
"Engine" and run the
application

You can add an engine to your car.

You can decide that this engine


should be better a new element,
thus creating a one thousand
engine.

When you run the application you


will see that there is a new
element that is an engine.

You can decide that you'd better


have an attribute here and your
engine becomes an attribute.

This is a new way to declare XML


documents, a very declarative
way, almost like you visualize the
XML documents. You can create
complex XML and they look like

Screenshot

70.Read and type:


var xml = new XElement("Car");

71.Type:

74.Update the line to be:


var xml = new XElement("Car", new
XElement("Engine", 1000));

75.Run the application (Ctrl+F5)


76.Replace the engine XElement
declaration with an XAttribute
declaration and run the sample

2
6

normal XML elements.

Mixing LINQ to SQL and LINQ to XML


Action

Script

77.Insert the ndc snippet as the


first line of the static void Main
method

Things start to get interesting


when you mix those domains. For
example, if I go and introduce LINQ
to SQL here...

and replace the XML to output


the results of the Stored Procedure.

Now I execute this. I'm going to the


database, submitting to the stored

78.Replace the query (2nd line on)


by:
var xml = new XElement("Sales",

Screenshot

from s in
db.SalesByCategory("Seafood", "")
where s.TotalPurchase < 5000
select new XElement("Sale",
new XAttribute("Name",
s.ProductName),
new XAttribute("Total",

2
7

procedure, returning the data,


scoping down the data and
creating an XML out of the data.

s.TotalPurchase)));
Console.WriteLine(xml);

79.Run the code (Ctrl+F5)


80.Go to the end of the static void
Main method and insert the
oldcode snippet

Just imagine doing the same thing


with the DOM and with our ADO
code.

81.Scroll through the code as you


explain the second bullet

This is how it looks like.

Part of the problem is that you lose


the semantic meaning of what is
going on, and it is not easy to
understand.

82.Remove the code you inserted


using the snippet. Run the
code again, and copy the XML
output to the clipboard

VB Demo: XML Literals in VB9


Ask if most of the audience are VB programmers or not, because the next part will rise some
questions on why this feature is in VB and not in C#, so the answer is that the decision was
made by each language's team based on their philosophy

2
8

Action

Script

83.Copy the sample output to the


clipboard

Let me run this demo once again


and copy and paste the output
because I want to use it in my VB
demo.

You may have noticed that I


haven't used VB yet but all of the
things I've shown you so far are
present in VB.

Set this project as the startup


project.

86.In the Main Sub, type Dim xml


= and paste the XML from the
clipboard

Let's create an XML variable here


and paste the XML we copied
earlier.

87.Type

I can write the output to the


console.

What happened here is that we


added XML literals to the language
in VB.

84.Open
C:\VS2008TrainingKit\Demos\0
2 LINQ\SuperVB\Module1.vb
85.Go to Project | Set as Startup
project

Console.WriteLine(xml)

88.Run the sample (Ctrl+F5)

Screenshot

2
9

89.Point to the variable


declaration and wait for the
IntelliSense to pop up

If you see what the type of the


variable this is. This is the same
XElement that we had created
before. Under the cover, the
compiler is creating the same kind
of code that I've shown you before.
It is just syntactic sugar.

Mixing XML literals and code in VB9


Action

Script

90.Type at the beginning

You can do many things with this.

Dim name="Ravioli"

You can introduce a name here.

And you can run it.

Let's say that I want to create a


different XML from this XML.

And in my report I can access this


XML by typing like you do in
XPath. The language understands
this and gives you IntelliSense.

I can query by attributes ( @ )


and IntelliSense is always there to

91.Replace the first name


pasted from the XML with:

Screenshot

<%= name %>

92.Run the sample (Ctrl+F5)


93.Go to the last line of the Static
Sub Main method and type:
Dim xml2=<Report></Report>

94.Type the following between the


Report tags (explain as you
type):
<%= from s in xml... %>

95.Continue typing until the line

3
0

becomes:

help.

<%= From s In xml...<Sale> _


Where s.@Total < 1000 _

And then I can output the results.

Notice that I've been creating XML


with XML-like syntax, accessing
XML.

97.Run the sample

I can run this. What I've done is


very similar to an XSLT in VB.

98.Rename the Report tag


name by Lines and see how
the bottom declaration is also
renamed

You've got IntelliSense everywhere.


I can rename Report by Lines and
the IDE knows what you are doing,
and it becomes part of the
language.

select <Line><%= s.@Name %></Line>%>

96.Type:
Console.WriteLine(xml2)

Summary
If you just remember 3 things: we merged data with objects, we merged programming languages with data access, and I gave
you a variety of ideas on what you can do with this; we saw the difference on doing things imperatively vs. declaratively; and we
saw that the queries can be made independently from the data source.

3
1

I would add that the queries aren't executed until the time they are accessed, for example in
a foreach statement (deferred execution)

3
2

You might also like