You are on page 1of 138

LINQ to SQL

Microsoft LINQ Using Visual Basic 2008 4-1


Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

LINQ to SQL
Objectives
Learn how to map a data model to an object model.
Learn various techniques for using LINQ to SQL to query data in a
SQL Server database.
Explore how to modify data and save changes.
See how to use stored procedures to modify data.

The files associated with this chapter are located in the following folders:
{Install Folder}\LINQToSQL
{Install Folder}\LINQToSQLLab
{Install Folder}\LINQToSQLLabCompleted
LINQ to SQL
4-2 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

LINQ and Relational Data
At its most basic level, LINQ provides the ability to query any data source that
supports the IEnumerable or generic IEnumerable(T) interface. The data you
want to query in an application can come from a variety of sources. The data
may reside in in-memory objects. If so, you can use LINQ to Objects. The data
may reside in XML. If so, you can use LINQ to XML.
The primary source of data in most applications is a relational database, such
as SQL Server. If you have built database applications with Visual Studio, you
are familiar with using ADO.NET and building SQL statements to query and
modify data in a relational database.
In this chapter, you will see how to use LINQ to SQL to query and modify data
in a SQL Server database. You may find yourself thinking that ADO.NET
works great, so why do I need another way to work with relational data? What
advantage does LINQ to SQL offer me?
LINQ provides a consistent model for querying all types of data. With LINQ, a
query that works with objects looks similar to a query that works with XML. It
also looks similar to a query that works with relational data. If you know how
to use LINQ to Objects to write a query, you already know most of what you
need to write a query by using LINQ to SQL.
LINQ to SQL is part of the ADO.NET family of technologies. It abstracts
away the various ADO.NET classes such as SqlConnection, SqlCommand,
SqlDataAdapter, SqlDataReader, etc. You get the same functionality by
writing less code. You can also easily mix LINQ to SQL with existing
ADO.NET code.
LINQ to SQL also bridges the gap between object programming and
traditional database programming. As a .NET developer, you build
applications based on objects. The .NET Framework consists of classes. To
use the functionality that a class provides, you create an instance of the class
and then use its properties, methods, and events.
To query a database, you build a SQL statement as a string. You can then use
ADO.NET classes to send the query to the database. You can also store the
results by using the ADO.NET DataSet and DataTable classes. Is this object
programming? Yes and no. The use of ADO.NET is object programming;
however, the data model is based on tables and rows, not on objects.
To model the data as objects, you can create classes for each table in the
database. For example, you could create a Customer class with properties for
company name, address, city, region, and so on. When you query the Customer
table, you store the results in one or more instances of the Customer class.

LINQ and Relational Data
Microsoft LINQ Using Visual Basic 2008 4-3
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

LINQ to SQL provides a runtime infrastructure for managing relational data as
objects. To use LINQ to SQL, you map the structure of a relational database to
an object model. Each table in the database maps to a class. This class is an
entity class. At runtime, the .NET Framework translates LINQ queries into
SQL and sends them to the database. When the database returns results, the
runtime populates the objects with the returned data.
Once you create your object model, you can use LINQ to SQL to query and
change data in a SQL Server database.
NOTE Microsoft built LINQ to SQL to support any relational database.
However, the implementation of LINQ to SQL that ships with the
.NET Framework 3.5 supports only SQL Server. It is possible that
Microsoft will support other databases in future releases.
LINQ to SQL
4-4 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Creating an Object Model
You can manually create the object model that you need to work with LINQ to
SQL, although this can be a laborious, time-consuming process. Alternatively,
you can use the Object Relational Designer in Visual Studio. This feature
provides a design surface for creating classes and associations (relationships)
based on tables in a database.
In addition to generating classes, the Object Relational Designer generates an
instance of the strongly typed DataContext class, which is in the
System.Data.Linq namespace. The DataContext class is responsible for
communication between the entity classes and the database. It contains the
connection string information and methods for connecting to the database and
manipulating the data in the database.
Table 1 shows how a relational database maps to an object model. The
DataContext class represents the database, and an entity class represents each
table.

Database Concept Object Representation
Database DataContext class
Table or View Entity class
Column Field or property
Relationship Field or property (collection)
Stored procedure Method
Table 1. This is how a relational database maps to an object model.
Try It Out!
In this section, you will use the Object Relational Designer to create an object
model based on the SQL Server Northwind database.
1. In Visual Studio 2008, select File|New Project. Select Windows from the
Project Types list. Then select Empty Project from the Templates pane.
2. Name the project and solution ObjectModelDemo. Click OK.
3. Select Project|Add New Item.
4. In the Add New Item dialog box, select LINQ to SQL Classes from the
Templates pane.
Creating an Object Model
Microsoft LINQ Using Visual Basic 2008 4-5
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

5. Enter Northwind in the Name text box and click Add. You should see the
Object Relational Designer, as shown in Figure 1. The designer has two
panes. The left pane is for creating entity classes. The right pane is for
mapping stored procedures to methods.

Figure 1. The Object Relational Designer before you create your object model.
6. Select View|Server Explorer to display the Server Explorer window.
7. In the Server Explorer window, click the Connect to Database button.
8. In the Add Connection dialog box, click Change. This displays the
Change Data Source dialog box, as shown in Figure 2.
LINQ to SQL
4-6 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Figure 2. Select the data source to use in the application.
9. In the Change Data Source dialog box, select Microsoft SQL Server.
Click OK.
10. In the Add Connection dialog box, enter .\SQLEXPRESS in the Server
name text box. This indicates that you want to use the default instance of
SQL Express on this computer.
11. Select Northwind from the Select or enter a database name drop-down
list. The Add Connection dialog box should look like Figure 3.
Creating an Object Model
Microsoft LINQ Using Visual Basic 2008 4-7
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Figure 3. Select SQL Express and the Northwind database as your data source.
12. In the Add Connection dialog box, click Test Connection. After you
receive a message that the connection succeeded, click OK to dismiss the
Add Connection dialog box.
13. In the Server Explorer window, expand the Data Connections node that
corresponds to the Northwind database. Expand the Tables node, so you
see the list of tables in the database, as shown in Figure 4.
LINQ to SQL
4-8 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Figure 4. You can see the tables and other objects in the Northwind database.
14. Drag the Customers table from the Server Explorer window onto the left
pane of the Object Relational Designer. You should see the Customer class
in the design surface, as shown in Figure 5. Note that the name of the class
is Customer and the source is the Customers table in the database. The
Customer class has a property for each column in the Customers table.
Creating an Object Model
Microsoft LINQ Using Visual Basic 2008 4-9
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Figure 5. You created an entity class based on the Customers table.
15. Drag the Orders table from the Server Explorer window onto the left pane
of the Object Relational Designer. You should see the Customer and Order
classes in the design surface.
In the database, a one-to-many relationship exists between the Customers and
Orders tables. The object model must include the same relationship. In the
designer, an association line connects the Customer and Order classes. An
association represents a relationship. In the Properties window, shown in
Figure 6, you can see that this relationship matches the relationship in the
database.
LINQ to SQL
4-10 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Figure 6. The Customer and Order classes are related.
16. Drag the Order Details, Products, and Categories tables from the Server
Explorer window onto the left pane of the Object Relational Designer. The
designer should look like Figure 7.
Creating an Object Model
Microsoft LINQ Using Visual Basic 2008 4-11
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Figure 7. The object model consists of five entity classes.
17. Select File|Save All.
18. In the Solution Explorer, click Show All Files.
19. Open the Northwind.designer.vb file.
You will now explore the code that Visual Studio generates when you use the
Object Relational Designer to create an object model.
NOTE This project will not build because it does not have a main
procedure. That is okay, because here you are learning how to use
the Object Relational Designer.
LINQ to SQL
4-12 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

The DataContext Class
The NorthwindDataContext class inherits from the DataContext class. When
you query the database via LINQ to SQL, the DataContext object connects to
the database, translates your query into SQL queries, and then populates
instances of the entity classes with the results.

Par t i al Publ i c Cl ass Nor t hwi ndDat aCont ext
I nher i t s Syst em. Dat a. Li nq. Dat aCont ext

The DataContext object tracks changes that you make to data. It also caches
entity instances, so that if you query a table more than once, you create only
one instance of the entity class.
The NorthwindDataContext class uses the Name property of the
DatabaseAttribute attribute to map to the Northwind database.

<Syst em. Dat a. Li nq. Mappi ng. Dat abaseAt t r i but e( _
Name: =" Nor t hwi nd" ) > _
Par t i al Publ i c Cl ass Nor t hwi ndDat aCont ext
I nher i t s Syst em. Dat a. Li nq. Dat aCont ext

When you used the Server Explorer to create a connection to the Northwind
database, you created a connection string. This connection string is stored as a
project setting named NorthwindConnectionString. The
NorthwindDataContext class uses this connection string to connect to the
database.

Publ i c Sub New( )
MyBase. New( Gl obal . Obj ect Model Demo. My. MySet t i ngs. _
Def aul t . Nor t hwi ndConnect i onSt r i ng, mappi ngSour ce)
OnCr eat ed
End Sub

The NorthwindDataContext class contains a property for each table you added
to the Object Relational Designer. The following code shows the Customers
property, which represents the Customers table.
Creating an Object Model
Microsoft LINQ Using Visual Basic 2008 4-13
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Publ i c ReadOnl y Pr oper t y Cust omer s( ) As _
Syst em. Dat a. Li nq. Tabl e( Of Cust omer )
Get
Ret ur n Me. Get Tabl e( Of Cust omer )
End Get
End Pr oper t y

When the DataContext retrieves data, it stores the data in an instance of the
System.Data.Linq.Table class. This class represents a collection of entity
classes. In the previous code, the Customers property of the DataContext is a
table of instances of the Customer entity class.
The GetTable method of the DataContext class returns a collection of objects
of a particular type. In the previous code, the type is the Customer class.
The Table class implements both the IEnumerable and generic IEnumerable(T)
interfaces. Therefore, you can use LINQ to SQL to query the Customers,
Orders, Order Details, and Products tables.
Entity Classes
When you dragged the Customer table from the Server Explorer to the Object
Relational Designer, Visual Studio created the Customer entity class.

<Tabl e( Name: =" dbo. Cust omer s" ) > _
Par t i al Publ i c Cl ass Cust omer
I mpl ement s _
Syst em. Component Model . I Not i f yPr oper t yChangi ng, _
Syst em. Component Model . I Not i f yPr oper t yChanged

Pr i vat e Shar ed empt yChangi ngEvent Ar gs As _
Pr oper t yChangi ngEvent Ar gs = New _
Pr oper t yChangi ngEvent Ar gs( St r i ng. Empt y)

LINQ to SQL
4-14 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Pr i vat e _Cust omer I D As St r i ng
Pr i vat e _CompanyName As St r i ng
Pr i vat e _Cont act Name As St r i ng
Pr i vat e _Cont act Ti t l e As St r i ng
Pr i vat e _Addr ess As St r i ng
Pr i vat e _Ci t y As St r i ng
Pr i vat e _Regi on As St r i ng
Pr i vat e _Post al Code As St r i ng
Pr i vat e _Count r y As St r i ng
Pr i vat e _Phone As St r i ng
Pr i vat e _Fax As St r i ng
Pr i vat e _Or der s As Ent i t ySet ( Of [ Or der ] )

The Customer class uses the Table attribute to map to the Customers table. It
implements the INotifyPropertyChanging and INotifyPropertyChanged
interfaces and uses the PropertyChangingEventArgs class so that the
DataContext object can track changes to customer information.
The Customer class has a property for each column in the Customers table.
The following code shows the CustomerID property.

<Col umn( St or age: =" _Cust omer I D" , _
DbType: =" NChar ( 5) NOT NULL" , CanBeNul l : =f al se, _
I sPr i mar yKey: =t r ue) > _
Publ i c Pr oper t y Cust omer I D( ) As St r i ng
Get
Ret ur n Me. _Cust omer I D
End Get
Set
I f ( St r i ng. Equal s( Me. _Cust omer I D, val ue) = f al se) Then
Me. OnCust omer I DChangi ng( val ue)
Me. SendPr oper t yChangi ng
Me. _Cust omer I D = val ue
Me. SendPr oper t yChanged( " Cust omer I D" )
Me. OnCust omer I DChanged
End I f
End Set
End Pr oper t y

Creating an Object Model
Microsoft LINQ Using Visual Basic 2008 4-15
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Each property uses the Column attribute to map to a column in the table. The
Storage parameter causes LINQ to SQL to bypass the public property accessor
and read or write directly to the backing variable for the property. The DbType
parameter identifies the SQL Server type of the column. The CanBeNull
parameter specifies whether the column can contain nulls. The IsPrimaryKey
parameter indicates whether the column is the tables primary key (or part of
the composite primary key).
The DataContext object uses the code in the property setter to track changes to
this column.
Associations Between Entities
In the Northwind database, the Customers table has a one-to-many (or parent-
child) relationship with the Orders table, based on the CustomerID column.
CustomerID is the primary key in the Customers (or parent) table and is a
foreign key in the Orders (or child) table. When you dragged both tables onto
the Object Relational Designer, Visual Studio created an association between
the two tables.
The Customer class has an Orders property that represents the orders for that
customer. The Orders property uses the Association attribute to describe the
one-to-many relationship between customers and orders.

<Associ at i on( Name: =" Cust omer _Or der " , St or age: =" _Or der s" , _
Thi sKey: =" Cust omer I D" , Ot her Key: =" Cust omer I D" ) > _
Publ i c Pr oper t y Or der s( ) As Ent i t ySet ( Of [ Or der ] )
Get
Ret ur n Me. _Or der s
End Get
Set
Me. _Or der s. Assi gn( val ue)
End Set
End Pr oper t y

The ThisKey property of the Association attribute identifies the property in the
Customer class that LINQ to SQL uses to find related orders. The OtherKey
property identifies the property in the Order class that LINQ to SQL uses to
find orders for a particular customer.
The Orders property of the Customer class contains all of the orders for a
particular customer, so it uses the EntitySet generic class to specify that it can
contain instances of the Order class.
LINQ to SQL
4-16 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Publ i c Pr oper t y Or der s( ) As Ent i t ySet ( Of [ Or der ] )

The Order class uses the EntityRef class to identify the Customer class
instance that owns an order.

Pr i vat e _Cust omer As Ent i t yRef ( Of Cust omer )

The Customer property of the Order class uses the Association attribute to
describe the relationship between customers and orders.

<Associ at i on( Name: =" Cust omer _Or der " , _
St or age: =" _Cust omer " , Thi sKey: =" Cust omer I D" , _
Ot her Key: =" Cust omer I D" , I sFor ei gnKey: =t r ue) > _
Publ i c Pr oper t y Cust omer ( ) As Cust omer
Get
Ret ur n Me. _Cust omer . Ent i t y
End Get

The IsForeignKey property identifies that this is the many (or child) side of the
one-to-many (or parent-child) relationship. The Entity property of the
EntityRef class identifies the entity class that is the parent in the relationship.
Why did you just spend this time looking at generated code? Why not just
create the object model and start querying the data? Here are several good
reasons:
It is always a good idea to have at least a high-level understanding of
what happens when you use a designer or wizard in Visual Studio. In
addition to reading the documentation, perusing the generated code
gives you an idea of the capabilities of the object model you just
created.
Understanding the mechanics of how LINQ to SQL stores information
and maintains relationships makes it easier to write LINQ to SQL
queries and to understand the queries you will see in the next section.
You do not have to use the Object Relational Designer to create your
object model, although you typically will. However, you may want a
more lightweight version of the object model, or you may want a more
customized object model. In that case, you may elect to build your
classes by hand. If you choose to do that, a review of the code
provides you with a starting point.
Creating an Object Model
Microsoft LINQ Using Visual Basic 2008 4-17
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Once you create your object model, you can query the data by using LINQ to
SQL. You will do that in the next section.
LINQ to SQL
4-18 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Querying Data
When you query data, you are asking questions. For example, who are my
customers in Spain? Which products sold the most? How many orders did a
particular customer place last year? How much revenue did we record last
quarter?
In this section, you will see examples of using LINQ to SQL to query
information in a SQL Server databaseat this point we assume that you have
a general understanding of querying using LINQ. This section will review and
discuss a variety of queries that are representative of the types of questions you
will ask when building database applications.
LINQ to SQL makes it easy to access a database and execute queries. The
queries can be as simple as returning a column from a table, or as complex as a
multiple-table join with calculations. The queries you write with LINQ to SQL
have the same syntax as queries you write with LINQ to Objects, LINQ to
DataSets, or LINQ to XML, so if you are familiar with using LINQ queries,
you have a good basic knowledge for building LINQ to SQL queries.
A LINQ to SQL query differs from other LINQ queries in that the objects you
refer to are entities, and so are mapped to objects in the database. That is why
you created the object model in the previous section before writing any
queries.
LINQ to SQL translates your queries into SQL statements and passes them to
the ADO.NET provider, which then sends them to the SQL Server for
processing. The ADO.NET provider returns the query results as a DataReader.
LINQ to SQL translates the results to an IQueryable collection of anonymous
types.
You are probably fairly well versed in writing SQL statements to query
databases, but you are new to writing LINQ to SQL queries. How do you
know whether the LINQ query that you write is really the query you want?
You can look at the results that return, but its better to see the SQL statement
that LINQ to SQL sends. You will see several ways to do this in the next
section.
Simple Queries
When you select Simple Queries in the chapters sample application, you will
execute queries that return information from the Customers table in the
Northwind database. Because the queries reference entity classes, the first
thing the application does is retrieve a reference to the DataContext.
Select Simple
Queries
Querying Data
Microsoft LINQ Using Visual Basic 2008 4-19
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Di mnwi ndDat aCont ext As New Nor t hwi ndDat aCont ext

nwi ndDat aCont ext . Log = Consol e. Out

The code next sets the Log property of the DataContext to Console.Out, which
displays the SQL statement in the console or Output window. You can set the
Log property to any instance of the TextWriter class; you are not limited to
displaying the text in the console or Output windows. You can write the SQL
to a log file if you want.
The first query returns a list of customers in the United States.

Di musaCust omer s = _
Fr omcust omer I n nwi ndDat aCont ext . Cust omer s _
Wher e cust omer . Count r y = " USA" _
Sel ect cust omer . CompanyName

This query retrieves the CompanyName column from the Customers table for
each row in which the Country column contains USA. If you were writing this
query as a SQL statement, you would write:

Sel ect CompanyName
Fr omCust omer s
Wher e Count r y = USA

At this point, LINQ to SQL has translated this query to SQL, but has not yet
sent it to the database. That does not occur until the code loops through the
result set and displays the query results.

Di spl ayHeader ( " Cust omer s i n t he US" )
For Each cust I n usaCust omer s
Consol e. Wr i t eLi ne( cust )
Next

Figure 8 shows the results of running this query, as well as the generated SQL
statement.
LINQ to SQL
4-20 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Cust omer s i n t he US
===================
SELECT [ t 0] . [ CompanyName]
FROM [ dbo] . [ Cust omer s] AS [ t 0]
WHERE [ t 0] . [ Count r y] = @p0
- - @p0: I nput NVar Char ( Si ze = 3; Pr ec = 0; Scal e = 0) [ USA]

Gr eat Lakes Food Mar ket
Hungr y Coyot e I mpor t St or e
Lazy K Kount r y St or e
Let ' s St op N Shop
Lonesome Pi ne Rest aur ant
Ol d Wor l d Del i cat essen
Rat t l esnake Canyon Gr ocer y
Save- a- l ot Mar ket s
Spl i t Rai l Beer & Al e
The Bi g Cheese
The Cr acker Box
Tr ai l ' s Head Gour met Pr ovi si oner s
Whi t e Cl over Mar ket s
Figure 8. The query returns a list of customers in the United States.
The next query returns the name, city, and region of customers in the United
States. The query orders the results by region and then by city.
Querying Data
Microsoft LINQ Using Visual Basic 2008 4-21
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Di musaCust omer s = _
Fr omcust omer I n nwi ndDat aCont ext . Cust omer s _
Wher e cust omer . Count r y = " USA" _
Sel ect cust omer . CompanyName, cust omer . Ci t y, _
cust omer . Regi on _
Or der By Regi on, Ci t y

Consol e. Wr i t eLi ne( )
Consol e. Wr i t eLi ne( usaCust omer s. ToSt r i ng)

Di spl ayHeader ( _
" Cust omer s i n t he US or der ed by r egi on and ci t y" )
For Each cust I n usaCust omer s
Consol e. Wr i t eLi ne( " {0} i n {1}, {2}" , _
cust . CompanyName, cust . Ci t y, cust . Regi on)
Next

Figure 9 shows the results of running this query.
LINQ to SQL
4-22 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

SELECT [ t 0] . [ CompanyName] , [ t 0] . [ Ci t y] , [ t 0] . [ Regi on]
FROM [ dbo] . [ Cust omer s] AS [ t 0]
WHERE [ t 0] . [ Count r y] = @p0
ORDER BY [ t 0] . [ Regi on] , [ t 0] . [ Ci t y]


Cust omer s i n t he US or der ed by r egi on and ci t y
==============================================
Ol d Wor l d Del i cat essen i n Anchor age, AK
Let ' s St op N Shop i n San Fr anci sco, CA
Save- a- l ot Mar ket s i n Boi se, I D
The Cr acker Box i n But t e, MT
Rat t l esnake Canyon Gr ocer y i n Al buquer que, NM
Hungr y Coyot e I mpor t St or e i n El gi n, OR
Gr eat Lakes Food Mar ket i n Eugene, OR
The Bi g Cheese i n Por t l and, OR
Lonesome Pi ne Rest aur ant i n Por t l and, OR
Tr ai l ' s Head Gour met Pr ovi si oner s i n Ki r kl and, WA
Whi t e Cl over Mar ket s i n Seat t l e, WA
Lazy K Kount r y St or e i n Wal l a Wal l a, WA
Spl i t Rai l Beer & Al e i n Lander , WY
Figure 9. The query returns a list of customers in the United States, ordered by
region and city.
The next query returns a list of customers whose company name begins with
the letter G. This query uses the Visual Basic Like operator. It also uses the
SQL Server wildcard character (*) in the pattern to match.

Di mgCust omer s = _
Fr omcust omer I n nwi ndDat aCont ext . Cust omer s _
Wher e cust omer . CompanyName Li ke " G*" _
Sel ect cust omer . CompanyName

Di spl ayHeader ( " Cust omer s t hat begi n wi t h G" )
For Each cust I n gCust omer s
Consol e. Wr i t eLi ne( cust )
Next



Querying Data
Microsoft LINQ Using Visual Basic 2008 4-23
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Figure 10 shows the results of running this query.
Cust omer s t hat begi n wi t h G
===========================
Gal er a del gast r nomo
Godos Coci na T pi ca
Gour met Lanchonet es
Gr eat Lakes Food Mar ket
GROSELLA- Rest aur ant e
Figure 10. The query returns a list of customers whose company name begins
with G.
The final query returns a list of cities in Spain where customers reside. The
query uses the Distinct clause to list each city once, regardless of how many
customers reside there.

Di mspai nCust omer s = _
Fr omcust omer I n nwi ndDat aCont ext . Cust omer s _
Wher e cust omer . Count r y = " Spai n" _
Sel ect cust omer . Ci t y Di st i nct

Di mdat aCommand As Syst em. Dat a. Common. DbCommand = _
nwi ndDat aCont ext . Get Command( spai nCust omer s)
Consol e. Wr i t eLi ne( )
Consol e. Wr i t eLi ne( dat aCommand. CommandText )

Di spl ayHeader ( " Ci t i es i n Spai n wi t h cust omer s" )
For Each cust I n spai nCust omer s
Consol e. Wr i t eLi ne( cust )
Next

Before generating this query, the code uses the GetCommand method of the
DataContext to retrieve the generated SQL statement. This method returns an
instance of the DbCommand class. The CommandText property of that class
contains the SQL statement.
Figure 11 shows the results of running this query.
LINQ to SQL
4-24 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

SELECT DI STI NCT [ t 0] . [ Ci t y]
FROM [ dbo] . [ Cust omer s] AS [ t 0]
WHERE [ t 0] . [ Count r y] = @p0

Ci t i es i n Spai n wi t h cust omer s
==============================
Bar cel ona
Madr i d
Sevi l l a
Figure 11. This query returns a list of cities in Spain with customers.
You can write this query in two ways. The previous query uses the Distinct
clause. The following query uses the Distinct method. The results, of course,
are the same.

Di mspai nCust omer s = _
( Fr omcust omer I n nwi ndDat aCont ext . Cust omer s _
Wher e cust omer . Count r y = " Spai n" _
Sel ect cust omer . Ci t y) . Di st i nct

You can also use the SQL Server Query Visualizer to view SQL statements.
This tool does not ship with Visual Studio; however, you can download it from
the Web. Instructions for installing and using this tool are at
http://go.appdev.com/?id=LNQE.
In debugging mode, you can hover the cursor over the query variable, which
causes the Visual Studio debugger to display the data visualizer shown in
Figure 12.

Figure 12. Click the magnifying glass to see the query.
NOTE If you did not install the SQL Server Query Visualizer, you will
not see Database Query in the data visualizer. You will see the
magnifying glass, however.
Querying Data
Microsoft LINQ Using Visual Basic 2008 4-25
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

If you click the magnifying glass in the data visualizer, you will see the SQL
Server Query Visualizer window, as shown in Figure 13 and Figure 14.

Figure 13. This is the SQL statement that LINQ to SQL will send to the database.

Figure 14. This is the generated SQL statement for the LINQ to SQL query.
LINQ to SQL
4-26 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Click the Execute button to run the query and see the results, as shown in
Figure 15.

Figure 15. You can run the query and view the results.
So far, you have seen four ways to view the SQL statement that LINQ to SQL
generates. In addition, you can use the SQL Server Profiler. Various editions
of SQL Server include this tool, such as the Developer Edition. SQL Server
Express does not include SQL Server Profiler, although you can use it with
SQL Server Express.
To use the SQL Server Profiler, you start a new trace by selecting File|New
Trace. You then connect to the SQL Server instance you want to monitor.
Then click Run in the Trace Properties dialog box.
Figure 16 shows the SQL Server Profiler after running the queries in this
section. The SQL statement associated with the final query appears in the
bottom window.
Querying Data
Microsoft LINQ Using Visual Basic 2008 4-27
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Figure 16. Monitor the generated SQL statements in the SQL Server Profiler.
Scalar Functions
A scalar function operates on a single value and returns a single value. For
example, the ToUpper method of the String class is a scalar function. It takes a
single string as an argument and it returns a single string.
When you select Scalar Functions in the chapters sample application, you will
execute queries that use scalar functions to either filter or transform data in
various tables in the database.
The first query uses the StartsWith function to return a list of product names
that begin with A.
Select Scalar
Functions
LINQ to SQL
4-28 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Di maPr oduct s = _
Fr ompr oduct I n nwi ndDat aCont ext . Pr oduct s _
Wher e pr oduct . Pr oduct Name. St ar t sWi t h( " A" ) _
Sel ect pr odName = pr oduct . Pr oduct Name

Di spl ayHeader ( " Pr oduct s t hat st ar t wi t h A" )
For Each pr od I n aPr oduct s
Consol e. Wr i t eLi ne( pr od)
Next

Figure 17 shows the results of running this query.
Pr oduct s t hat st ar t wi t h A
==========================
Al i ce Mut t on
Ani seed Syr up
Figure 17. This query returns a list of product names that start with A.
The next query returns a list of categories. It uses the Substring and ToUpper
functions to capitalize the first three letters of the category name.

Di mcat egor i esWi t hAbbr ev = _
Fr omcat egor y I n nwi ndDat aCont ext . Cat egor i es _
Sel ect name = cat egor y. Cat egor yName, _
abbr ev = cat egor y. Cat egor yName. Subst r i ng( _
0, 3) . ToUpper

Di spl ayHeader ( " Cat egor y names and abbr evi at i ons" )
For Each cat I n cat egor i esWi t hAbbr ev
Consol e. Wr i t eLi ne( " {0} ( {1}) " , _
cat . name, cat . abbr ev)
Next




Querying Data
Microsoft LINQ Using Visual Basic 2008 4-29
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Figure 18 shows the results of running this query.
Cat egor y names and abbr evi at i ons
================================
Bever ages ( BEV)
Condi ment s ( CON)
Conf ect i ons ( CON)
Dai r y Pr oduct s ( DAI )
Gr ai ns/ Cer eal s ( GRA)
Meat / Poul t r y ( MEA)
Pr oduce ( PRO)
Seaf ood ( SEA)
Figure 18. This query returns a list of categories and a three-letter abbreviation for
each.
The final query uses the Contains function to return a list of customer contacts
whose names include the word Carlos. This query returns contacts whose
name is Carlos as well as contacts whose name is Juan Carlos.

Di mcar l osCust omer s = _
Fr omcust omer I n nwi ndDat aCont ext . Cust omer s _
Wher e cust omer . Cont act Name. Cont ai ns( " Car l os" ) _
Sel ect cust omer . CompanyName, _
cust omer . Cont act Name, cust omer . Cont act Ti t l e

Di spl ayHeader ( " Cont act s named Car l os" )
For Each cust I n car l osCust omer s
Consol e. Wr i t eLi ne( " {0}, {1} at {2}" , _
cust . Cont act Name, cust . Cont act Ti t l e, _
cust . CompanyName)
Next

Figure 19 shows the results of running this query.
Cont act s named Car l os
=====================
Car l os Her nndez, Sal es Repr esent at i ve at HI LARI ON- Abast os
Car l os Gonzl ez, Account i ng Manager at LI LA- Super mer cado
Figure 19. This query returns contacts whose names include the word Carlos.
LINQ to SQL
4-30 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Aggregate Functions
An aggregate function operates on a collection of values and returns a single
value that summarizes the collection. The Count and Sum functions are
aggregate functions. They both operate on a collection and return a single
value, either the number of items or the sum of a value.
When you select Aggregate Functions in the chapters sample application, you
will execute queries that use aggregate functions to return summary
information from the database.
The first query uses the Count function to return the total number of orders.

Di mquer y1 = _
Aggr egat e or der I n nwi ndDat aCont ext . Or der s _
I nt o or der sCount = Count ( )

Di mquer y2 = _
( Fr omor der I n nwi ndDat aCont ext . Or der s _
Sel ect or der ) . Count

Consol e. Wr i t eLi ne( _
" Ther e wer e {0} t ot al or der s" , quer y1)
Consol e. Wr i t eLi ne( )
Consol e. Wr i t eLi ne( _
" Ther e wer e {0} t ot al or der s" , quer y2)

TIP: There is no deferred execution when the query returns a single value and not
a result set. In this example, the query executes as soon as it is defined. If you
display query.ToString in the previous code, you will not see the generated
SQL statementyou will see the query result. The same is true if you use the
data visualizer in debug mode. If you set the Log property of the DataContext
after the query definition, you will see nothing at all. You will see the
generated SQL statement only by using DataContext.Log before the code
defines the query, or by using the SQL Server Profiler.
The first version of this query uses the Aggregate clause to apply an aggregate
function to the collection of orders in the Orders table. The Into clause
includes the aggregate functionin this case Countand specifies that the
count be stored in the orderCount field.
Select Aggregate
Functions
Querying Data
Microsoft LINQ Using Visual Basic 2008 4-31
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

The second version of this query uses the functional syntax rather than the
query syntax. The results are the same regardless of which style of query you
use.
Figure 20 shows the results of running these queries.
Tot al number of or der s
======================
Ther e wer e 830 t ot al or der s

Ther e wer e 830 t ot al or der s
Figure 20. These queries return the total number of orders.
The next query returns summary information about orders placed for
product 7.

Di mquer y = _
Aggr egat e det ai l I n nwi ndDat aCont ext . Or der _Det ai l s _
Wher e det ai l . Pr oduct I D = 7 _
I nt o or der sCount = Count ( ) , _
or der sVal ue = _
Sum( det ai l . Uni t Pr i ce * det ai l . Quant i t y) , _
aver ageOr der = _
Aver age( det ai l . Uni t Pr i ce * det ai l . Quant i t y) , _
l ar gest Or der = _
Max( det ai l . Uni t Pr i ce * det ai l . Quant i t y) , _
smal l est Or der = _
Mi n( det ai l . Uni t Pr i ce * det ai l . Quant i t y)

Di spl ayHeader ( " Or der s summar y f or pr oduct 7" )
Consol e. Wr i t eLi ne( _
" Pr oduct 7 was or der ed {0} t i mes" , quer y. or der sCount )
Consol e. Wr i t eLi ne( _
" The t ot al val ue of or der s was {0: C}" , _
quer y. or der sVal ue)
Consol e. Wr i t eLi ne( _
" The aver age or der was {0: C}" , quer y. aver ageOr der )
Consol e. Wr i t eLi ne( _
LINQ to SQL
4-32 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

" The l ar gest or der was {0: C}" , quer y. l ar gest Or der )
Consol e. Wr i t eLi ne( _
" The smal l est or der was {0: C}" , quer y. smal l est Or der )

The query uses a Where clause to limit the results to product 7. It then uses the
Count, Sum, Average, Min, and Max functions to get the total number of
orders, as well as the total, average, lowest, and highest value of orders.
Notice that the query specifies multiplication of a decimal value (price) by a
short value (quantity). Ordinarily, the compiler would throw an exception if
you attempt to multiply a decimal by a short. Here, the database server does
the multiplication, not the .NET Runtime. LINQ to SQL identifies the
difference in data types and accounts for it in the generated SQL statement.
The server converts the quantity to a decimal and then multiplies it by the
price.
Figure 21 shows the results of running this query.
Or der s summar y f or pr oduct 7
============================
Pr oduct 7 was or der ed 29 t i mes
The t ot al val ue of or der s was $22, 464. 00
The aver age or der was $774. 62
The l ar gest or der was $2, 700. 00
The smal l est or der was $30. 00
Figure 21. This query returns summary information for orders of product 7.
The SQL Server Profiler shows that the following SQL statements executed:

exec sp_execut esql N' SELECT COUNT( *) AS [ val ue]
FROM [ dbo] . [ Or der Det ai l s] AS [ t 0]
WHERE [ t 0] . [ Pr oduct I D] = @p0' , N' @p0 i nt ' , @p0=7


exec sp_execut esql N' SELECT SUM( [ t 1] . [ val ue] ) AS [ val ue]
FROM (
SELECT [ t 0] . [ Uni t Pr i ce] *
( CONVERT( Deci mal ( 29, 4) , CONVERT( I nt , [ t 0] . [ Quant i t y] ) ) ) AS
[ val ue] , [ t 0] . [ Pr oduct I D]
FROM [ dbo] . [ Or der Det ai l s] AS [ t 0]
) AS [ t 1]
Querying Data
Microsoft LINQ Using Visual Basic 2008 4-33
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

WHERE [ t 1] . [ Pr oduct I D] = @p0' , N' @p0 i nt ' , @p0=7


exec sp_execut esql N' SELECT AVG( [ t 1] . [ val ue] ) AS [ val ue]
FROM (
SELECT [ t 0] . [ Uni t Pr i ce] *
( CONVERT( Deci mal ( 29, 4) , CONVERT( I nt , [ t 0] . [ Quant i t y] ) ) ) AS
[ val ue] , [ t 0] . [ Pr oduct I D]
FROM [ dbo] . [ Or der Det ai l s] AS [ t 0]
) AS [ t 1]
WHERE [ t 1] . [ Pr oduct I D] = @p0' , N' @p0 i nt ' , @p0=7


exec sp_execut esql N' SELECT [ t 0] . [ Or der I D] ,
[ t 0] . [ Pr oduct I D] , [ t 0] . [ Uni t Pr i ce] , [ t 0] . [ Quant i t y] ,
[ t 0] . [ Di scount ]
FROM [ dbo] . [ Or der Det ai l s] AS [ t 0]
WHERE [ t 0] . [ Pr oduct I D] = @p0' , N' @p0 i nt ' , @p0=7


exec sp_execut esql N' SELECT [ t 0] . [ Or der I D] ,
[ t 0] . [ Pr oduct I D] , [ t 0] . [ Uni t Pr i ce] , [ t 0] . [ Quant i t y] ,
[ t 0] . [ Di scount ]
FROM [ dbo] . [ Or der Det ai l s] AS [ t 0]
WHERE [ t 0] . [ Pr oduct I D] = @p0' , N' @p0 i nt ' , @p0=7

Notice that one LINQ to SQL query generates five separate SQL statements.
The first SQL query returns the count. The second returns the total value of
orders. The third returns the average value of orders. Interestingly, the fourth
and fifth queries return the order detail records for product 7. The maximum
and minimum are calculated in memory at the client, not on the server.
The final query shows an alternative way of retrieving summary information
for product 7. Rather than use a Where clause, it passes the filter to the Count
function.
LINQ to SQL
4-34 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Di mquer y = _
Aggr egat e det ai l I n nwi ndDat aCont ext . Or der _Det ai l s _
I nt o or der sCount = Count ( det ai l . Pr oduct I D = 7)

Consol e. Wr i t eLi ne( _
" Pr oduct 7 was or der ed {0} t i mes" , quer y)

Figure 22 shows the results of running this query.
Tot al number of or der s f or pr oduct 7
====================================
Pr oduct 7 was or der ed 29 t i mes
Figure 22. This query returns the number of orders for product 7.
Querying Related Tables
Often, the information you want is stored in a single table. If you want a list of
company names, product names, or dates of orders for product number 7, you
can write a query that retrieves information from a single table in the database.
In a relational database, of course, information is stored in multiple tables. If
you want to retrieve the name of a category and the names and prices of
products in that category, you will need to write a query that retrieves
information from both the Categories and Products tables.
To retrieve this information via a SQL statement, you write something like
this:

SELECT [ t 0] . [ Pr oduct Name] , [ t 0] . [ Uni t Pr i ce]
FROM [ dbo] . [ Pr oduct s] AS [ t 0]
LEFT OUTER J OI N [ dbo] . [ Cat egor i es] AS [ t 1] ON
[ t 1] . [ Cat egor yI D] = [ t 0] . [ Cat egor yI D]
WHERE [ t 1] . [ Cat egor yName] = ' Bever ages'




Select Querying
Related Tables
Querying Data
Microsoft LINQ Using Visual Basic 2008 4-35
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

The LINQ to SQL query syntax supports querying from related tables by using
the Join clause. However, as you saw earlier in the chapter, the object model
already accounts for the relationships between tables. The Products property of
the Category class contains the products for a particular category. The
Category property of the Product class contains a reference to the instance of
the Category class. That instance contains information for the products
category.
When you select Querying Related Tables in the chapters sample application,
you will execute queries that take advantage of the relationships built into the
object model and retrieve information from more than one table in the
database.
The first query returns the name and price for each product in the Beverages
category.

Di mbever ages = _
Fr ompr oduct I n nwi ndDat aCont ext . Pr oduct s _
Wher e pr oduct . Cat egor y. Cat egor yName = " Bever ages" _
Sel ect pr oduct . Pr oduct Name, pr oduct . Uni t Pr i ce

Di spl ayHeader ( " Pr oduct s i n t he Bever ages cat egor y" )
For Each pr od I n bever ages
Consol e. Wr i t eLi ne( " {0} ( {1: C}) " , _
pr od. Pr oduct Name, pr od. Uni t Pr i ce)
Next

In the previous code, product.Category returns an instance of the Category
class and that instance is populated with information for the products
category. Therefore, to retrieve the name of the products category, the code
uses product.Category.CategoryName.
Figure 23 shows the results of running this query.
LINQ to SQL
4-36 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Pr oduct s i n t he Bever ages cat egor y
==================================
Chai ( $18. 00)
Chang ( $19. 00)
Guar an Fant st i ca ( $4. 50)
Sasquat ch Al e ( $14. 00)
St eel eye St out ( $18. 00)
Ct e de Bl aye ( $263. 50)
Char t r euse ver t e ( $18. 00)
I poh Cof f ee ( $46. 00)
Laughi ng Lumber j ack Lager ( $14. 00)
Out back Lager ( $15. 00)
Rhnbr u Kl ost er bi er ( $7. 75)
Lakkal i kr i ( $18. 00)
Figure 23. This query returns a list of products in the Beverages category.
The SQL Server Query Visualizer shows the following generated SQL
statement:

exec sp_execut esql N' SELECT [ t 0] . [ Pr oduct Name] ,
[ t 0] . [ Uni t Pr i ce]
FROM [ dbo] . [ Pr oduct s] AS [ t 0]
LEFT OUTER J OI N [ dbo] . [ Cat egor i es] AS [ t 1] ON
[ t 1] . [ Cat egor yI D] = [ t 0] . [ Cat egor yI D]
WHERE [ t 1] . [ Cat egor yName] = @p0' , N' @p0
nvar char ( 9) ' , @p0=N' Bever ages'

The next query retrieves a list of customers who placed 20 or more orders and
the number of orders they placed.
Querying Data
Microsoft LINQ Using Visual Basic 2008 4-37
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Di mhi ghOr der Cust omer s = _
Fr omcust omer I n nwi ndDat aCont ext . Cust omer s _
Wher e cust omer . Or der s. Count >= 20 _
Sel ect name = cust omer . CompanyName, _
count = cust omer . Or der s. Count

Di spl ayHeader ( _
" Cust omer s wi t h 20 or mor e or der s" )
For Each cust I n Hi ghOr der Cust omer s
Consol e. Wr i t eLi ne( " {0} pl aced {1} or der s" , _
cust . name, cust . count )
Next

In the previous query, customer.Orders.Count represents the number of rows in
the Orders table that have a CustomerID equal to the CustomerID of the
current customer. In other words, it represents the number of orders for each
customer.
Figure 24 shows the results of running this query.
Cust omer s wi t h 20 or mor e or der s
================================
Er nst Handel pl aced 30 or der s
QUI CK- St op pl aced 28 or der s
Save- a- l ot Mar ket s pl aced 31 or der s
Figure 24. This query returns a list of customers with 20 or more orders.
The SQL Server Query Visualizer shows the following generated SQL
statement:
LINQ to SQL
4-38 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


SELECT [ t 0] . [ CompanyName] AS [ name] , (
SELECT COUNT( *)
FROM [ dbo] . [ Or der s] AS [ t 2]
WHERE [ t 2] . [ Cust omer I D] = [ t 0] . [ Cust omer I D]
) AS [ count ]
FROM [ dbo] . [ Cust omer s] AS [ t 0]
WHERE ( (
SELECT COUNT( *)
FROM [ dbo] . [ Or der s] AS [ t 1]
WHERE [ t 1] . [ Cust omer I D] = [ t 0] . [ Cust omer I D]
) ) >= 20

The next query also retrieves data from the Customers and Orders tables.
However, it also returns the actual orders, not just a count of the orders. To
limit the amount of data returned, the query retrieves information for
customers who placed zero, one, or two orders.

Di ml owOr der Cust omer s = _
Fr omcust omer I n nwi ndDat aCont ext . Cust omer s _
Wher e cust omer . Or der s. Count < 3 _
Sel ect cust omer . CompanyName, cust omer . Ci t y, _
cust omer . Regi on, cust omer . Or der s

Di spl ayHeader ( " Cust omer s wi t h 2 or f ewer or der s" )
For Each cust I n l owOr der Cust omer s
Consol e. Wr i t eLi ne( _
" {0} i n {1}, {2} pl aced {3} or der s" , _
cust . CompanyName, cust . Ci t y, _
cust . Regi on, cust . Or der s. Count )

For Each or der I n cust . Or der s
Consol e. Wr i t eLi ne( _
" Or der {0} pl aced {1: d} and shi pped {2: d}" , _
or der . Or der I D, or der . Or der Dat e, _
or der . Shi ppedDat e)
Next
Consol e. Wr i t eLi ne( )
Next
Querying Data
Microsoft LINQ Using Visual Basic 2008 4-39
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

In the previous code, customer.Orders is an EntitySet that contains one
instance of the Order class for each order the customer placed. The outer For
loop displays customer information and the inner For loop displays
information about each customers orders.
Figure 25 shows the results of running this query.
Cust omer s wi t h 2 or f ewer or der s
================================
Cent r o comer ci al Moct ezuma i n Mxi co D. F. , pl aced 1 or der s
Or der 10259 pl aced 7/ 18/ 1996 and shi pped 7/ 25/ 1996

FI SSA Fabr i ca I nt er . Sal chi chas S. A. i n Madr i d, pl aced 0
or der s

GROSELLA- Rest aur ant e i n Car acas, DF pl aced 2 or der s
Or der 10268 pl aced 7/ 30/ 1996 and shi pped 8/ 2/ 1996
Or der 10785 pl aced 12/ 18/ 1997 and shi pped 12/ 24/ 1997

Lazy K Kount r y St or e i n Wal l a Wal l a, WA pl aced 2 or der s
Or der 10482 pl aced 3/ 21/ 1997 and shi pped 4/ 10/ 1997
Or der 10545 pl aced 5/ 22/ 1997 and shi pped 6/ 26/ 1997

Par i s spci al i t s i n Par i s, pl aced 0 or der s
Figure 25. The query returns a list of customers with fewer than three orders and
information about the orders.
The SQL Server Query Visualizer shows the following generated SQL
statement:
LINQ to SQL
4-40 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


SELECT [ t 0] . [ CompanyName] , [ t 0] . [ Ci t y] , [ t 0] . [ Regi on] ,
[ t 1] . [ Or der I D] , [ t 1] . [ Cust omer I D] , [ t 1] . [ Empl oyeeI D] ,
[ t 1] . [ Or der Dat e] , [ t 1] . [ Requi r edDat e] , [ t 1] . [ Shi ppedDat e] ,
[ t 1] . [ Shi pVi a] , [ t 1] . [ Fr ei ght ] , [ t 1] . [ Shi pName] ,
[ t 1] . [ Shi pAddr ess] , [ t 1] . [ Shi pCi t y] , [ t 1] . [ Shi pRegi on] ,
[ t 1] . [ Shi pPost al Code] , [ t 1] . [ Shi pCount r y] , (
SELECT COUNT( *)
FROM [ dbo] . [ Or der s] AS [ t 3]
WHERE [ t 3] . [ Cust omer I D] = [ t 0] . [ Cust omer I D]
) AS [ val ue]
FROM [ dbo] . [ Cust omer s] AS [ t 0]
LEFT OUTER J OI N [ dbo] . [ Or der s] AS [ t 1] ON
[ t 1] . [ Cust omer I D] = [ t 0] . [ Cust omer I D]
WHERE ( (
SELECT COUNT( *)
FROM [ dbo] . [ Or der s] AS [ t 2]
WHERE [ t 2] . [ Cust omer I D] = [ t 0] . [ Cust omer I D]
) ) < 3
ORDER BY [ t 0] . [ Cust omer I D] , [ t 1] . [ Or der I D]

Notice the SQL statement that LINQ to SQL generates for this query. It returns
all columns in the Customers table, even though the Select clause specifies
only the CompanyName, City, and Region columns. Why is that?
This occurs because of the entity relationship between the Customer and Order
classes. You saw earlier that the Order class uses the EntityRef class to
identify the Customer class instance that owns an order.

Pr i vat e _Cust omer As Ent i t yRef ( Of Cust omer )

The Customer property of the Order class contains an instance of the Customer
class. The Customer class has a property for each column in the Customers
table. Therefore, the inclusion of customer.Orders in the query requires the
SQL statement to return enough information to populate
customer.Orders.Customer.
The final query returns the total value of orders for a particular customer.
Rather than search for the customer based on the customer ID, the code uses
the customers name.
Querying Data
Microsoft LINQ Using Visual Basic 2008 4-41
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Di mquer y = _
Aggr egat e det ai l I n nwi ndDat aCont ext . Or der _Det ai l s _
Wher e det ai l . Or der . Cust omer . CompanyName = _
" Bl auer See Del i kat essen" _
I nt o or der sVal ue = _
Sum( det ai l . Uni t Pr i ce * det ai l . Quant i t y)

Di spl ayHeader ( _
" Or der s summar y f or Bl auer See Del i kat essen" )
Consol e. Wr i t eLi ne( _
" The t ot al val ue of or der s was {0: C}" , quer y)

Figure 26 shows the results of running this query.
Or der s summar y f or Bl auer See Del i kat essen
==========================================
The t ot al val ue of or der s was $3, 239. 80
Figure 26. This query returns the total value of orders for this customer.
The SQL Server Profiler shows that the following SQL statement executed:

exec sp_execut esql N' SELECT SUM( [ t 3] . [ val ue] ) AS [ val ue]
FROM (
SELECT [ t 0] . [ Uni t Pr i ce] *
( CONVERT( Deci mal ( 29, 4) , CONVERT( I nt , [ t 0] . [ Quant i t y] ) ) ) AS
[ val ue] , [ t 2] . [ CompanyName]
FROM [ dbo] . [ Or der Det ai l s] AS [ t 0]
I NNER J OI N [ dbo] . [ Or der s] AS [ t 1] ON [ t 1] . [ Or der I D] =
[ t 0] . [ Or der I D]
LEFT OUTER J OI N [ dbo] . [ Cust omer s] AS [ t 2] ON
[ t 2] . [ Cust omer I D] = [ t 1] . [ Cust omer I D]
) AS [ t 3]
WHERE [ t 3] . [ CompanyName] = @p0' , N' @p0
nvar char ( 23) ' , @p0=N' Bl auer See Del i kat essen'

LINQ to SQL
4-42 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Lambda Expressions
To enable you to specify parameters to LINQ query methods that are actually
functions, Visual Basic C#, in Visual Studio 2008, supports a new language
feature: lambda expressions. Visual Basic uses the Function keyword to
indicate that youre creating a lambda expression. You specify one or more
parameters within parentheses, as if creating a standard function.
When you select Lambda Expressions in the chapters sample application, you
will execute queries that use lambda expressions to limit the data that a query
returns and to manipulate that data.
The first query returns the name of each product in the Beverages category,
along with the number of orders for the product and the total value of those
orders.

Di mbever ages = _
Fr ompr oduct I n nwi ndDat aCont ext . Pr oduct s _
Wher e pr oduct . Cat egor y. Cat egor yName = " Bever ages" _
Sel ect pr oduct . Pr oduct Name, _
number = pr oduct . Or der _Det ai l s. Count , _
r evenue = pr oduct . Or der _Det ai l s. Sum( _
Funct i on( o) o. Quant i t y * o. Uni t Pr i ce)

Di spl ayHeader ( " Revenue by bever age pr oduct " )
For Each pr oduct I n bever ages
Consol e. Wr i t eLi ne( _
" {0} was or der ed {1} t i mes f or a t ot al of {2: C}" , _
pr oduct . Pr oduct Name, pr oduct . number , _
pr oduct . r evenue)
Next

The query uses the lambda expression Function(o) o.Quantity * o.UnitPrice to
calculate the value of each order detail record. The query sums these values to
determine the total value of orders for each beverage product.
Figure 27 shows the results of running this query.
Select Lambda
Expressions
Querying Data
Microsoft LINQ Using Visual Basic 2008 4-43
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Revenue by bever age pr oduct
===========================
Chai was or der ed 38 t i mes f or a t ot al of $14, 277. 60
Chang was or der ed 44 t i mes f or a t ot al of $18, 559. 20
Guar an Fant st i ca was or der ed 51 t i mes f or a t ot al of
$4, 782. 60
Sasquat ch Al e was or der ed 19 t i mes f or a t ot al of $6, 678. 00
St eel eye St out was or der ed 36 t i mes f or a t ot al of
$14, 536. 80
Ct e de Bl aye was or der ed 24 t i mes f or a t ot al of
$149, 984. 20
Char t r euse ver t e was or der ed 30 t i mes f or a t ot al of
$13, 150. 80
I poh Cof f ee was or der ed 28 t i mes f or a t ot al of $25, 079. 20
Laughi ng Lumber j ack Lager was or der ed 10 t i mes f or a t ot al
of $2, 562. 00
Out back Lager was or der ed 39 t i mes f or a t ot al of $11, 472. 00
Rhnbr u Kl ost er bi er was or der ed 46 t i mes f or a t ot al of
$8, 650. 55
Lakkal i kr i was or der ed 39 t i mes f or a t ot al of $16, 794. 00
Figure 27. This query returns the number of orders for each beverage and the total
value of those orders.
The next query returns order information for a single order, based on the
order id.

Di mor der = _
nwi ndDat aCont ext . Or der s. Si ngl e( _
Funct i on( o) o. Or der I D = 10530)

Di spl ayHeader ( " Or der 10530" )
Consol e. Wr i t eLi ne( " Or der dat e: {0}" , _
or der . Or der Dat e)
Consol e. Wr i t eLi ne( " Requi r ed dat e: {0}" , _
or der . Requi r edDat e)
Consol e. Wr i t eLi ne( " Shi pped dat e: {0}" , _
or der . Shi ppedDat e)

LINQ to SQL
4-44 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

This query uses the Single operator to specify that the query will return one
row. The code passes the lambda expression Function(o) o.OrderID = 10530 to
the Single operator to identify the order that the query should return.
Figure 28 shows the results of running this query.
Or der 10530
===========
Or der dat e: 5/ 8/ 1997 12: 00: 00 AM
Requi r ed dat e: 6/ 5/ 1997 12: 00: 00 AM
Shi pped dat e: 5/ 12/ 1997 12: 00: 00 AM
Figure 28. This query returns information on order 10530.
The final query returns order information for an order that does not exist. This
causes a runtime exception, as shown in Figure 29.

Figure 29. An exception occurs if the query returns no results.
To catch the possible exception, the code uses a Try Catch block.
Querying Data
Microsoft LINQ Using Visual Basic 2008 4-45
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Tr y
Di mor der = _
nwi ndDat aCont ext . Or der s. Si ngl e( _
Funct i on( o) o. Or der I D = 530)

Di spl ayHeader ( " Or der 530" )
Consol e. Wr i t eLi ne( " Or der dat e: {0}" , _
or der . Or der Dat e)
Consol e. Wr i t eLi ne( " Requi r ed dat e: {0}" , _
or der . Requi r edDat e)
Consol e. Wr i t eLi ne( " Shi pped dat e: {0}" , _
or der . Shi ppedDat e)
Cat ch ex As I nval i dOper at i onExcept i on
Consol e. Wr i t eLi ne( " Ther e i s no or der 530" )
End Tr y

Extension Methods
Extension methods enable you to extend existing types. You can use extension
methods to extend the behavior of an existing class, whether it is a .NET
Framework class or a class you create yourself. In order for an extension
method to work, it must:
Accept a parameter, the type of which defines the class that youre
extending.
Exist within a module.
Include the <Extension()> attribute.
TIP: In order to use the Extension attribute, add an Imports statement to your code
that imports the System.Runtime.CompilerServices namespace.
When you select Extension Methods in the chapters sample application, you
will execute two queries that return the total value of orders for product 7. The
first query returns the total value of orders in dollars.
Select Extension
Methods
LINQ to SQL
4-46 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Di mquer y1 = _
Aggr egat e det ai l I n nwi ndDat aCont ext . Or der _Det ai l s _
Wher e det ai l . Pr oduct I D = 7 _
I nt o or der sVal ue = Sum( _
det ai l . Uni t Pr i ce * det ai l . Quant i t y)

Di spl ayHeader ( " Or der s summar y f or pr oduct 7" )
Consol e. Wr i t eLi ne( _
" The t ot al val ue of or der s was {0: N2} dol l ar s" , quer y1)
Consol e. Wr i t eLi ne( )

The second query uses the extension method ConvertToEuros to convert
dollars to Euros. It therefore returns the total value of orders in Euros.

Di mquer y2 = _
( Aggr egat e det ai l I n nwi ndDat aCont ext . Or der _Det ai l s _
Wher e det ai l . Pr oduct I D = 7 _
I nt o or der sVal ue = Sum( _
det ai l . Uni t Pr i ce * det ai l . Quant i t y) ) . Conver t ToEur os

Consol e. Wr i t eLi ne( _
" The t ot al val ue of or der s was {0: N2} Eur os" , quer y2)

The ConvertToEuros extension method is in the ExtensionMethods.vb file.
Querying Data
Microsoft LINQ Using Visual Basic 2008 4-47
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


I mpor t s Syst em. Runt i me. Compi l er Ser vi ces

Publ i c Modul e Ext ensi onMet hods

<Ext ensi on( ) > _
Publ i c Funct i on Conver t ToEur os( _
ByVal amount As Deci mal ) As Deci mal

Ret ur n amount * 1. 47D
End Funct i on

End Modul e

NOTE In this case, the ConvertToEuros method uses a fixed value of
1.47 to convert dollars to Euros. In a production application, you
need to retrieve the current exchange rate, perhaps via a Web
service.
Figure 30 shows the results of running these queries.
Or der s summar y f or pr oduct 7
============================
The t ot al val ue of or der s was 22, 464. 00 dol l ar s

The t ot al val ue of or der s was 33, 022. 08 Eur os
Figure 30. These queries return the total value of orders for product 7 in both
dollars and Euros.




LINQ to SQL
4-48 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Grouping
Earlier in the chapter, you saw the use of aggregate functions to calculate
summary information for a collection. You saw queries to calculate the total
number of orders and the total order value for a product. How do you obtain
this information for multiple products? Rather than running multiple queries,
you can use a Group By clause.
When you select Grouping in the chapters sample application, you will
execute queries that group the elements of a query result. The queries will use
aggregate functions to provide summary information for each group.
The first query returns a list of customers in Spain by city.

Di mspai nCust omer s = _
Fr omcust omer I n nwi ndDat aCont ext . Cust omer s _
Wher e cust omer . Count r y = " Spai n" _
Gr oup cust omer By cust omer . Ci t y _
I nt o gr oupedCust omer s = Gr oup _
Sel ect Ci t y, gr oupedCust omer s

Di spl ayHeader ( " Cust omer s i n Spai n by ci t y" )
For Each ci t y I n spai nCust omer s
Consol e. Wr i t eLi ne( _
" {0} [ {1} cust omer ( s) ] " , _
ci t y. Ci t y, ci t y. gr oupedCust omer s. Count )
For Each cust I n ci t y. gr oupedCust omer s
Consol e. Wr i t eLi ne( " {0} at {1}" , _
cust . CompanyName, cust . Addr ess)
Next
Consol e. Wr i t eLi ne( )
Next

This query uses the Group By clause to specify that customers be grouped by
city. The query uses the Into clause and Group keyword query to name the
group groupedCustomers.
Grouping occurs by one or more keys. In this example, the grouping occurs by
one key, which is city. The Select clause specifies that the query result should
include the city, identified by groupedCustomers.Key. The Select clause also
includes groupedCustomers, which specifies that the collection of customers in
each city should be included.
Select Grouping
Querying Data
Microsoft LINQ Using Visual Basic 2008 4-49
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

In the code that displays the query results, groupedCity.city represents a city
and groupedCity.customers represents the customers in that city.
Figure 31 shows the results of running this query.
Cust omer s i n Spai n
==================
Bar cel ona [ 1 cust omer ( s) ]
Gal er a del gast r nomo at Rambl a de Cat al ua, 23

Madr i d [ 3 cust omer ( s) ]
Bl i do Comi das pr epar adas at C/ Ar aqui l , 67
FI SSA Fabr i ca I nt er . Sal chi chas S. A. at C/ Mor al zar zal , 86
Romer o y t omi l l o at Gr an V a, 1

Sevi l l a [ 1 cust omer ( s) ]
Godos Coci na T pi ca at C/ Romer o, 33
Figure 31. This query returns customers in Spain, grouped by city.
The next query retrieves categories that contain more than ten products and the
products in those categories.

Di mhi ghPr oduct Cat egor i es = _
Fr ompr oduct I n nwi ndDat aCont ext . Pr oduct s _
Gr oup By cat egor yName = _
pr oduct . Cat egor y. Cat egor yName _
I nt o Gr oup _
Sel ect cat egor yName, gr oupedCat egor i es = Gr oup _
Wher e gr oupedCat egor i es. Count > 10

Di spl ayHeader ( " Cat egor i es wi t h mor e t han 10 pr oduct s" )
For Each cat I n hi ghPr oduct Cat egor i es
Consol e. Wr i t eLi ne( _
" {0} [ {1} pr oduct s] " , _
cat . cat egor yName, cat . gr oupedCat egor i es. Count )
For Each pr od I n cat . gr oupedCat egor i es
Consol e. Wr i t eLi ne( " " & pr od. Pr oduct Name)
Next
Consol e. Wr i t eLi ne( )
Next
LINQ to SQL
4-50 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

In the previous query, the filtering occurred at the customer level. The query
retrieved only customers in Spain and then grouped those customers by city. In
the next query, the filtering occurs at the group level. The query instructs SQL
Server to group products by category and to return only products within
categories that contain more than ten products.
Figure 32 shows the results of running this query.
Querying Data
Microsoft LINQ Using Visual Basic 2008 4-51
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Cat egor i es wi t h mor e t han 10 pr oduct s
=====================================
Bever ages [ 12 pr oduct s]
Chai
Chang
Guar an Fant st i ca
Sasquat ch Al e
St eel eye St out
Ct e de Bl aye
Char t r euse ver t e
I poh Cof f ee
Laughi ng Lumber j ack Lager
Out back Lager
Rhnbr u Kl ost er bi er
Lakkal i kr i

Condi ment s [ 12 pr oduct s]
Ani seed Syr up
Chef Ant on' s Caj un Seasoni ng
Chef Ant on' s Gumbo Mi x
Gr andma' s Boysenber r y Spr ead
Nor t hwoods Cr anber r y Sauce
Genen Shouyu
Gul a Mal acca
Si r op d' r abl e
Vegi e- spr ead
Loui si ana Fi er y Hot Pepper Sauce
Loui si ana Hot Spi ced Okr a
Or i gi nal Fr ankf ur t er gr ne Soe

Conf ect i ons [ 13 pr oduct s]
Pavl ova
Teat i me Chocol at e Bi scui t s
Si r Rodney' s Mar mal ade
<<To save space, t he r est of t he r esul t s ar e omi t t ed her e>
Figure 32. This query returns categories with more than ten products and the
products in those categories.
The final query returns revenue by year.
LINQ to SQL
4-52 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Di mr evenueByYear = _
Fr omor der I n nwi ndDat aCont ext . Or der s, _
det ai l I n nwi ndDat aCont ext . Or der _Det ai l s _
Wher e det ai l . Or der I s or der _
Gr oup By year = or der . Or der Dat e. Val ue. Year _
I nt o r evenue = _
Sum( det ai l . Quant i t y * det ai l . Uni t Pr i ce) _
Or der By year Descendi ng

Di spl ayHeader ( " Annual r evenue" )
For Each or der I n r evenueByYear
Consol e. Wr i t eLi ne( " {0: C} i n {1}" , _
or der . r evenue, or der . year )
Next

To calculate revenue, the query multiplies the quantity and unit price of
individual order details. To calculate annual revenue, the query groups order
details by year. The query determines the year for each order detail by
checking the date of the order. Recall that the Order_Detail class has an Order
property, which references the order. The Order class has an OrderDate
property. In this query, detail.Order.OrderDate represents the date of the order
to which the detail belongs. The OrderDate property does not have a Year
property, but the date is an instance of the DateTime structure and does have a
Year property. The query therefore uses OrderDate.Value.Year to extract the
year from the order date. The query can then group revenue by year.
Figure 33 shows the results of running this query.
Annual r evenue
==============
$469, 771. 34 i n 1998
$658, 388. 75 i n 1997
$226, 298. 50 i n 1996
Figure 33. The query returns annual revenue.

Querying Data
Microsoft LINQ Using Visual Basic 2008 4-53
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Joins
In the section on querying related tables, you saw how to write queries that
retrieve information from more than one table in the database. You saw that
because the object model already accounts for the relationships between tables,
you can write these queries based solely on entity classes. You do not have to
use the Join keyword. You can write LINQ to SQL queries by using either
entity class relationships or the Join clause. In general, you should use the
existing relationships because they are easier to write. Use the Join clause if
you have not defined a relationship between entities or if you cant achieve the
join you want using the relationships.
When you select Joins in the chapters sample application, you will execute
queries that use the Join clause to retrieve information from more than one
table.
The first query returns a list of beverages.

Di mbever ages = _
Fr omcat egor y I n nwi ndDat aCont ext . Cat egor i es _
J oi n pr oduct I n nwi ndDat aCont ext . Pr oduct s _
On cat egor y. Cat egor yI D Equal s pr oduct . Cat egor yI D _
Wher e cat egor y. Cat egor yName = " Bever ages" _
Sel ect pr oduct . Pr oduct Name, pr oduct . Uni t Pr i ce

Di spl ayHeader ( " Pr oduct s i n t he Bever ages cat egor y" )
For Each pr od I n bever ages
Consol e. Wr i t eLi ne( " {0} ( {1: C}) " , _
pr od. Pr oduct Name, pr od. Uni t Pr i ce)
Next

This query uses the Join clause to specify that the Products table is related to
the Categories table. The query uses On to identify the key of the first table
and Equals to identify the key of the second table.





Select Joins
LINQ to SQL
4-54 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Figure 34 shows the results of running this query.
Pr oduct s i n t he Bever ages cat egor y
==================================
Chai ( $18. 00)
Chang ( $19. 00)
Guar an Fant st i ca ( $4. 50)
Sasquat ch Al e ( $14. 00)
St eel eye St out ( $18. 00)
Ct e de Bl aye ( $263. 50)
Char t r euse ver t e ( $18. 00)
I poh Cof f ee ( $46. 00)
Laughi ng Lumber j ack Lager ( $14. 00)
Out back Lager ( $15. 00)
Rhnbr u Kl ost er bi er ( $7. 75)
Lakkal i kr i ( $18. 00)
Figure 34. This query returns a list of products in the Beverages category.
The SQL Server Query Visualizer shows the following generated SQL
statement:

SELECT [ t 1] . [ Pr oduct Name] , [ t 1] . [ Uni t Pr i ce]
FROM [ dbo] . [ Cat egor i es] AS [ t 0]
I NNER J OI N [ dbo] . [ Pr oduct s] AS [ t 1] ON ( [ t 0] . [ Cat egor yI D] )
= [ t 1] . [ Cat egor yI D]
WHERE [ t 0] . [ Cat egor yName] = ' Bever ages'

In the section on querying related tables, you ran the following query to
retrieve the same list of products:

Di mbever ages = _
Fr ompr oduct I n nwi ndDat aCont ext . Pr oduct s _
Wher e pr oduct . Cat egor y. Cat egor yName = " Bever ages" _
Sel ect pr oduct . Pr oduct Name, pr oduct . Uni t Pr i ce





Querying Data
Microsoft LINQ Using Visual Basic 2008 4-55
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

LINQ to SQL generated the following SQL statement based on this query:

SELECT [ t 0] . [ Pr oduct Name] , [ t 0] . [ Uni t Pr i ce]
FROM [ dbo] . [ Pr oduct s] AS [ t 0]
LEFT OUTER J OI N [ dbo] . [ Cat egor i es] AS [ t 1] ON
[ t 1] . [ Cat egor yI D] = [ t 0] . [ Cat egor yI D]
WHERE [ t 1] . [ Cat egor yName] = @p0

As you can see, when you query based on entity relationships, LINQ to SQL
generates a SQL statement that contains a Left Outer Join rather than an Inner
Join.
The results of an Inner Join query do not include parent items without related
children. If a category has no products, that category will not be in the querys
results. The results of a Left Outer Join query do include parent items without
related children. If a category has no products, that category will be in the
querys results.
In this example, the results of the two queries are the same because all
categories contain products.
The next query returns a list of customers in Spain who placed orders, along
with the number of orders they placed. Note that Spain has five customers, but
only four of them placed orders.
LINQ to SQL
4-56 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Di mspai nCust omer s = _
Fr omcust I n nwi ndDat aCont ext . Cust omer s _
Wher e cust . Count r y = " Spai n" _
J oi n or d I n nwi ndDat aCont ext . Or der s On _
cust . Cust omer I D Equal s or d. Cust omer I D _
Gr oup name = cust . CompanyName _
By cust . CompanyName _
I nt o Gr oup _
Sel ect CompanyName, Gr oup

Di spl ayHeader ( St r i ng. For mat ( _
" {0} cust omer s i n Spai n pl aced or der s" , _
spai nCust omer s. Count ) )
For Each cust Or d I n spai nCust omer s
Consol e. Wr i t eLi ne( " {0} pl aced {1} or der s" , _
cust Or d. CompanyName, cust Or d. Gr oup. Count )
Next

Figure 35 shows the results of running this query.
4 cust omer s i n Spai n pl aced or der s
==================================
Bl i do Comi das pr epar adas pl aced 3 or der s
Gal er a del gast r nomo pl aced 5 or der s
Godos Coci na T pi ca pl aced 10 or der s
Romer o y t omi l l o pl aced 5 or der s
Figure 35. This query returns a list of customers in Spain who placed orders and
the number of orders they placed.
The SQL Server Query Visualizer shows the following generated SQL
statement:
Querying Data
Microsoft LINQ Using Visual Basic 2008 4-57
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


SELECT [ t 0] . [ CompanyName]
FROM [ dbo] . [ Cust omer s] AS [ t 0]
I NNER J OI N [ dbo] . [ Or der s] AS [ t 1] ON [ t 0] . [ Cust omer I D] =
[ t 1] . [ Cust omer I D]
WHERE [ t 0] . [ Count r y] = ' Spai n'
GROUP BY [ t 0] . [ CompanyName]

The generated SQL statement uses an Inner Join and therefore returns a list of
the four customers who placed orders. The query groups orders by customer to
return the number of orders that each customer placed.
The final query returns a list of all customers, including any who did not place
orders, and the number of orders each customer placed.

Di mspai nCust omer s = _
Fr omcust I n nwi ndDat aCont ext . Cust omer s _
Wher e cust . Count r y = " Spai n" _
Gr oup J oi n or d I n nwi ndDat aCont ext . Or der s On _
cust . Cust omer I D Equal s or d. Cust omer I D _
I nt o cust Or der s = Gr oup _
Sel ect cust . CompanyName, cust Or der s

Di spl ayHeader ( St r i ng. For mat ( _
" Ther e ar e {0} cust omer s i n Spai n" , _
spai nCust omer s. Count ) )
For Each cust Or d I n spai nCust omer s
Consol e. Wr i t eLi ne( " {0} pl aced {1} or der s" , _
cust Or d. CompanyName, cust Or d. cust Or der s. Count )
Next

The query uses the Group Join clause to return all customers in Spain, even if
they did not place orders.
Figure 36 shows the results of running this query.
LINQ to SQL
4-58 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Ther e ar e 5 cust omer s i n Spai n
==============================
Bl i do Comi das pr epar adas pl aced 3 or der s
FI SSA Fabr i ca I nt er . Sal chi chas S. A. pl aced 0 or der s
Gal er a del gast r nomo pl aced 5 or der s
Godos Coci na T pi ca pl aced 10 or der s
Romer o y t omi l l o pl aced 5 or der s
Figure 36. This query returns a list of customers in Spain and the number of orders
they placed.
The SQL Server Query Visualizer shows the following generated SQL
statement:

SELECT [ t 0] . [ CompanyName] , [ t 1] . [ Or der I D] ,
[ t 1] . [ Cust omer I D] , [ t 1] . [ Empl oyeeI D] , [ t 1] . [ Or der Dat e] ,
[ t 1] . [ Requi r edDat e] , [ t 1] . [ Shi ppedDat e] , [ t 1] . [ Shi pVi a] ,
[ t 1] . [ Fr ei ght ] , [ t 1] . [ Shi pName] , [ t 1] . [ Shi pAddr ess] ,
[ t 1] . [ Shi pCi t y] , [ t 1] . [ Shi pRegi on] , [ t 1] . [ Shi pPost al Code] ,
[ t 1] . [ Shi pCount r y] , (
SELECT COUNT( *)
FROM [ dbo] . [ Or der s] AS [ t 2]
WHERE [ t 0] . [ Cust omer I D] = [ t 2] . [ Cust omer I D]
) AS [ val ue]
FROM [ dbo] . [ Cust omer s] AS [ t 0]
LEFT OUTER J OI N [ dbo] . [ Or der s] AS [ t 1] ON
[ t 0] . [ Cust omer I D] = [ t 1] . [ Cust omer I D]
WHERE [ t 0] . [ Count r y] = ' Spai n'
ORDER BY [ t 0] . [ Cust omer I D] , [ t 1] . [ Or der I D]

The SQL statement that LINQ to SQL generates for this query includes a Left
Outer Join to return all customers in Spain, even those who placed no orders.
TIP: Until you are well versed in LINQ to SQL, it is a good idea to investigate the
SQL statement that LINQ to SQL generates. This will help you learn how to
write better LINQ to SQL queries, as well as help ensure that you write the
queries you really want. In addition, this may help you identify ways to
improve the efficiency and performance of your queries.
Modifying Data
Microsoft LINQ Using Visual Basic 2008 4-59
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Modifying Data
The Q in LINQ stands for Query. In this chapter, you have already seen a
variety of examples of querying data in a SQL Server database. In this section,
you will see how to modify data. You can use LINQ to SQL to add, change,
and remove data.
In the previous section, you saw that by taking advantage of the object models
entity classes, you could easily retrieve information from more than one table.
You can also take advantage of the entity classes when you modify data. For
example:
To add a customer, you can create an instance of the Customer class
and then add the new Customer class to the Customers collection
(represented by the Customers property of the DataContext).
To update a customer, you can first create an instance of the
Customers class, typically by running a query, and then modify the
properties of the class that corresponds to the information you want to
change.
To delete a customer, you can remove from the Customers collection
the instance of the Customers class that represents that customer.
When you select Modify Data in the chapters sample application, you will see
four examples of modifying data in one table. The first example changes the
price of all products in the Beverages category. The second example adds a
new customer. The third example modifies that customer. The fourth example
deletes the customer.
The first example modifies existing data and lowers the price of each beverage
by ten percent.
Select Modify Data
LINQ to SQL
4-60 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Di mbever agesBef or e = _
Fr ompr oduct I n nwi ndDat aCont ext . Pr oduct s _
Wher e pr oduct . Cat egor y. Cat egor yName = " Bever ages"


For Each pr oduct I n bever agesBef or e
pr oduct . Uni t Pr i ce = pr oduct . Uni t Pr i ce * 0. 9D
Next


nwi ndDat aCont ext . Submi t Changes( )


Di mbever agesAf t er = _
Fr ompr oduct I n nwi ndDat aCont ext . Pr oduct s _
Wher e pr oduct . Cat egor y. Cat egor yName = " Bever ages"

The code first returns and displays the name and price of beverages. The field
beveragesBefore contains the collection of beverages. Specifically, it contains
a number of instances of the Product class. To modify prices, the code loops
through each instance in the collection and changes the UnitPrice property.
The changes occur in memory on the local computer, similarly to ADO.NET.
When the code calls the SubmitChanges method of the DataContext, LINQ to
SQL generates the appropriate Update statements and sends those to the SQL
Server database.
The code then reruns the original query to see the new prices.
Figure 37 shows the original prices, which the first query returns. It then shows
the new prices, which the second query returns.
Modifying Data
Microsoft LINQ Using Visual Basic 2008 4-61
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Cur r ent pr i ces
==============
Chai cur r ent l y cost s $18. 00
Chang cur r ent l y cost s $19. 00
Guar an Fant st i ca cur r ent l y cost s $4. 50
Sasquat ch Al e cur r ent l y cost s $14. 00
St eel eye St out cur r ent l y cost s $18. 00
Ct e de Bl aye cur r ent l y cost s $263. 50
Char t r euse ver t e cur r ent l y cost s $18. 00
I poh Cof f ee cur r ent l y cost s $46. 00
Laughi ng Lumber j ack Lager cur r ent l y cost s $14. 00
Out back Lager cur r ent l y cost s $15. 00
Rhnbr u Kl ost er bi er cur r ent l y cost s $7. 75
Lakkal i kr i cur r ent l y cost s $18. 00

New pr i ces
==========
Chai cur r ent l y cost s $16. 20
Chang cur r ent l y cost s $17. 10
Guar an Fant st i ca cur r ent l y cost s $4. 05
Sasquat ch Al e cur r ent l y cost s $12. 60
St eel eye St out cur r ent l y cost s $16. 20
Ct e de Bl aye cur r ent l y cost s $237. 15
Char t r euse ver t e cur r ent l y cost s $16. 20
I poh Cof f ee cur r ent l y cost s $41. 40
Laughi ng Lumber j ack Lager cur r ent l y cost s $12. 60
Out back Lager cur r ent l y cost s $13. 50
Rhnbr u Kl ost er bi er cur r ent l y cost s $6. 98
Lakkal i kr i cur r ent l y cost s $16. 20
Figure 37. Beverages now cost ten percent less than before.
The SQL Server Profiler shows that the following SQL statement executed for
the final product:
LINQ to SQL
4-62 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


exec sp_execut esql N' UPDATE [ dbo] . [ Pr oduct s]
SET [ Uni t Pr i ce] = @p9
WHERE ( [ Pr oduct I D] = @p0) AND ( [ Pr oduct Name] = @p1) AND
( [ Suppl i er I D] = @p2) AND ( [ Cat egor yI D] = @p3) AND
( [ Quant i t yPer Uni t ] = @p4) AND ( [ Uni t Pr i ce] = @p5) AND
( [ Uni t sI nSt ock] = @p6) AND ( [ Uni t sOnOr der ] = @p7) AND
( [ Reor der Level ] = @p8) AND ( NOT ( [ Di scont i nued] =
1) ) ' , N' @p0 i nt , @p1 nvar char ( 12) , @p2 i nt , @p3 i nt , @p4
nvar char ( 6) , @p5 money, @p6 smal l i nt , @p7 smal l i nt , @p8
smal l i nt , @p9
money' , @p0=76, @p1=N' Lakkal i kr i ' , @p2=23, @p3=1, @p4=N' 500
ml ' , @p5=$3. 0017, @p6=57, @p7=0, @p8=20, @p9=$2. 7015

When you call the SubmitChanges method of the DataContext, LINQ to SQL
identifies which entities have new items and which entities have existing items
that changed. It then generates the appropriate Insert, Update, and Delete
statements.
NOTE Later in the chapter, you will see how to configure the
DataContext to use stored procedures for modifying data rather
than Insert, Update, and Delete statements. The sample application
for this chapter is configured that way, so SQL Server Profiler will
show that the UpdateCustomer stored procedure executed, not the
Update statement listed here. If you configure the DataContext to
use generated SQL statements, which is the default, you will see
this Update statement execute.
Before sending the SQL statements, the DataContext starts a transaction. All
pending updates are part of this transaction. If any of them fails, the entire set
of updates will fail. At that point, you could correct the issue and resubmit the
changes.
The second data modification example adds a new customer, modifies that
customer, and then deletes the customer.
Modifying Data
Microsoft LINQ Using Visual Basic 2008 4-63
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Di mnewCust omer As New Cust omer Wi t h _
{. Cust omer I D = " BI GGE" , _
. CompanyName = " Bi gge I ndust r i es" , _
. Cont act Name = " Rober t Gr een" , _
. Cont act Ti t l e = " Pr esi dent " , _
. Addr ess = " 12345 NE 54321 St " , _
. Ci t y = " Redmond" , _
. Regi on = " WA" , _
. Post al Code = " 98052" , _
. Count r y = " USA" , _
. Phone = " 425- 555- 5555" , _
. Fax = " 425- 555- 5556" }

nwi ndDat aCont ext . Cust omer s. I nser t OnSubmi t ( newCust omer )
nwi ndDat aCont ext . Submi t Changes( )

The code first creates a new instance of the Customer class, supplying the
information for the customer that the code will add. The code then calls the
InsertOnSubmit method of the DataContext to add the new Customer instance
to the collection of Customers. In other words, this adds the new customer to
the local in-memory version of the customers in the database. The new
customer is not added to the database until the code calls SubmitChanges. At
that point, LINQ to SQL generates the appropriate Insert statement and sends it
to the database.
The SQL Server Profiler shows that the following Insert statement executed:
LINQ to SQL
4-64 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


exec sp_execut esql N' I NSERT I NTO
[ dbo] . [ Cust omer s] ( [ Cust omer I D] , [ CompanyName] ,
[ Cont act Name] , [ Cont act Ti t l e] , [ Addr ess] , [ Ci t y] ,
[ Regi on] , [ Post al Code] , [ Count r y] , [ Phone] , [ Fax] )
VALUES ( @p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9,
@p10) ' , N' @p0 nchar ( 5) , @p1 nvar char ( 16) , @p2
nvar char ( 12) , @p3 nvar char ( 9) , @p4 nvar char ( 17) , @p5
nvar char ( 7) , @p6 nvar char ( 2) , @p7 nvar char ( 5) , @p8
nvar char ( 3) , @p9 nvar char ( 12) , @p10
nvar char ( 12) ' , @p0=N' BI GGE' , @p1=N' Bi gge
I ndust r i es' , @p2=N' Rober t
Gr een' , @p3=N' Pr esi dent ' , @p4=N' 12345 NE 54321
St ' , @p5=N' Redmond' , @p6=N' WA' , @p7=N' 98052' , @p8=N' USA' , @p9=N
' 425- 555- 5555' , @p10=N' 425- 555- 5556'

Figure 38 shows the results of then querying the database for the list of
customers in Washington. The new customer appears in the list.
Cust omer s i n Washi ngt on
=======================
Bi gge I ndust r i es i n Redmond, WA
Lazy K Kount r y St or e i n Wal l a Wal l a, WA
Tr ai l ' s Head Gour met Pr ovi si oner s i n Ki r kl and, WA
Whi t e Cl over Mar ket s i n Seat t l e, WA
Figure 38. Bigge Industries is now a customer in Washington.
The next example modifies the new customer. The code first executes a query
to return the customer. It next changes the contact name and title and calls
SubmitChanges to send the changes to the database. The code then executes a
query to return the updated customer.
Modifying Data
Microsoft LINQ Using Visual Basic 2008 4-65
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Di mcust omer Bef or e = _
nwi ndDat aCont ext . Cust omer s. Si ngl e( _
Funct i on( c) c. Cust omer I D = " BI GGE" )


cust omer Bef or e. Cont act Name = " Ken Get z"
cust omer Bef or e. Cont act Ti t l e = " Owner "

nwi ndDat aCont ext . Submi t Changes( )

Di mcust omer Af t er = _
nwi ndDat aCont ext . Cust omer s. Si ngl e( _
Funct i on( c) c. Cust omer I D = " BI GGE" )

Figure 39 shows the current contact and title and the updated contact and title.
Cont act i nf or mat i on f or Bi gge I ndust r i es
========================================
Cur r ent cont act i s Rober t Gr een, Pr esi dent

Cur r ent cont act i s Ken Get z, Owner
Figure 39. The contact and title for this customer have changed.
The SQL Server Profiler shows that the following Update statement executed:
LINQ to SQL
4-66 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


exec sp_execut esql N' UPDATE [ dbo] . [ Cust omer s]
SET [ Cont act Name] = @p11, [ Cont act Ti t l e] = @p12
WHERE ( [ Cust omer I D] = @p0) AND ( [ CompanyName] = @p1) AND
( [ Cont act Name] = @p2) AND ( [ Cont act Ti t l e] = @p3) AND
( [ Addr ess] = @p4) AND ( [ Ci t y] = @p5) AND ( [ Regi on] = @p6)
AND ( [ Post al Code] = @p7) AND ( [ Count r y] = @p8) AND
( [ Phone] = @p9) AND ( [ Fax] = @p10) ' , N' @p0 nchar ( 5) , @p1
nvar char ( 16) , @p2 nvar char ( 12) , @p3 nvar char ( 9) , @p4
nvar char ( 17) , @p5 nvar char ( 7) , @p6 nvar char ( 2) , @p7
nvar char ( 5) , @p8 nvar char ( 3) , @p9 nvar char ( 12) , @p10
nvar char ( 12) , @p11 nvar char ( 8) , @p12
nvar char ( 5) ' , @p0=N' BI GGE' , @p1=N' Bi gge
I ndust r i es' , @p2=N' Rober t
Gr een' , @p3=N' Pr esi dent ' , @p4=N' 12345 NE 54321
St ' , @p5=N' Redmond' , @p6=N' WA' , @p7=N' 98052' , @p8=N' USA' , @p9=N
' 425- 555- 5555' , @p10=N' 425- 555- 5556' , @p11=N' Ken
Get z' , @p12=N' Owner '

The final example deletes the new customer by calling the DeleteOnSubmit
method of the DataContext and passing customerBIGGE, which represents the
updated customer. The code then calls Submit Changes and reruns the query to
list customers in Washington.

Di mcust omer BI GGE = _
nwi ndDat aCont ext . Cust omer s. Si ngl e( _
Funct i on( c) c. Cust omer I D = " BI GGE" )

nwi ndDat aCont ext . Cust omer s. Del et eOnSubmi t ( cust omer BI GGE)
nwi ndDat aCont ext . Submi t Changes( )

Figure 40 displays the current customers in Washington after deleting the new
customer.
Modifying Data
Microsoft LINQ Using Visual Basic 2008 4-67
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Cust omer s i n Washi ngt on
=======================
Lazy K Kount r y St or e i n Wal l a Wal l a, WA
Tr ai l ' s Head Gour met Pr ovi si oner s i n Ki r kl and, WA
Whi t e Cl over Mar ket s i n Seat t l e, WA
Figure 40. The customer added previously was removed.
The SQL Server Profiler shows that the following Delete statement executed:

exec sp_execut esql N' DELETE FROM [ dbo] . [ Cust omer s] WHERE
( [ Cust omer I D] = @p0) AND ( [ CompanyName] = @p1) AND
( [ Cont act Name] = @p2) AND ( [ Cont act Ti t l e] = @p3) AND
( [ Addr ess] = @p4) AND ( [ Ci t y] = @p5) AND ( [ Regi on] = @p6)
AND ( [ Post al Code] = @p7) AND ( [ Count r y] = @p8) AND
( [ Phone] = @p9) AND ( [ Fax] = @p10) ' , N' @p0 nchar ( 5) , @p1
nvar char ( 16) , @p2 nvar char ( 8) , @p3 nvar char ( 5) , @p4
nvar char ( 17) , @p5 nvar char ( 7) , @p6 nvar char ( 2) , @p7
nvar char ( 5) , @p8 nvar char ( 3) , @p9 nvar char ( 12) , @p10
nvar char ( 12) ' , @p0=N' BI GGE' , @p1=N' Bi gge
I ndust r i es' , @p2=N' Ken Get z' , @p3=N' Owner ' , @p4=N' 12345 NE
54321
St ' , @p5=N' Redmond' , @p6=N' WA' , @p7=N' 98052' , @p8=N' USA' , @p9=N
' 425- 555- 5555' , @p10=N' 425- 555- 5556'

When you select Modify Related Data in the chapters sample application, you
will see an example of modifying data in related tables. The example adds an
order for a customer. The order contains three products, so one record is added
to the Orders table and three related records are added to the Order Details
table.
The code that runs executes a query to retrieve information for a particular
customer.

Di mcust omer ALFKI = _
nwi ndDat aCont ext . Cust omer s. Si ngl e( _
Funct i on( c) c. Cust omer I D = " ALFKI " )

Select Modify
Related Data
LINQ to SQL
4-68 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

The field customerALFKI is an instance of the Customer class with its
properties set to the appropriate information for this customer.
customerALFKI.Orders is an EntitySet that represents a collection of orders,
specifically a collection of instances of the Order class.
The code adds a new order by first creating a new instance of the Order class
and then adding it to the customers orders collection by calling the Add
method of the EntitySet class.

Di mnewOr der = New Or der Wi t h _
{. Cust omer I D = " ALFKI " , _
. Or der Dat e = Dat eTi me. Today, _
. Requi r edDat e = Dat eTi me. Today. AddDays( 7) , _
. Empl oyeeI D = 4}

cust omer ALFKI . Or der s. Add( newOr der )

newOrder is an instance of the Order class so it has an Order_Details property,
which represents a collection of details for this order. The code creates three
new instances of the Order_Detail class and adds them to the collection of
details by calling the Add method. To add the new order to the database, the
code calls the SubmitChanges method.
Modifying Data
Microsoft LINQ Using Visual Basic 2008 4-69
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Di mor der Det ai l = New Or der _Det ai l Wi t h _
{. Pr oduct I D = 7, _
. Uni t Pr i ce = 25, _
. Quant i t y = 10, _
. Di scount = 0}
newOr der . Or der _Det ai l s. Add( or der Det ai l )

or der Det ai l = New Or der _Det ai l Wi t h _
{. Pr oduct I D = 8, _
. Uni t Pr i ce = 10, _
. Quant i t y = 15, _
. Di scount = 0}
newOr der . Or der _Det ai l s. Add( or der Det ai l )

or der Det ai l = New Or der _Det ai l Wi t h _
{. Pr oduct I D = 12, _
. Uni t Pr i ce = 20, _
. Quant i t y = 25, _
. Di scount = 0}
newOr der . Or der _Det ai l s. Add( or der Det ai l )

nwi ndDat aCont ext . Submi t Changes( )

Figure 41 shows the orders for this customer after adding the new order and
the details for the new order.
LINQ to SQL
4-70 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Or der 10643 pl aced 8/ 25/ 1997 and r equi r ed 9/ 22/ 1997
Or der 10692 pl aced 10/ 3/ 1997 and r equi r ed 10/ 31/ 1997
Or der 10702 pl aced 10/ 13/ 1997 and r equi r ed 11/ 24/ 1997
Or der 10835 pl aced 1/ 15/ 1998 and r equi r ed 2/ 12/ 1998
Or der 10952 pl aced 3/ 16/ 1998 and r equi r ed 4/ 27/ 1998
Or der 11011 pl aced 4/ 9/ 1998 and r equi r ed 5/ 7/ 1998
Or der 11078 pl aced 9/ 2/ 2008 and r equi r ed 9/ 9/ 2008

Det ai l s f or or der 11078
=======================
10 uni t s of Uncl e Bob' s Or gani c Dr i ed Pear s at $25. 00
15 uni t s of Nor t hwoods Cr anber r y Sauce at $10. 00
25 uni t s of Queso Manchego La Past or a at $20. 00
Figure 41. A new order was added for this customer.
The SQL Server Profiler shows that the following Insert statement executed to
add the order:

exec sp_execut esql N' I NSERT I NTO
[ dbo] . [ Or der s] ( [ Cust omer I D] , [ Empl oyeeI D] , [ Or der Dat e] ,
[ Requi r edDat e] , [ Shi ppedDat e] , [ Shi pVi a] , [ Fr ei ght ] ,
[ Shi pName] , [ Shi pAddr ess] , [ Shi pCi t y] , [ Shi pRegi on] ,
[ Shi pPost al Code] , [ Shi pCount r y] )
VALUES ( @p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9,
@p10, @p11, @p12)

SELECT CONVERT( I nt , SCOPE_I DENTI TY( ) ) AS [ val ue] ' , N' @p0
nchar ( 5) , @p1 i nt , @p2 dat et i me, @p3 dat et i me, @p4
dat et i me, @p5 i nt , @p6 money, @p7 nvar char ( 4000) , @p8
nvar char ( 4000) , @p9 nvar char ( 4000) , @p10 nvar char ( 4000) , @p11
nvar char ( 4000) , @p12
nvar char ( 4000) ' , @p0=N' ALFKI ' , @p1=4, @p2=' 2008- 09- 02
00: 00: 00: 000' , @p3=' 2008- 09- 09
00: 00: 00: 000' , @p4=NULL, @p5=NULL, @p6=NULL, @p7=NULL, @p8=NULL
, @p9=NULL, @p10=NULL, @p11=NULL, @p12=NULL


Modifying Data
Microsoft LINQ Using Visual Basic 2008 4-71
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

The SQL Server Profiler shows that the following Insert statement executed to
add the first order detail:

exec sp_execut esql N' I NSERT I NTO [ dbo] . [ Or der
Det ai l s] ( [ Or der I D] , [ Pr oduct I D] , [ Uni t Pr i ce] , [ Quant i t y] ,
[ Di scount ] )
VALUES ( @p0, @p1, @p2, @p3, @p4) ' , N' @p0 i nt , @p1 i nt , @p2
money, @p3 smal l i nt , @p4
r eal ' , @p0=11078, @p1=7, @p2=$25. 0000, @p3=10, @p4=0


LINQ to SQL
4-72 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Using Stored Procedures
Depending on the application, and on the wishes of the database administrator,
you may use stored procedures rather than SQL statements to query and
modify data. Earlier in the chapter, you dragged tables from the Server
Explorer to the Object Relational Designer to create entity classes.
You can also drag stored procedures from the Server Explorer to the Object
Relational Designer to create methods of the DataContext. To call the stored
procedures, you can then call those methods. The method accepts any
parameters that the stored procedure accepts.
Try It Out!
In this exercise, you will use the Object Relational Designer to create
DataContext methods based on stored procedures in the SQL Server
Northwind database.
1. In Visual Studio 2008, select File|Open|Project/Solution. In the Open
Project dialog box, navigate to the location where you saved the
ObjectModelDemo solution.
2. Select ObjectModelDemo.sln. Click Open.
3. Select View|Server Explorer to display the Server Explorer window. You
should see the connection to the Northwind database that you created
earlier in the chapter.
4. In the Server Explorer, expand the node for the Northwind database.
5. In the Northwind node, expand the node for Stored Procedures.
6. Right-click Stored Procedures and select Add New Stored Procedure.
7. Replace the code with the following code:

CREATE PROCEDURE dbo. Cust omer sI nRegi on
(
@Regi on nvar char ( 15)
)
AS
SELECT Cust omer I D, CompanyName, Cont act Name,
Cont act Ti t l e, Addr ess, Ci t y, Regi on, Post al Code,
Count r y, Phone, Fax FROM Cust omer s WHERE ( Regi on =
@Regi on)
Using Stored Procedures
Microsoft LINQ Using Visual Basic 2008 4-73
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

8. Select File|Save to save the stored procedure to the database.
9. Right-click Stored Procedures and select Add New Stored Procedure.
10. Replace the code with the following code:

CREATE PROCEDURE dbo. AddCust omer
(
@Cust omer I D nchar ( 5) ,
@CompanyName nvar char ( 40) ,
@Cont act Name nvar char ( 30) ,
@Cont act Ti t l e nvar char ( 30) ,
@Addr ess nvar char ( 60) ,
@Ci t y nvar char ( 15) ,
@Regi on nvar char ( 15) ,
@Post al Code nvar char ( 10) ,
@Count r y nvar char ( 15) ,
@Phone nvar char ( 24) ,
@Fax nvar char ( 24)
)
AS
SET NOCOUNT OFF;
I NSERT I NTO [ dbo] . [ Cust omer s] ( [ Cust omer I D] ,
[ CompanyName] , [ Cont act Name] , [ Cont act Ti t l e] ,
[ Addr ess] , [ Ci t y] , [ Regi on] , [ Post al Code] , [ Count r y] ,
[ Phone] , [ Fax] )
VALUES ( @Cust omer I D, @CompanyName, @Cont act Name,
@Cont act Ti t l e, @Addr ess, @Ci t y, @Regi on, @Post al Code,
@Count r y, @Phone, @Fax) ;

11. Select File|Save to save the stored procedure to the database.
12. Right-click Stored Procedures and select Add New Stored Procedure.
13. Replace the code with the following code:
LINQ to SQL
4-74 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


CREATE PROCEDURE dbo. Updat eCust omer
(
@Cust omer I D nchar ( 5) ,
@CompanyName nvar char ( 40) ,
@Cont act Name nvar char ( 30) ,
@Cont act Ti t l e nvar char ( 30) ,
@Addr ess nvar char ( 60) ,
@Ci t y nvar char ( 15) ,
@Regi on nvar char ( 15) ,
@Post al Code nvar char ( 10) ,
@Count r y nvar char ( 15) ,
@Phone nvar char ( 24) ,
@Fax nvar char ( 24) ,
@Or i gi nal _Cust omer I D nchar ( 5)
)
AS
SET NOCOUNT OFF;
UPDATE [ dbo] . [ Cust omer s] SET [ Cust omer I D] = @Cust omer I D,
[ CompanyName] = @CompanyName, [ Cont act Name] =
@Cont act Name, [ Cont act Ti t l e] = @Cont act Ti t l e,
[ Addr ess] = @Addr ess, [ Ci t y] = @Ci t y, [ Regi on] =
@Regi on, [ Post al Code] = @Post al Code, [ Count r y] =
@Count r y, [ Phone] = @Phone, [ Fax] = @Fax WHERE
[ Cust omer I D] = @Or i gi nal _Cust omer I D;

14. Select File|Save to save the stored procedure to the database.
15. Right-click Stored Procedures and select Add New Stored Procedure.
16. Replace the code with the following code:
Using Stored Procedures
Microsoft LINQ Using Visual Basic 2008 4-75
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


CREATE PROCEDURE dbo. Del et eCust omer
(
@Or i gi nal _Cust omer I D nchar ( 5)
)
AS
SET NOCOUNT OFF;
DELETE FROM [ dbo] . [ Cust omer s] WHERE ( ( [ Cust omer I D] =
@Or i gi nal _Cust omer I D) )

17. Select File|Save to save the stored procedure to the database.
18. Close the stored procedure code windows.
19. In the Solution Explorer, double-click Northwind.dbml. This opens the
Object Relational Designer.
20. Drag the CustomersInRegion, AddCustomer, UpdateCustomer, and
DeleteCustomer stored procedures from the Server Explorer to the right
pane of the Object Relational Designer. This adds these stored procedures
as methods of the DataContext class, as shown in Figure 42.

Figure 42. The stored procedures are now methods of the DataContext.


LINQ to SQL
4-76 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

21. Select File|Save All.
22. If necessary, in the Solution Explorer, click Show All Files.
23. Open the Northwind.designer.vb file.
NOTE This project will not build because it does not have a main
procedure. That is okay, because here you are learning how to use
the Object Relational Designer.
Visual Studio generates the following code to create methods for each stored
procedure.

<Funct i onAt t r i but e( Name: =" dbo. Del et eCust omer " ) > _
Publ i c Funct i on Del et eCust omer ( _
<Par amet er ( Name: =" Or i gi nal _Cust omer I D" ,
DbType: =" NChar ( 5) " ) > ByVal or i gi nal _Cust omer I D As
St r i ng) As I nt eger

Di mr esul t As I Execut eResul t = _
Me. Execut eMet hodCal l ( Me, _
CType( Met hodI nf o. Get Cur r ent Met hod, Met hodI nf o) , _
or i gi nal _Cust omer I D)
Ret ur n CType( r esul t . Ret ur nVal ue, I nt eger )
End Funct i on

<Funct i onAt t r i but e( Name: =" dbo. AddCust omer " ) > _
Publ i c Funct i on AddCust omer ( _
<Par amet er ( Name: =" Cust omer I D" , DbType: =" NChar ( 5) " ) > _
ByVal cust omer I D As St r i ng, _
<Par amet er ( Name: =" CompanyName" , _
DbType: =" NVar Char ( 40) " ) > ByVal companyName As St r i ng, _
<Par amet er ( Name: =" Cont act Name" , _
DbType: =" NVar Char ( 30) " ) > ByVal cont act Name As St r i ng, _
<Par amet er ( Name: =" Cont act Ti t l e" , _
DbType: =" NVar Char ( 30) " ) > _
ByVal cont act Ti t l e As St r i ng, _
<Par amet er ( Name: =" Addr ess" , DbType: =" NVar Char ( 60) " ) > _
ByVal addr ess As St r i ng, <Par amet er ( Name: =" Ci t y" , _
DbType: =" NVar Char ( 15) " ) > ByVal ci t y As St r i ng, _
Using Stored Procedures
Microsoft LINQ Using Visual Basic 2008 4-77
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

<Par amet er ( Name: =" Regi on" , DbType: =" NVar Char ( 15) " ) > _
ByVal r egi on As St r i ng, <Par amet er ( Name: =" Post al Code" , _
DbType: =" NVar Char ( 10) " ) > ByVal post al Code As St r i ng, _
<Par amet er ( Name: =" Count r y" , DbType: =" NVar Char ( 15) " ) > _
ByVal count r y As St r i ng, <Par amet er ( Name: =" Phone" , _
DbType: =" NVar Char ( 24) " ) > ByVal phone As St r i ng, _
<Par amet er ( Name: =" Fax" , DbType: =" NVar Char ( 24) " ) > _
ByVal f ax As St r i ng) As I nt eger

Di mr esul t As I Execut eResul t = _
Me. Execut eMet hodCal l ( Me, _
CType( Met hodI nf o. Get Cur r ent Met hod, Met hodI nf o) , _
cust omer I D, companyName, cont act Name, cont act Ti t l e, _
addr ess, ci t y, r egi on, post al Code, count r y, phone, _
f ax)
Ret ur n CType( r esul t . Ret ur nVal ue, I nt eger )
End Funct i on

<Funct i onAt t r i but e( Name: =" dbo. Updat eCust omer " ) > _
Publ i c Funct i on Updat eCust omer ( _
<Par amet er ( Name: =" Cust omer I D" , DbType: =" NChar ( 5) " ) > _
ByVal cust omer I D As St r i ng, _
<Par amet er ( Name: =" CompanyName" , _
DbType: =" NVar Char ( 40) " ) > _
ByVal companyName As St r i ng, _
<Par amet er ( Name: =" Cont act Name" , _
DbType: =" NVar Char ( 30) " ) > ByVal cont act Name As St r i ng, _
<Par amet er ( Name: =" Cont act Ti t l e" , _
DbType: =" NVar Char ( 30) " ) > ByVal cont act Ti t l e As St r i ng, _
<Par amet er ( Name: =" Addr ess" , DbType: =" NVar Char ( 60) " ) > _
ByVal addr ess As St r i ng, <Par amet er ( Name: =" Ci t y" , _
DbType: =" NVar Char ( 15) " ) > ByVal ci t y As St r i ng, _
<Par amet er ( Name: =" Regi on" , DbType: =" NVar Char ( 15) " ) > _
ByVal r egi on As St r i ng, <Par amet er ( Name: =" Post al Code" , _
DbType: =" NVar Char ( 10) " ) > ByVal post al Code As St r i ng, _
<Par amet er ( Name: =" Count r y" , DbType: =" NVar Char ( 15) " ) > _
ByVal count r y As St r i ng, <Par amet er ( Name: =" Phone" , _
DbType: =" NVar Char ( 24) " ) > ByVal phone As St r i ng, _
LINQ to SQL
4-78 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

<Par amet er ( Name: =" Fax" , DbType: =" NVar Char ( 24) " ) > _
ByVal f ax As St r i ng, _
<Par amet er ( Name: =" Or i gi nal _Cust omer I D" , _
DbType: =" NChar ( 5) " ) > ByVal or i gi nal _Cust omer I D As _
St r i ng) As I nt eger

Di mr esul t As I Execut eResul t = _
Me. Execut eMet hodCal l ( Me, _
CType( Met hodI nf o. Get Cur r ent Met hod, Met hodI nf o) , _
cust omer I D, companyName, cont act Name, cont act Ti t l e, _
addr ess, ci t y, r egi on, post al Code, count r y, phone, _
f ax, or i gi nal _Cust omer I D)
Ret ur n CType( r esul t . Ret ur nVal ue, I nt eger )
End Funct i on

<Funct i onAt t r i but e( Name: =" dbo. Cust omer sI nRegi on" ) > _
Publ i c Funct i on
Cust omer sI nRegi on( <Par amet er ( Name: =" Regi on" ,
DbType: =" NVar Char ( 15) " ) > ByVal r egi on As St r i ng) As
I Si ngl eResul t ( Of Cust omer sI nRegi onResul t )
Di mr esul t As I Execut eResul t = Me. Execut eMet hodCal l ( Me,
CType( Met hodI nf o. Get Cur r ent Met hod, Met hodI nf o) , r egi on)
Ret ur n CType( r esul t . Ret ur nVal ue, I Si ngl eResul t ( Of
Cust omer sI nRegi onResul t ) )
End Funct i on

When you select Stored Procedures 1 in the chapters sample application, you
will see the first of two examples of that call stored procedures to modify data
in related tables. The example adds an order for a customer. The order contains
three products, so one record is added to the Orders table and three related
records are added to the Order Details table.
The code first calls the AddCustomer method of the DataContext to add a new
customer. The code passes the information for the customer to the method. The
code then calls the CustomersInRegion method to display customers in Ohio.
Select Stored
Procedures 1
Using Stored Procedures
Microsoft LINQ Using Visual Basic 2008 4-79
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


nwi ndDat aCont ext . Log = Consol e. Out

nwi ndDat aCont ext . AddCust omer ( _
" AAAAA" , " AAAAA Consul t i ng" , " Don Ki el y" , _
" Sal es Manager " , " 1234 Mai n St " , " Tol edo" , " OH" , _
" 43555" , " USA" , " 419- 555- 5555" , " 419- 555- 5556" )

nwi ndDat aCont ext . Log = Not hi ng

Di mohi oCust omer s = _
nwi ndDat aCont ext . Cust omer sI nRegi on( " OH" )

Di spl ayOhi oCust omer s( ohi oCust omer s)

When the code calls the AddCustomer method, LINQ to SQL immediately
creates a SQL statement to call the stored procedure and sends it to the
database. There is no need to call SubmitChanges.
The DisplayOhioCustomers method displays customers in Ohio as follows:

Pr i vat e Sub Di spl ayOhi oCust omer s( ByVal quer y As _
I Si ngl eResul t ( Of LI NQToSQLDemo. Cust omer sI nRegi onResul t ) )

Di spl ayHeader ( " Cust omer s i n Ohi o" )
For Each cust I n quer y
Consol e. Wr i t eLi ne( " {0}: , {1}, {2} at {3} i n {4}" , _
cust . CompanyName, cust . Cont act Name, _
cust . Cont act Ti t l e, cust . Addr ess, cust . Ci t y)
Next
End Sub

Figure 43 shows the results of running this example.
LINQ to SQL
4-80 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

EXEC @RETURN_VALUE = [ dbo] . [ AddCust omer ] @Cust omer I D = @p0,
@CompanyName = @p1,
@Cont act Name = @p2, @Cont act Ti t l e = @p3, @Addr ess = @p4,
@Ci t y = @p5, @Regi on =
@p6, @Post al Code = @p7, @Count r y = @p8, @Phone = @p9, @Fax =
@p10
- - @p0: I nput NChar ( Si ze = 5; Pr ec = 0; Scal e = 0) [ AAAAA]
- - @p1: I nput NVar Char ( Si ze = 16; Pr ec = 0; Scal e = 0)
[ AAAAA Consul t i ng]
- - @p2: I nput NVar Char ( Si ze = 9; Pr ec = 0; Scal e = 0) [ Don
Ki el y]
- - @p3: I nput NVar Char ( Si ze = 13; Pr ec = 0; Scal e = 0)
[ Sal es Manager ]
- - @p4: I nput NVar Char ( Si ze = 12; Pr ec = 0; Scal e = 0)
[ 1234 Mai n St ]
- - @p5: I nput NVar Char ( Si ze = 6; Pr ec = 0; Scal e = 0)
[ Tol edo]
- - @p6: I nput NVar Char ( Si ze = 2; Pr ec = 0; Scal e = 0) [ OH]
- - @p7: I nput NVar Char ( Si ze = 5; Pr ec = 0; Scal e = 0)
[ 43555]
- - @p8: I nput NVar Char ( Si ze = 3; Pr ec = 0; Scal e = 0) [ USA]
- - @p9: I nput NVar Char ( Si ze = 12; Pr ec = 0; Scal e = 0)
[ 419- 555- 5555]
- - @p10: I nput NVar Char ( Si ze = 12; Pr ec = 0; Scal e = 0)
[ 419- 555- 5556]
- - @RETURN_VALUE: Out put I nt ( Si ze = 0; Pr ec = 0; Scal e = 0)
[ Nul l ]
- - Cont ext : Sql Pr ovi der ( Sql 2005) Model : At t r i but edMet aModel
Bui l d: 3. 5. 30729. 1


Cust omer s i n Ohi o
=================
AAAAA Consul t i ng: , Don Ki el y, Sal es Manager at 1234 Mai n St
i n Tol edo
Figure 43. Customer AAAAA Consulting was added.
The code next calls the UpdateCustomer method to make a change to the
customer. The stored procedure takes as arguments all of the columns in the
Customers table. The code changes the company name and the contact title.
Again, there is no need to call SubmitChanges.
Using Stored Procedures
Microsoft LINQ Using Visual Basic 2008 4-81
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

After calling the UpdateCustomer method, the code refreshes the DataContext.
This is necessary so that the subsequent call to CustomersInRegion will query
the database. Otherwise, the DataContext will issue the query against cached
data and the changes will not display.

nwi ndDat aCont ext . Updat eCust omer ( _
" AAAAA" , " Pent upl e A Consul t i ng" , " Don Ki el y" , _
" Vi ce Pr esi dent " , " 100 J acobs Bl vd" , " Cl evel and" , _
" OH" , " 44555" , " USA" , " 216- 555- 5555" , " 216- 555- 5556" , _
" AAAAA" )

Di mohi oCust omer s = _
nwi ndDat aCont ext . Cust omer sI nRegi on( " OH" )

Figure 44 shows the results of running this code.
Cust omer s i n Ohi o
=================
Pent upl e A Consul t i ng: , Don Ki el y, Vi ce Pr esi dent at 100
J acobs Bl vd i n Cl evel and
Figure 44. The customers information changed.
The SQL Server Profiler shows that the UpdateCustomer stored procedure
executed:
LINQ to SQL
4-82 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


decl ar e @p15 i nt
set @p15=0
exec sp_execut esql N' EXEC @RETURN_VALUE =
[ dbo] . [ Updat eCust omer ] @Cust omer I D = @p0, @CompanyName =
@p1, @Cont act Name = @p2, @Cont act Ti t l e = @p3, @Addr ess =
@p4, @Ci t y = @p5, @Regi on = @p6, @Post al Code = @p7,
@Count r y = @p8, @Phone = @p9, @Fax = @p10,
@Or i gi nal _Cust omer I D = @p11' , N' @p0 nchar ( 5) , @p1
nvar char ( 21) , @p2 nvar char ( 9) , @p3 nvar char ( 14) , @p4
nvar char ( 15) , @p5 nvar char ( 9) , @p6 nvar char ( 2) , @p7
nvar char ( 5) , @p8 nvar char ( 3) , @p9 nvar char ( 12) , @p10
nvar char ( 12) , @p11 nchar ( 5) , @RETURN_VALUE i nt
out put ' , @p0=N' AAAAA' , @p1=N' Pent upl e A
Consul t i ng' , @p2=N' Don Ki el y' , @p3=N' Vi ce
Pr esi dent ' , @p4=N' 100 J acobs
Bl vd' , @p5=N' Cl evel and' , @p6=N' OH' , @p7=N' 44555' , @p8=N' USA' , @
p9=N' 216- 555- 5555' , @p10=N' 216- 555-
5556' , @p11=N' AAAAA' , @RETURN_VALUE=@p15 out put
sel ect @p15

Finally, the code calls the DeleteCustomer method to remove the customer.
This method takes the customer ID as an argument.

nwi ndDat aCont ext . Del et eCust omer ( " AAAAA" )

Di mohi oCust omer s = _
nwi ndDat aCont ext . Cust omer sI nRegi on( " OH" )

Di spl ayOhi oCust omer s( ohi oCust omer s)

Figure 45 shows the results of calling this code.
Cust omer s i n Ohi o
=================
Figure 45. The customer was deleted.
Using Stored Procedures
Microsoft LINQ Using Visual Basic 2008 4-83
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

The SQL Server Profiler shows that the DeleteCustomer stored procedure
executed:

decl ar e @p4 i nt
set @p4=0
exec sp_execut esql N' EXEC @RETURN_VALUE =
[ dbo] . [ Del et eCust omer ] @Or i gi nal _Cust omer I D = @p0' , N' @p0
nchar ( 5) , @RETURN_VALUE i nt
out put ' , @p0=N' AAAAA' , @RETURN_VALUE=@p4 out put
sel ect @p4

Configuring the Update Behavior of
Entity Classes
You just saw that you can call stored procedures directly in code by calling a
method of the DataContext. You can use stored procedures in a second way:
You can configure the DataContext to use these stored procedures when you
call SubmitChanges. You will next configure the DataContext to automatically
use the AddCustomer stored procedure to add customers, to use the
UpdateCustomer stored procedure to modify existing customers, and to use the
DeleteCustomer stored procedure to remove a customer.
Try It Out!
In this section, you will use the Object Relational Designer to associate stored
procedures with the Insert, Update, and Delete methods of the Customer class.
1. In Visual Studio 2008, select File|Open|Project/Solution. In the Open
Project dialog box, navigate to the location where you saved the
ObjectModelDemo solution.
2. Select ObjectModelDemo.sln. Click Open.
3. In the Solution Explorer, double-click Northwind.dbml. This opens the
Object Relational Designer.
4. Right-click Customer and select Configure Behavior. This displays the
Configure Behavior dialog box, as shown in Figure 46.
LINQ to SQL
4-84 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Figure 46. Use this dialog box to instruct the class to use SQL statements or stored
procedures to modify data.
Currently, the Customer class uses SQL statements that LINQ to SQL
generates to insert, update, and delete customers. You will now change that
behavior.
5. Select Customize and select AddCustomer from the drop-down list, as
shown in Figure 47.
Using Stored Procedures
Microsoft LINQ Using Visual Basic 2008 4-85
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Figure 47. Configure the DataContext to use the AddCustomer stored procedure
when you add customers.
6. Click Apply.
7. Select Update from the Behavior drop-down list.
8. Select Customize and select UpdateCustomer from the drop-down list.
9. Locate the original_CustomerID method argument. Select CustomerID
(Original) from the Class Properties drop-down list, as shown in
Figure 48.
LINQ to SQL
4-86 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Figure 48. Identify the property that identifies the customer.
The CustomerID column is the primary key in the Customers table. Unlike
most primary keys, you can modify CustomerID even after you add a
customer. The UpdateCustomer stored procedure uses the following Where
clause to identify the customer:

WHERE ( ( [ Cust omer I D] = @Or i gi nal _Cust omer I D) )

When you configure the DataContext to use this stored procedure for updating
customers, you need to confirm whether you want to identify customers by
using the current value or the original value of CustomerID.
Using Stored Procedures
Microsoft LINQ Using Visual Basic 2008 4-87
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

TIP: If you are certain that the customer ID cannot change, you can safely select
either the original or current version of this property. To be on the safe side,
however, you should probably use the original value.
10. Click Apply.
11. Select Delete from the Behavior drop-down list.
12. Select Customize and select DeleteCustomer from the drop-down list.
13. Select CustomerID (Original) from the Class Properties drop-down list.
14. Click OK to close the Configure Behavior dialog box.
15. Select File|Save All.
The DataContext will now use these stored procedures instead of SQL
statements when you modify data and call SubmitChanges.
When you select Stored Procedures 2 in the chapters sample application, you
will see the second of two examples of calling stored procedures to modify
data in related tables. As in the first example, this example adds an order for a
customer. The order contains three products, so one record is added to the
Orders table and three related records are added to the Order Details table. The
difference between the first example and this one is that the stored procedures
are called automatically when the code calls SubmitChanges.
The code first creates a new instance of the Customer class and then calls the
InsertOnSubmit and SubmitChanges methods of the DataContext to add the
new customer.
Select Stored
Procedures 2
LINQ to SQL
4-88 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Di mnewCust omer As New Cust omer Wi t h _
{. Cust omer I D = " AAAAA" , _
. CompanyName = " AAAAA Consul t i ng" , _
. Cont act Name = " Don Ki el y" , _
. Cont act Ti t l e = " Sal es Manager " , _
. Addr ess = " 1234 Mai n St " , _
. Ci t y = " Tol edo" , _
. Regi on = " OH" , _
. Post al Code = " 43555" , _
. Count r y = " USA" , _
. Phone = " 419- 555- 5555" , _
. Fax = " 419- 555- 5556" }

nwi ndDat aCont ext . Cust omer s. I nser t OnSubmi t ( newCust omer )
nwi ndDat aCont ext . Submi t Changes( )

Di mohi oCust omer s = _
nwi ndDat aCont ext . Cust omer sI nRegi on( " OH" )

When the code calls SubmitChanges, LINQ to SQL generates the SQL
statement to call the AddCustomer stored procedure. The results of running
this code are the same as those shown previously in Figure 43.
The code next retrieves information for the new customer. The code modifies
several properties of the Customer class instance and then calls
SubmitChanges. LINQ to SQL generates the SQL statement to call the
UpdateCustomer stored procedure. The results of running this code are the
same as those shown previously in Figure 44.
Using Stored Procedures
Microsoft LINQ Using Visual Basic 2008 4-89
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Di mcust omer AAAAA = _
nwi ndDat aCont ext . Cust omer s. Si ngl e( _
Funct i on( c) c. Cust omer I D = " AAAAA" )

Wi t h cust omer AAAAA
. CompanyName = " Pent upl e A Consul t i ng"
. Cont act Ti t l e = " Vi ce Pr esi dent "
. Addr ess = " 100 J acobs Bl vd"
. Ci t y = " Cl evel and"
. Post al Code = " 44555"
. Phone = " 216- 555- 5555"
. Fax = " 216- 555- 5556"
End Wi t h

nwi ndDat aCont ext . Submi t Changes( )

Di mohi oCust omer s = _
nwi ndDat aCont ext . Cust omer sI nRegi on( " OH" )

Finally, the code calls the DeleteOnSubmit method, passing the Customer
class instance. When the code calls SubmitChanges, LINQ to SQL generates
the SQL statement to call the DeleteCustomer stored procedure. The results of
running this code are the same as those shown previously in Figure 45.

Di mcust omer AAAAA = _
nwi ndDat aCont ext . Cust omer s. Si ngl e( _
Funct i on( c) c. Cust omer I D = " AAAAA" )

nwi ndDat aCont ext . Cust omer s. Del et eOnSubmi t ( _
cust omer AAAAA)
nwi ndDat aCont ext . Submi t Changes( )

Di mohi oCust omer s = _
nwi ndDat aCont ext . Cust omer sI nRegi on( " OH" )

LINQ to SQL
4-90 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

LINQ to SQL vs DataSets
You may be starting to wonder how using LINQ to SQL differs from using
DataSets in your database applications. Lets review a few of the major
differences.
Object model: LINQ to SQL works through an object model. One of
the benefits is that its easier to write queries. Another benefit is that
you can rename classes and properties. In this chapter, we use
Northwind for the demos, so theres no need to rename. Customers are
in the Customers table and orders are in the Orders table. However,
your database may have more cryptic names. If you use DataSets, you
are stuck with those names. If you use an object model, you can
rename items so your code is easier to write, read, and understand.
In addition, working with related data is much easier with the object
model because you dont have to write the joins to get data out of
multiple tables. LINQ to SQL takes care of that for you.
Performance: ADO.NET communicates directly with the database, so
using DataAdapters and DataSets will be faster. Modeling has a layer
of abstraction and that has a price. LINQ to SQL needs to translate
your queries against the object model into native SQL and translate the
query results to class instances. This results in a performance hit that
may or may not be noticeable.
Supported data sources: ADO.NET works with lots of different data,
including Oracle, Access, and DB2. If you have an ADO.NET data
provider, you can work with a data source. LINQ to SQL works only
with SQL Server.
Offline support: It is easy to go offline and back online when you use
DataSets. You can use the WriteXml method of the DataSet to write
the contents of the DataSet to XML. You can store that XML on the
local computer. When you are offline, you can use the ReadXml
method to read the contents of the XML file into the DataSet. You are
then working with the same local copy of the data. Any changes you
make will be to that local copy. You can then use WriteXml to save
the changes to disk. When the user is back online, you can use
ReadXml to repopulate the DataSet and then save the changes to the
data source.
Batch updating: Datasets offer batch updating. LINQ to SQL does
not.
Both approaches have pros and cons. If you are writing an application where
users can simply view SQL Server data, it makes sense to use LINQ to SQL
instead of DataSets. However, if users can modify data, you will often want to
use DataSets. You can still use LINQ to SQL for querying data or for
retrieving aggregates, such as the total number or value of orders for a
customer.
LINQ to SQL vs DataSets
Microsoft LINQ Using Visual Basic 2008 4-91
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Its likely that you will use both DataSets and LINQ to SQL in many, perhaps
most, database applications.
LINQ to SQL
4-92 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Summary
You can use LINQ to SQL to query and modify data in a SQL Server
database.
LINQ to SQL is part of the ADO.NET family of technologies. It
abstracts away the various ADO.NET classes so you can write less
code.
To use LINQ to SQL, you map the structure of a relational database to
an object model. You can create the object model yourself.
Alternatively, you can use the Object Relational Designer in Visual
Studio.
The DataContext class is responsible for communication between the
entity classes and the database. It contains the connection string
information and methods for connecting to the database and
manipulating the data in the database.
At runtime, the .NET Framework translates LINQ queries into SQL
and sends them to the database. When the database returns results, the
runtime populates the objects with the returned data.
You can view the generated SQL statements in several ways. You can
use the Log property or GetCommand method of the DataContext.
You can use the SQL Server Query Visualizer. You can also use the
SQL Server Profiler.
The LINQ to SQL query syntax supports querying from related tables
via the Join clause. However, the object model already accounts for
the relationships between tables. That makes it easier to write queries
based on more than one table.
To add data, you can use the InsertOnSubmit method of the
DataContext. To modify data, you can change the values of properties.
To remove data, you can use the DeleteOnSubmit method.
To save changes, call the SubmitChanges method of the DataContext.
LINQ to SQL generates the appropriate Insert, Update, and Delete
statements and sends those to the SQL Server database. It also wraps
them in a transaction.
You can drag stored procedures from the Server Explorer to the Object
Relational Designer to create methods of the DataContext. You can
then call these methods and execute the stored procedures.
You can configure the DataContext to automatically use stored
procedures to insert, update, and delete data.
LINQ to SQL vs DataSets
Microsoft LINQ Using Visual Basic 2008 4-93
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Questions
1. How does LINQ to SQL bridge the gap between database programming
and object programming?
2. How do you create an object model from your data?
3. How do you use LINQ to SQL to modify data?
4. How can you use stored procedures with LINQ to SQL?
5. What are some differences between using LINQ to SQL and DataSets?

LINQ to SQL
4-94 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Answers
1. How does LINQ to SQL bridge the gap between database programming
and object programming?
LINQ to SQL provides a runtime infrastructure for managing
relational data as objects. To use LINQ to SQL, you map the
structure of a relational database to an object model. Each table
in the database maps to a class. This class is an entity class. You
then write queries that work with the object model. At runtime,
the .NET Framework translates LINQ queries into SQL and sends
them to the database. When the database returns results, the
runtime populates the objects with the returned data.
2. How do you create an object model from your data?
You can create the object model yourself, although this can be a
laborious, time-consuming process. Alternatively, you can use the
Object Relational Designer in Visual Studio. To build the model,
drag tables from the Server Explorer to the designer. The model
will contain an entity class for each table you drag.
3. How do you use LINQ to SQL to modify data?
To add data, you can use the InsertOnSubmit method of the
DataContext. To modify data, you can change the values of
properties. To remove data, you can use the DeleteOnSubmit
method. To save changes, call the SubmitChanges method of the
DataContext. LINQ to SQL generates the appropriate Insert,
Update, and Delete statements or the appropriate calls to stored
procedures and sends those to the SQL Server database. It also
wraps these in a transaction.
4. How can you use stored procedures with LINQ to SQL?
You can drag stored procedures from the Server Explorer to the
Object Relational Designer to create methods of the DataContext.
To call the stored procedures, you can then call those methods.
You can configure the DataContext to automatically use stored
procedures to insert, update, and delete data.
5. What are some differences between using LINQ to SQL and DataSets?
ADO.NET communicates directly with the database, whereas
LINQ to SQL works through the object model, so using DataSets
for querying will be faster. With LINQ to SQL, you can rename
classes and properties if necessary. ADO.NET works with lots of
different data. LINQ to SQL works only with SQL Server. DataSets
support batch updating and have built-in support for working
offline.
Lab 4:
LINQ to SQL
Microsoft LINQ Using Visual Basic 2008 4-95
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Lab 4:
LINQ to SQL
Lab 4:
LINQ to SQL
4-96 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Lab 4 Overview
In this lab youll learn how to create an object model based on tables in a SQL
Server database. Youll then write LINQ to SQL queries that use that object
model. Youll also see how to modify data and use stored procedures.
To complete this lab, youll need to work through three exercises:
Create an Object Model
Query Data
Modify Data
Each exercise includes an Objective section that describes the purpose of the
exercise. You are encouraged to try to complete the exercise from the
information given in the Objective section. If you require more information to
complete the exercise, the Objective section is followed by detailed step-by-
step instructions.
Create an Object Model
Microsoft LINQ Using Visual Basic 2008 4-97
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Create an Object Model
Objective
In this exercise, youll create an object model based on the Northwind SQL
Server database. You will create entity classes based on several tables in the
database. You will also create stored procedures and add them to the data
model.
Step-by-Step Instructions
In this section, you will use the Object Relational Designer to create an object
model based on the SQL Server Northwind database.
1. In Visual Studio 2008, select File|New Project. Select Windows from the
Project Types list. Then select Console Application from the Templates
pane.
2. Name the project and solution LINQToSQLLab. Click OK.
3. Select Project|Add New Item.
4. In the Add New Item dialog box, select LINQ to SQL Classes from the
Templates pane.
5. Enter Northwind in the Name text box and click Add. You should see the
Object Relational Designer, as shown in Figure 49.
Lab 4:
LINQ to SQL
4-98 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Figure 49. The Object Relational Designer before you create your object model.
6. Select View|Server Explorer to display the Server Explorer window.
NOTE If you completed the exercises earlier in the chapter, you should
see a connection to the Northwind database in the Server Explorer
and can skip ahead to Step 13.
7. In the Server Explorer window, click the Connect to Database button.
8. In the Add Connection dialog box, click Change. This displays the
Change Data Source dialog box, as shown in Figure 50.

Figure 50. Select the data source to use in the application.
Create an Object Model
Microsoft LINQ Using Visual Basic 2008 4-99
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

9. In the Change Data Source dialog box, select Microsoft SQL Server.
Click OK.
10. In the Add Connection dialog box, enter .\SQLEXPRESS in the Server
name text box. This indicates that you want to use the default instance of
SQL Express on this computer.
11. Select Northwind from the Select or enter a database name drop-down
list. The Add Connection dialog box should look like Figure 51.

Figure 51. Select SQL Express and the Northwind database as your data source.
12. In the Add Connection dialog box, click Test Connection. After you
receive a message that the connection succeeded, click OK to dismiss the
Add Connection dialog box.

Lab 4:
LINQ to SQL
4-100 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

13. In the Server Explorer window, expand the Data Connections node that
corresponds to the Northwind database. Expand the Tables node so you
see the list of tables in the database, as shown in Figure 52.

Figure 52. You can see the tables and other objects in the Northwind database.
14. Drag the Categories table from the Server Explorer window onto the left
pane of the Object Relational Designer. You should see the Category class
in the design surface, as shown in Figure 53. Note that the name of the
class is Category and the source is the Categories table in the database.
Create an Object Model
Microsoft LINQ Using Visual Basic 2008 4-101
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Figure 53. You created an entity class based on the Categories table.
15. Drag the Products table from the Server Explorer window onto the left
pane of the Object Relational Designer. You should see the Category and
Product classes in the design surface and you should see an association
line connecting them, as shown in Figure 54.
Lab 4:
LINQ to SQL
4-102 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Figure 54. The Category and Product classes are related.
16. Drag the Suppliers table from the Server Explorer window onto the left
pane of the Object Relational Designer. The designer should look like
Figure 55.
Create an Object Model
Microsoft LINQ Using Visual Basic 2008 4-103
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Figure 55. The object model consists of three entity classes.
17. Select File|Save All.
Next, you will create stored procedures for working with products. You will
then add those to the object model.
18. In the Server Explorer, expand the node for Stored Procedures.
19. Right-click Stored Procedures and select Add New Stored Procedure.
20. Replace the code with the following code:
Lab 4:
LINQ to SQL
4-104 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


CREATE PROCEDURE dbo. AddPr oduct
(
@Pr oduct Name nvar char ( 40) ,
@Suppl i er I D i nt ,
@Cat egor yI D i nt ,
@Quant i t yPer Uni t nvar char ( 20) ,
@Uni t Pr i ce money,
@Uni t sI nSt ock smal l i nt ,
@Uni t sOnOr der smal l i nt ,
@Reor der Level smal l i nt ,
@Di scont i nued bi t
)
AS
I NSERT I NTO [ dbo] . [ Pr oduct s] ( [ Pr oduct Name] ,
[ Suppl i er I D] , [ Cat egor yI D] , [ Quant i t yPer Uni t ] ,
[ Uni t Pr i ce] , [ Uni t sI nSt ock] , [ Uni t sOnOr der ] ,
[ Reor der Level ] , [ Di scont i nued] )
VALUES ( @Pr oduct Name, @Suppl i er I D, @Cat egor yI D,
@Quant i t yPer Uni t , @Uni t Pr i ce, @Uni t sI nSt ock,
@Uni t sOnOr der , @Reor der Level , @Di scont i nued) ;

RETURN SCOPE_I DENTI TY( )

21. Select File|Save to save the stored procedure to the database.
22. Right-click Stored Procedures and select Add New Stored Procedure.
23. Replace the code with the following code:
Create an Object Model
Microsoft LINQ Using Visual Basic 2008 4-105
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


CREATE PROCEDURE dbo. Updat ePr oduct
(
@Pr oduct Name nvar char ( 40) ,
@Suppl i er I D i nt ,
@Cat egor yI D i nt ,
@Quant i t yPer Uni t nvar char ( 20) ,
@Uni t Pr i ce money,
@Uni t sI nSt ock smal l i nt ,
@Uni t sOnOr der smal l i nt ,
@Reor der Level smal l i nt ,
@Di scont i nued bi t ,
@Or i gi nal _Pr oduct I D i nt
)
AS
UPDATE [ dbo] . [ Pr oduct s]
SET [ Pr oduct Name] = @Pr oduct Name,
[ Suppl i er I D] = @Suppl i er I D,
[ Cat egor yI D] = @Cat egor yI D,
[ Quant i t yPer Uni t ] = @Quant i t yPer Uni t ,
[ Uni t Pr i ce] = @Uni t Pr i ce,
[ Uni t sI nSt ock] = @Uni t sI nSt ock,
[ Uni t sOnOr der ] = @Uni t sOnOr der ,
[ Reor der Level ] = @Reor der Level ,
[ Di scont i nued] = @Di scont i nued
WHERE [ Pr oduct I D] = @Or i gi nal _Pr oduct I D;

24. Select File|Save to save the stored procedure to the database.
25. Right-click Stored Procedures and select Add New Stored Procedure.
26. Replace the code with the following code:
Lab 4:
LINQ to SQL
4-106 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


CREATE PROCEDURE dbo. Del et ePr oduct
(
@Or i gi nal _Pr oduct I D i nt
)
AS
SET NOCOUNT OFF;
DELETE FROM [ dbo] . [ Pr oduct s]
WHERE [ Pr oduct I D] =
@Or i gi nal _Pr oduct I D;

27. Select File|Save to save the stored procedure to the database.
28. Close the stored procedure code windows.
29. Drag the AddProduct, UpdateProduct, and DeleteProduct stored
procedures from the Server Explorer to the right pane of the Object
Relational Designer. This adds these stored procedures as methods of the
DataContext class, as shown in Figure 56.

Figure 56. The stored procedures are now methods of the DataContext class.
30. Select File|Save All.
Query Data
Microsoft LINQ Using Visual Basic 2008 4-107
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Query Data
Objective
In this exercise, youll write LINQ to SQL queries that work against the object
model you just created. These queries will retrieve information from the SQL
Server Northwind database.
Step-by-Step Instructions
1. Ensure that you have the project that you created in the previous exercise
open within Visual Studio 2008. (If you skipped that exercise, you can
open the project in the LinqToSQLLab_ex02 folder as a starting place for
this exercise.)
2. Open the Module1.vb file.
3. Add the following declaration inside the module:

Pr i vat e nwi ndDat aCont ext As Nor t hwi ndDat aCont ext = Not hi ng

4. Create the following method to retrieve a list of beverages:
Lab 4:
LINQ to SQL
4-108 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Pr i vat e Sub Exer ci se2_1( )
nwi ndDat aCont ext = New Nor t hwi ndDat aCont ext

nwi ndDat aCont ext . Log = Consol e. Out

Di mbever ages = _
Fr ompr oduct I n nwi ndDat aCont ext . Pr oduct s _
Wher e pr oduct . Cat egor yI D = 1 _
Sel ect pr oduct . Pr oduct Name, pr oduct . Uni t Pr i ce _
Or der By Uni t Pr i ce Descendi ng

For Each pr od I n bever ages
Consol e. Wr i t eLi ne( " {0} cost s {1: C}" , _
pr od. Pr oduct Name, pr od. Uni t Pr i ce)
Next
End Sub

5. Modify the Main method so that it calls the Exercise2_1 method:

Exer ci se2_1( )

Consol e. Wr i t eLi ne( )
Consol e. Wr i t eLi ne( " Pr ess any key. . . " )
Consol e. ReadKey( )

6. Save and run the application. You should see the results shown in
Figure 57. Press any key to return to Visual Studio.
Query Data
Microsoft LINQ Using Visual Basic 2008 4-109
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

SELECT [ t 0] . [ Pr oduct Name] , [ t 0] . [ Uni t Pr i ce]
FROM [ dbo] . [ Pr oduct s] AS [ t 0]
WHERE [ t 0] . [ Cat egor yI D] = @p0
ORDER BY [ t 0] . [ Uni t Pr i ce] DESC
- - @p0: I nput I nt ( Si ze = 0; Pr ec = 0; Scal e = 0) [ 1]
- - Cont ext : Sql Pr ovi der ( Sql 2005) Model : At t r i but edMet aModel
Bui l d: 3. 5. 30729. 1

Ct e de Bl aye cost s $263. 50
I poh Cof f ee cost s $46. 00
Chang cost s $19. 00
Chai cost s $18. 00
Char t r euse ver t e cost s $18. 00
St eel eye St out cost s $18. 00
Lakkal i kr i cost s $18. 00
Out back Lager cost s $15. 00
Laughi ng Lumber j ack Lager cost s $14. 00
Sasquat ch Al e cost s $14. 00
Rhnbr u Kl ost er bi er cost s $7. 75
Guar an Fant st i ca cost s $4. 50
Figure 57. This query returns a list of beverages and their prices.
7. Create the following method to calculate aggregate values for category 5:
Lab 4:
LINQ to SQL
4-110 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Pr i vat e Sub Exer ci se2_2( )
nwi ndDat aCont ext = New Nor t hwi ndDat aCont ext

Di mquer y = _
Aggr egat e pr oduct I n nwi ndDat aCont ext . Pr oduct s _
Wher e pr oduct . Cat egor yI D = 5 _
I nt o pr oduct Count = Count ( ) , _
aver agePr i ce = Aver age( pr oduct . Uni t Pr i ce) , _
hi ghest Pr i ce = Max( pr oduct . Uni t Pr i ce) , _
l owest Pr i ce = Mi n( pr oduct . Uni t Pr i ce)

Consol e. Wr i t eLi ne( _
" Ther e ar e {0} pr oduct s i n cat egor y 5" , _
quer y. pr oduct Count )
Consol e. Wr i t eLi ne( _
" The aver age pr i ce i s {0: C}" , _
quer y. aver agePr i ce)
Consol e. Wr i t eLi ne( _
" The hi ghest pr i ce i s {0: C}" , _
quer y. hi ghest Pr i ce)
Consol e. Wr i t eLi ne( _
" The l owest pr i ce i s {0: C}" , _
quer y. l owest Pr i ce)
End Sub

8. Modify the Main method so that it calls the Exercise2_2 method.
9. Save and run the application. You should see the results shown in
Figure 58. Press any key to return to Visual Studio.
Ther e ar e 7 pr oduct s i n cat egor y 5
The aver age pr i ce i s $20. 25
The hi ghest pr i ce i s $38. 00
The l owest pr i ce i s $7. 00
Figure 58. This query returns summary information for products in category 5.

Query Data
Microsoft LINQ Using Visual Basic 2008 4-111
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

10. Create the following method to retrieve products in the Seafood category:

Pr i vat e Sub Exer ci se2_3( )
nwi ndDat aCont ext = New Nor t hwi ndDat aCont ext

Di mseaf ood = _
Fr ompr oduct I n nwi ndDat aCont ext . Pr oduct s _
Wher e pr oduct . Cat egor y. Cat egor yName = " Seaf ood" _
Sel ect pr oduct . Pr oduct Name, pr oduct . Uni t Pr i ce _
Or der By Uni t Pr i ce Descendi ng

For Each pr od I n seaf ood
Consol e. Wr i t eLi ne( " {0} cost s {1: C}" , _
pr od. Pr oduct Name, pr od. Uni t Pr i ce)
Next
End Sub

11. Modify the Main method so that it calls the Exercise2_3 method.
12. Save and run the application. You should see the results shown in
Figure 59. Press any key to return to Visual Studio.
Car nar von Ti ger s cost s $62. 50
I kur a cost s $31. 00
Gr avad l ax cost s $26. 00
Nor d- Ost Mat j esher i ng cost s $25. 89
I nl agd Si l l cost s $19. 00
Bost on Cr ab Meat cost s $18. 40
Rd Kavi ar cost s $15. 00
Escar got s de Bour gogne cost s $13. 25
Spegesi l d cost s $12. 00
J ack' s New Engl and Cl amChowder cost s $9. 65
Rogede si l d cost s $9. 50
Konbu cost s $6. 00
Figure 59. This query returns a list of seafood products.
13. Create the following method to retrieve a list of high-priced products:
Lab 4:
LINQ to SQL
4-112 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Pr i vat e Sub Exer ci se2_4( )
nwi ndDat aCont ext = New Nor t hwi ndDat aCont ext

Di mhi ghPr i cedPr oduct s = _
Fr ompr oduct I n nwi ndDat aCont ext . Pr oduct s _
Wher e pr oduct . Uni t Pr i ce > 50 _
Sel ect pr oduct . Pr oduct Name, _
Suppl i er = pr oduct . Suppl i er . CompanyName, _
pr oduct . Uni t Pr i ce

For Each pr od I n hi ghPr i cedPr oduct s
Consol e. Wr i t eLi ne( " {0} by {1} cost s {2: C}" , _
pr od. Pr oduct Name, pr od. Suppl i er , _
pr od. Uni t Pr i ce)
Next
End Sub

14. Modify the Main method so that it calls the Exercise2_4 method.
15. Save and run the application. You should see the results shown in
Figure 60. Press any key to return to Visual Studio.
Mi shi Kobe Ni ku by Tokyo Tr ader s cost s $97. 00
Car nar von Ti ger s by Pavl ova, Lt d. cost s $62. 50
Si r Rodney' s Mar mal ade by Speci al t y Bi scui t s, Lt d. cost s
$81. 00
Thr i nger Rost br at wur st by Pl ut zer Lebensmi t t el gr omr kt e AG
cost s $123. 79
Ct e de Bl aye by Aux j oyeux eccl si ast i ques cost s $263. 50
Manj i mup Dr i ed Appl es by G' day, Mat e cost s $53. 00
Racl et t e Cour davaul t by Gai pt ur age cost s $55. 00
Figure 60. This query returns a list of high-priced products.
16. Create the following method to retrieve products from German suppliers:
Query Data
Microsoft LINQ Using Visual Basic 2008 4-113
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Pr i vat e Sub Exer ci se2_5( )
nwi ndDat aCont ext = New Nor t hwi ndDat aCont ext

Di mger manPr oduct s = _
Fr ompr oduct I n nwi ndDat aCont ext . Pr oduct s _
Wher e pr oduct . Suppl i er . Count r y = " Ger many" _
Gr oup pr oduct By pr oduct . Suppl i er . CompanyName _
I nt o gr oupedPr oduct s = Gr oup _
Sel ect CompanyName, gr oupedPr oduct s

For Each pr oduct I n ger manPr oduct s
Consol e. Wr i t eLi ne( " {0} has {1} pr oduct ( s) " , _
pr oduct . CompanyName, _
pr oduct . gr oupedPr oduct s. Count )
For Each pr od I n pr oduct . gr oupedPr oduct s
Consol e. Wr i t eLi ne( " {0} cost s {1: C}" , _
pr od. Pr oduct Name, pr od. Uni t Pr i ce)
Next
Consol e. Wr i t eLi ne( )
Next
End Sub

17. Modify the Main method so that it calls the Exercise2_5 method.
18. Save and run the application. You should see the results shown in
Figure 61. Press any key to return to Visual Studio.
Lab 4:
LINQ to SQL
4-114 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Hel i Swar en GmbH & Co. KG has 3 pr oduct ( s)
NuNuCa Nu- Nougat - Cr eme cost s $14. 00
Gumbr Gummi br chen cost s $31. 23
Schoggi Schokol ade cost s $43. 90

Nor d- Ost - Fi sch Handel sgesel l schaf t mbH has 1 pr oduct ( s)
Nor d- Ost Mat j esher i ng cost s $25. 89

Pl ut zer Lebensmi t t el gr omr kt e AG has 5 pr oduct ( s)
Rssl e Sauer kr aut cost s $45. 60
Thr i nger Rost br at wur st cost s $123. 79
Wi mmer s gut e Semmel kndel cost s $33. 25
Rhnbr u Kl ost er bi er cost s $7. 75
Or i gi nal Fr ankf ur t er gr ne Soe cost s $13. 00
Figure 61. This query returns a list of products from German suppliers.
Modify Data
Microsoft LINQ Using Visual Basic 2008 4-115
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Modify Data
Objective
In this exercise, youll see how to modify data by using the object model you
created in the first exercise. Youll use both generated Insert, Update, and
Delete statements as well as the stored procedures you created.
Step-by-Step Instructions
1. Ensure that you have the project that you created in the previous exercise
open within Visual Studio 2008. (If you skipped that exercise, you can
open the project in the LinqToSQLLab_ex03 folder as a starting place for
this exercise.)
2. Open the Module1.vb file.
3. Create the following method to add a new supplier:

Pr i vat e Sub Exer ci se3_1( )
nwi ndDat aCont ext = New Nor t hwi ndDat aCont ext

Di mnewSuppl i er As New Suppl i er Wi t h _
{. CompanyName = " AppDev" , _
. Cont act Name = " Rober t Gr een" , _
. Cont act Ti t l e = " I nst r uct or " , _
. Addr ess = " 10250 Val l ey Vi ew Dr " , _
. Ci t y = " Eden Pr ai r i e" , _
. Regi on = " MN" , _
. Post al Code = " 55344" , _
. Count r y = " USA" , _
. Phone = " ( 800) 578- 2062" , _
. Fax = " ( 952) 942- 8452" }

nwi ndDat aCont ext . Log = Consol e. Out

nwi ndDat aCont ext . Suppl i er s. I nser t OnSubmi t ( _
newSuppl i er )
Lab 4:
LINQ to SQL
4-116 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

nwi ndDat aCont ext . Submi t Changes( )

nwi ndDat aCont ext . Log = Not hi ng

Di musaSuppl i er s = _
Fr omsuppl i er I n nwi ndDat aCont ext . Suppl i er s _
Wher e suppl i er . Count r y = " USA" _
Sel ect suppl i er

For Each supp I n usaSuppl i er s
Consol e. Wr i t eLi ne( supp. CompanyName)
Consol e. Wr i t eLi ne( " {0}, {1}" , _
supp. Cont act Name, supp. Cont act Ti t l e)
Consol e. Wr i t eLi ne( " {0}, {1}" , _
supp. Ci t y, supp. Regi on)
Consol e. Wr i t eLi ne( )
Next
End Sub

4. Modify the Main method so that it calls the Exercise3_1 method.
5. Save and run the application. You should see the results shown in
Figure 62. Press any key to return to Visual Studio.
Modify Data
Microsoft LINQ Using Visual Basic 2008 4-117
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

I NSERT I NTO [ dbo] . [ Suppl i er s] ( [ CompanyName] , [ Cont act Name] ,
[ Cont act Ti t l e] , [ Add
r ess] , [ Ci t y] , [ Regi on] , [ Post al Code] , [ Count r y] , [ Phone] , [ Fax] ,
[ HomePage] )
VALUES ( @p0, @p1, @p2, @p3, @p4, @p5, @p6, @p7, @p8, @p9, @p10)

SELECT CONVERT( I nt , SCOPE_I DENTI TY( ) ) AS [ val ue]
- - @p0: I nput NVar Char ( Si ze = 6; Pr ec = 0; Scal e = 0) [ AppDev]
- - @p1: I nput NVar Char ( Si ze = 12; Pr ec = 0; Scal e = 0) [ Rober t
Gr een]
- - @p2: I nput NVar Char ( Si ze = 10; Pr ec = 0; Scal e = 0)
[ I nst r uct or ]
- - @p3: I nput NVar Char ( Si ze = 20; Pr ec = 0; Scal e = 0) [ 10250
Val l ey Vi ew Dr ]
- - @p4: I nput NVar Char ( Si ze = 12; Pr ec = 0; Scal e = 0) [ Eden
Pr ai r i e]
- - @p5: I nput NVar Char ( Si ze = 2; Pr ec = 0; Scal e = 0) [ MN]
- - @p6: I nput NVar Char ( Si ze = 5; Pr ec = 0; Scal e = 0) [ 55344]
- - @p7: I nput NVar Char ( Si ze = 3; Pr ec = 0; Scal e = 0) [ USA]
- - @p8: I nput NVar Char ( Si ze = 14; Pr ec = 0; Scal e = 0) [ ( 800) 578-
2062]
- - @p9: I nput NVar Char ( Si ze = 14; Pr ec = 0; Scal e = 0) [ ( 952) 942-
8452]
- - @p10: I nput NText ( Si ze = 0; Pr ec = 0; Scal e = 0) [ Nul l ]
- - Cont ext : Sql Pr ovi der ( Sql 2005) Model : At t r i but edMet aModel Bui l d:
3. 5. 30729. 1

New Or l eans Caj un Del i ght s
Shel l ey Bur ke, Or der Admi ni st r at or
New Or l eans, LA

Gr andma Kel l y' s Homest ead
Regi na Mur phy, Sal es Repr esent at i ve
Ann Ar bor , MI

Bi gf oot Br ewer i es
Cher yl Sayl or , Regi onal Account Rep.
Bend, OR

New Engl and Seaf ood Canner y
Robb Mer chant , Whol esal e Account Agent
Bost on, MA
Lab 4:
LINQ to SQL
4-118 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


AppDev
Rober t Gr een, I nst r uct or
Eden Pr ai r i e, MN
Figure 62. This example adds a new customer.
6. Create the following method to change some information about the
supplier you just added:

Pr i vat e Sub Exer ci se3_2( )
nwi ndDat aCont ext = New Nor t hwi ndDat aCont ext

Di msuppl i er AppDev = _
nwi ndDat aCont ext . Suppl i er s. Si ngl e( _
Funct i on( s) s. CompanyName = " AppDev" )

nwi ndDat aCont ext . Log = Consol e. Out

suppl i er AppDev. Cont act Name = " Ken Get z"
nwi ndDat aCont ext . Submi t Changes( )

nwi ndDat aCont ext . Log = Not hi ng

Di musaSuppl i er s = _
Fr omsuppl i er I n nwi ndDat aCont ext . Suppl i er s _
Wher e suppl i er . Count r y = " USA" _
Sel ect suppl i er

For Each supp I n usaSuppl i er s
Consol e. Wr i t eLi ne( supp. CompanyName)
Consol e. Wr i t eLi ne( " {0}, {1}" , _
supp. Cont act Name, supp. Cont act Ti t l e)
Consol e. Wr i t eLi ne( " {0}, {1}" , _
supp. Ci t y, supp. Regi on)
Consol e. Wr i t eLi ne( )
Next
End Sub

Modify Data
Microsoft LINQ Using Visual Basic 2008 4-119
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

7. Modify the Main method so that it calls the Exercise3_2 method.
8. Save and run the application. You should see the results shown in
Figure 63. Press any key to return to Visual Studio.
Lab 4:
LINQ to SQL
4-120 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

UPDATE [ dbo] . [ Suppl i er s]
SET [ Cont act Name] = @p11
WHERE ( [ Suppl i er I D] = @p0) AND ( [ CompanyName] = @p1) AND
( [ Cont act Name] = @p2) A
ND ( [ Cont act Ti t l e] = @p3) AND ( [ Addr ess] = @p4) AND ( [ Ci t y]
= @p5) AND ( [ Regi on]
= @p6) AND ( [ Post al Code] = @p7) AND ( [ Count r y] = @p8) AND
( [ Phone] = @p9) AND (
[ Fax] = @p10)
- - @p0: I nput I nt ( Si ze = 0; Pr ec = 0; Scal e = 0) [ 38]
- - @p1: I nput NVar Char ( Si ze = 6; Pr ec = 0; Scal e = 0)
[ AppDev]
- - @p2: I nput NVar Char ( Si ze = 12; Pr ec = 0; Scal e = 0)
[ Rober t Gr een]
- - @p3: I nput NVar Char ( Si ze = 10; Pr ec = 0; Scal e = 0)
[ I nst r uct or ]
- - @p4: I nput NVar Char ( Si ze = 20; Pr ec = 0; Scal e = 0)
[ 10250 Val l ey Vi ew Dr ]
- - @p5: I nput NVar Char ( Si ze = 12; Pr ec = 0; Scal e = 0)
[ Eden Pr ai r i e]
- - @p6: I nput NVar Char ( Si ze = 2; Pr ec = 0; Scal e = 0) [ MN]
- - @p7: I nput NVar Char ( Si ze = 5; Pr ec = 0; Scal e = 0)
[ 55344]
- - @p8: I nput NVar Char ( Si ze = 3; Pr ec = 0; Scal e = 0) [ USA]
- - @p9: I nput NVar Char ( Si ze = 14; Pr ec = 0; Scal e = 0)
[ ( 800) 578- 2062]
- - @p10: I nput NVar Char ( Si ze = 14; Pr ec = 0; Scal e = 0)
[ ( 952) 942- 8452]
- - @p11: I nput NVar Char ( Si ze = 8; Pr ec = 0; Scal e = 0) [ Ken
Get z]
- - Cont ext : Sql Pr ovi der ( Sql 2005) Model : At t r i but edMet aModel
Bui l d: 3. 5. 30729. 1

New Or l eans Caj un Del i ght s
Shel l ey Bur ke, Or der Admi ni st r at or
New Or l eans, LA

Gr andma Kel l y' s Homest ead
Regi na Mur phy, Sal es Repr esent at i ve
Ann Ar bor , MI

Bi gf oot Br ewer i es
Modify Data
Microsoft LINQ Using Visual Basic 2008 4-121
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Cher yl Sayl or , Regi onal Account Rep.
Bend, OR

New Engl and Seaf ood Canner y
Robb Mer chant , Whol esal e Account Agent
Bost on, MA

AppDev
Ken Get z, I nst r uct or
Eden Pr ai r i e, MN
Figure 63. This example changes the contact name of the supplier.
9. Create the following method to remove the supplier you just added:

Pr i vat e Sub Exer ci se3_3( )
nwi ndDat aCont ext = New Nor t hwi ndDat aCont ext

Di msuppl i er AppDev = _
nwi ndDat aCont ext . Suppl i er s. Si ngl e( _
Funct i on( s) s. CompanyName = " AppDev" )

nwi ndDat aCont ext . Log = Consol e. Out

nwi ndDat aCont ext . Suppl i er s. Del et eOnSubmi t ( _
suppl i er AppDev)
nwi ndDat aCont ext . Submi t Changes( )

nwi ndDat aCont ext . Log = Not hi ng

Di musaSuppl i er s = _
Fr omsuppl i er I n nwi ndDat aCont ext . Suppl i er s _
Wher e suppl i er . Count r y = " USA" _
Sel ect suppl i er

Lab 4:
LINQ to SQL
4-122 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

For Each supp I n usaSuppl i er s
Consol e. Wr i t eLi ne( supp. CompanyName)
Consol e. Wr i t eLi ne( " {0}, {1}" , _
supp. Cont act Name, supp. Cont act Ti t l e)
Consol e. Wr i t eLi ne( " {0}, {1}" , _
supp. Ci t y, supp. Regi on)
Consol e. Wr i t eLi ne( )
Next
End Sub

10. Modify the Main method so that it calls the Exercise3_3 method.
11. Save and run the application. You should see the results shown in
Figure 64. Press any key to return to Visual Studio.
Modify Data
Microsoft LINQ Using Visual Basic 2008 4-123
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

DELETE FROM [ dbo] . [ Suppl i er s] WHERE ( [ Suppl i er I D] = @p0) AND
( [ CompanyName] = @p
1) AND ( [ Cont act Name] = @p2) AND ( [ Cont act Ti t l e] = @p3) AND
( [ Addr ess] = @p4) AN
D ( [ Ci t y] = @p5) AND ( [ Regi on] = @p6) AND ( [ Post al Code] = @p7) AND
( [ Count r y] =
@p8) AND ( [ Phone] = @p9) AND ( [ Fax] = @p10)
- - @p0: I nput I nt ( Si ze = 0; Pr ec = 0; Scal e = 0) [ 39]
- - @p1: I nput NVar Char ( Si ze = 6; Pr ec = 0; Scal e = 0) [ AppDev]
- - @p2: I nput NVar Char ( Si ze = 8; Pr ec = 0; Scal e = 0) [ Ken Get z]
- - @p3: I nput NVar Char ( Si ze = 10; Pr ec = 0; Scal e = 0)
[ I nst r uct or ]
- - @p4: I nput NVar Char ( Si ze = 20; Pr ec = 0; Scal e = 0) [ 10250
Val l ey Vi ew Dr ]
- - @p5: I nput NVar Char ( Si ze = 12; Pr ec = 0; Scal e = 0) [ Eden
Pr ai r i e]
- - @p6: I nput NVar Char ( Si ze = 2; Pr ec = 0; Scal e = 0) [ MN]
- - @p7: I nput NVar Char ( Si ze = 5; Pr ec = 0; Scal e = 0) [ 55344]
- - @p8: I nput NVar Char ( Si ze = 3; Pr ec = 0; Scal e = 0) [ USA]
- - @p9: I nput NVar Char ( Si ze = 14; Pr ec = 0; Scal e = 0) [ ( 800) 578-
2062]
- - @p10: I nput NVar Char ( Si ze = 14; Pr ec = 0; Scal e = 0) [ ( 952)
942- 8452]
- - Cont ext : Sql Pr ovi der ( Sql 2005) Model : At t r i but edMet aModel Bui l d:
3. 5. 30729. 1

New Or l eans Caj un Del i ght s
Shel l ey Bur ke, Or der Admi ni st r at or
New Or l eans, LA

Gr andma Kel l y' s Homest ead
Regi na Mur phy, Sal es Repr esent at i ve
Ann Ar bor , MI

Bi gf oot Br ewer i es
Cher yl Sayl or , Regi onal Account Rep.
Bend, OR

New Engl and Seaf ood Canner y
Robb Mer chant , Whol esal e Account Agent
Bost on, MA
Figure 64. This example removes the supplier you added.
Lab 4:
LINQ to SQL
4-124 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

12. Create the following method to add a new product by using the
AddProduct stored procedure:

Pr i vat e Sub Exer ci se3_4( )
nwi ndDat aCont ext = New Nor t hwi ndDat aCont ext

Di msuppl i er Exot i c = _
nwi ndDat aCont ext . Suppl i er s. Si ngl e( _
Funct i on( s) s. CompanyName = " Exot i c Li qui ds" )

Di mcat egor yBever age = _
nwi ndDat aCont ext . Cat egor i es. Si ngl e( _
Funct i on( c) c. Cat egor yName = " Bever ages" )

nwi ndDat aCont ext . AddPr oduct ( _
" Doubl e Dut ch Chocol at e Mi l k" , _
suppl i er Exot i c. Suppl i er I D, _
cat egor yBever age. Cat egor yI D, _
" 12 car t ons per box" , 25D, 50, 50, 50, Fal se)

Di mbever ages = _
Fr ompr oduct I n nwi ndDat aCont ext . Pr oduct s _
Wher e pr oduct . Cat egor yI D = _
cat egor yBever age. Cat egor yI D _
Sel ect pr oduct . Pr oduct Name, pr oduct . Uni t Pr i ce

For Each pr od I n bever ages
Consol e. Wr i t eLi ne( " {0} cost s {1: C}" , _
pr od. Pr oduct Name, pr od. Uni t Pr i ce)
Next
End Sub

13. Modify the Main method so that it calls the Exercise3_4 method.
14. Save and run the application. You should see the results shown in
Figure 65. Press any key to return to Visual Studio.
Modify Data
Microsoft LINQ Using Visual Basic 2008 4-125
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Chai cost s $18. 00
Chang cost s $19. 00
Guar an Fant st i ca cost s $4. 50
Sasquat ch Al e cost s $14. 00
St eel eye St out cost s $18. 00
Ct e de Bl aye cost s $263. 50
Char t r euse ver t e cost s $18. 00
I poh Cof f ee cost s $46. 00
Laughi ng Lumber j ack Lager cost s $14. 00
Out back Lager cost s $15. 00
Rhnbr u Kl ost er bi er cost s $7. 75
Lakkal i kr i cost s $18. 00
Doubl e Dut ch Chocol at e Mi l k cost s $25. 00
Figure 65. This example adds a product.
15. Create the following method to modify some information about the
product you just added via the UpdateProduct stored procedure:

Pr i vat e Sub Exer ci se3_5( )
nwi ndDat aCont ext = New Nor t hwi ndDat aCont ext

Di mdoubl eDut ch = _
nwi ndDat aCont ext . Pr oduct s. Si ngl e( _
Funct i on( p) p. Pr oduct Name = _
" Doubl e Dut ch Chocol at e Mi l k" )

nwi ndDat aCont ext . Updat ePr oduct ( _
" Doubl e Dut ch Nonf at Chocol at e Mi l k" , _
doubl eDut ch. Suppl i er I D, _
doubl eDut ch. Cat egor yI D, _
doubl eDut ch. Quant i t yPer Uni t , _
20D, _
doubl eDut ch. Uni t sI nSt ock, _
doubl eDut ch. Uni t sOnOr der , _
doubl eDut ch. Reor der Level , _
doubl eDut ch. Di scont i nued, _
doubl eDut ch. Pr oduct I D)

Lab 4:
LINQ to SQL
4-126 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Di mbever ages = _
Fr ompr oduct I n nwi ndDat aCont ext . Pr oduct s _
Wher e pr oduct . Cat egor yI D = _
doubl eDut ch. Cat egor yI D _
Sel ect pr oduct . Pr oduct Name, pr oduct . Uni t Pr i ce

For Each pr od I n bever ages
Consol e. Wr i t eLi ne( " {0} cost s {1: C}" , _
pr od. Pr oduct Name, pr od. Uni t Pr i ce)
Next
End Sub

16. Modify the Main method so that it calls the Exercise3_5 method.
17. Save and run the application. You should see the results shown in
Figure 66. Press any key to return to Visual Studio.
Chai cost s $18. 00
Chang cost s $19. 00
Guar an Fant st i ca cost s $4. 50
Sasquat ch Al e cost s $14. 00
St eel eye St out cost s $18. 00
Ct e de Bl aye cost s $263. 50
Char t r euse ver t e cost s $18. 00
I poh Cof f ee cost s $46. 00
Laughi ng Lumber j ack Lager cost s $14. 00
Out back Lager cost s $15. 00
Rhnbr u Kl ost er bi er cost s $7. 75
Lakkal i kr i cost s $18. 00
Doubl e Dut ch Nonf at Chocol at e Mi l k cost s $20. 00
Figure 66. This example changes some information about the product.
18. Create the following method to remove the product you just added by
using the DeleteProduct stored procedure:
Modify Data
Microsoft LINQ Using Visual Basic 2008 4-127
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Pr i vat e Sub Exer ci se3_6( )
nwi ndDat aCont ext = New Nor t hwi ndDat aCont ext

Di mdoubl eDut ch = _
nwi ndDat aCont ext . Pr oduct s. Si ngl e( _
Funct i on( p) p. Pr oduct Name = _
" Doubl e Dut ch Nonf at Chocol at e Mi l k" )

nwi ndDat aCont ext . Del et ePr oduct ( doubl eDut ch. Pr oduct I D)

Di mbever ages = _
Fr ompr oduct I n nwi ndDat aCont ext . Pr oduct s _
Wher e pr oduct . Cat egor yI D = _
doubl eDut ch. Cat egor yI D _
Sel ect pr oduct . Pr oduct Name, pr oduct . Uni t Pr i ce

For Each pr od I n bever ages
Consol e. Wr i t eLi ne( " {0} cost s {1: C}" , _
pr od. Pr oduct Name, pr od. Uni t Pr i ce)
Next
End Sub

19. Modify the Main method so that it calls the Exercise3_6 method.
20. Save and run the application. You should see the results shown in
Figure 67. Press any key to return to Visual Studio.
Lab 4:
LINQ to SQL
4-128 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Chai cost s $18. 00
Chang cost s $19. 00
Guar an Fant st i ca cost s $4. 50
Sasquat ch Al e cost s $14. 00
St eel eye St out cost s $18. 00
Ct e de Bl aye cost s $263. 50
Char t r euse ver t e cost s $18. 00
I poh Cof f ee cost s $46. 00
Laughi ng Lumber j ack Lager cost s $14. 00
Out back Lager cost s $15. 00
Rhnbr u Kl ost er bi er cost s $7. 75
Lakkal i kr i cost s $18. 00
Figure 67. This example removes the product that you just added.
You will now configure the DataContext to use stored procedures when you
call the SubmitChanges method after adding, modifying, or removing a
product.
21. In the Solution Explorer, double-click Northwind.dbml. This opens the
Object Relational Designer.
22. Right-click Product and select Configure Behavior. This displays the
Configure Behavior dialog box, as shown in Figure 68.
Modify Data
Microsoft LINQ Using Visual Basic 2008 4-129
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Figure 68. Use this dialog box to instruct the class to use SQL statements or stored
procedures to modify data.
23. Select Customize and select AddProduct from the drop-down list, as
shown in Figure 69.
Lab 4:
LINQ to SQL
4-130 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Figure 69. Configure the DataContext to use the AddProduct stored procedure
when you add products.
24. Click Apply.
25. Select Update from the Behavior drop-down list.
26. Select Customize and select UpdateProduct from the drop-down list.
27. Locate the original_ProductID method argument. Select ProductID
(Original) from the Class Properties drop-down list, as shown in
Figure 70.
Modify Data
Microsoft LINQ Using Visual Basic 2008 4-131
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.


Figure 70. Identify the property that identifies the product.
28. Click Apply.
29. Select Delete from the Behavior drop-down list.
30. Select Customize and select DeleteProduct from the drop-down list.
31. Select ProductID (Original) from the Class Properties drop-down list.
32. Click OK to close the Configure Behavior dialog box.
33. Select File|Save All.
34. Create the following method to add a new product:

Pr i vat e Sub Exer ci se3_7( )
nwi ndDat aCont ext = New Nor t hwi ndDat aCont ext

Di msuppl i er Exot i c = _
nwi ndDat aCont ext . Suppl i er s. Si ngl e( _
Funct i on( s) s. CompanyName = " Exot i c Li qui ds" )

Lab 4:
LINQ to SQL
4-132 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

Di mcat egor yBever age = _
nwi ndDat aCont ext . Cat egor i es. Si ngl e( _
Funct i on( c) c. Cat egor yName = " Bever ages" )

Di mnewPr oduct As New Pr oduct Wi t h _
{. Pr oduct Name = " Doubl e Dut ch Chocol at e Mi l k" , _
. Suppl i er I D = suppl i er Exot i c. Suppl i er I D, _
. Cat egor yI D = cat egor yBever age. Cat egor yI D, _
. Quant i t yPer Uni t = " 12 car t ons per box" , _
. Uni t Pr i ce = 25D, _
. Uni t sI nSt ock = 50, _
. Uni t sOnOr der = 50, _
. Reor der Level = 50, _
. Di scont i nued = Fal se}

nwi ndDat aCont ext . Log = Consol e. Out

nwi ndDat aCont ext . Pr oduct s. I nser t OnSubmi t ( newPr oduct )
nwi ndDat aCont ext . Submi t Changes( )

nwi ndDat aCont ext . Log = Not hi ng

Di mbever ages = _
Fr ompr oduct I n nwi ndDat aCont ext . Pr oduct s _
Wher e pr oduct . Cat egor yI D = _
cat egor yBever age. Cat egor yI D _
Sel ect pr oduct . Pr oduct Name, pr oduct . Uni t Pr i ce

For Each pr od I n bever ages
Consol e. Wr i t eLi ne( " {0} cost s {1: C}" , _
pr od. Pr oduct Name, pr od. Uni t Pr i ce)
Next
End Sub





Modify Data
Microsoft LINQ Using Visual Basic 2008 4-133
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

35. Modify the Main method so that it calls the Exercise3_7 method.
36. Save and run the application. You should see the results shown in
Figure 71. Press any key to return to Visual Studio.
EXEC @RETURN_VALUE = [ dbo] . [ AddPr oduct ] @Pr oduct Name = @p0,
@Suppl i er I D = @p1, @
Cat egor yI D = @p2, @Quant i t yPer Uni t = @p3, @Uni t Pr i ce = @p4,
@Uni t sI nSt ock = @p5,
@Uni t sOnOr der = @p6, @Reor der Level = @p7, @Di scont i nued =
@p8
- - @p0: I nput NVar Char ( Si ze = 27; Pr ec = 0; Scal e = 0)
[ Doubl e Dut ch Chocol at e
Mi l k]
- - @p1: I nput I nt ( Si ze = 0; Pr ec = 0; Scal e = 0) [ 32]
- - @p2: I nput I nt ( Si ze = 0; Pr ec = 0; Scal e = 0) [ 1]
- - @p3: I nput NVar Char ( Si ze = 18; Pr ec = 0; Scal e = 0) [ 12
car t ons per box]
- - @p4: I nput Money ( Si ze = 0; Pr ec = 19; Scal e = 4) [ 25]
- - @p5: I nput Smal l I nt ( Si ze = 0; Pr ec = 0; Scal e = 0) [ 50]
- - @p6: I nput Smal l I nt ( Si ze = 0; Pr ec = 0; Scal e = 0) [ 50]
- - @p7: I nput Smal l I nt ( Si ze = 0; Pr ec = 0; Scal e = 0) [ 50]
- - @p8: I nput Bi t ( Si ze = 0; Pr ec = 0; Scal e = 0) [ Fal se]
- - @RETURN_VALUE: Out put I nt ( Si ze = 0; Pr ec = 0; Scal e = 0)
[ Nul l ]
- - Cont ext : Sql Pr ovi der ( Sql 2005) Model : At t r i but edMet aModel
Bui l d: 3. 5. 30729. 1

Chai cost s $18. 00
Chang cost s $19. 00
Guar an Fant st i ca cost s $4. 50
Sasquat ch Al e cost s $14. 00
St eel eye St out cost s $18. 00
Ct e de Bl aye cost s $263. 50
Char t r euse ver t e cost s $18. 00
I poh Cof f ee cost s $46. 00
Laughi ng Lumber j ack Lager cost s $14. 00
Out back Lager cost s $15. 00
Rhnbr u Kl ost er bi er cost s $7. 75
Lakkal i kr i cost s $18. 00
Doubl e Dut ch Chocol at e Mi l k cost s $25. 00

Figure 71. This example adds a product.
Lab 4:
LINQ to SQL
4-134 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

37. Create the following method to modify some information about the
product that you just added:

Pr i vat e Sub Exer ci se3_8( )
nwi ndDat aCont ext = New Nor t hwi ndDat aCont ext

Di mdoubl eDut ch = _
nwi ndDat aCont ext . Pr oduct s. Si ngl e( _
Funct i on( p) p. Pr oduct Name = _
" Doubl e Dut ch Chocol at e Mi l k" )

doubl eDut ch. Pr oduct Name = _
" Doubl e Dut ch Nonf at Chocol at e Mi l k"
doubl eDut ch. Uni t Pr i ce = 20D

nwi ndDat aCont ext . Log = Consol e. Out

nwi ndDat aCont ext . Submi t Changes( )

nwi ndDat aCont ext . Log = Not hi ng

Di mbever ages = _
Fr ompr oduct I n nwi ndDat aCont ext . Pr oduct s _
Wher e pr oduct . Cat egor yI D = _
doubl eDut ch. Cat egor yI D _
Sel ect pr oduct . Pr oduct Name, pr oduct . Uni t Pr i ce

For Each pr od I n bever ages
Consol e. Wr i t eLi ne( " {0} cost s {1: C}" , _
pr od. Pr oduct Name, pr od. Uni t Pr i ce)
Next
End Sub

38. Modify the Main method so that it calls the Exercise3_8 method.
39. Save and run the application. You should see the results shown in
Figure 72. Press any key to return to Visual Studio.
Modify Data
Microsoft LINQ Using Visual Basic 2008 4-135
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

EXEC @RETURN_VALUE = [ dbo] . [ Updat ePr oduct ] @Pr oduct Name =
@p0, @Suppl i er I D = @p1
, @Cat egor yI D = @p2, @Quant i t yPer Uni t = @p3, @Uni t Pr i ce =
@p4, @Uni t sI nSt ock = @
p5, @Uni t sOnOr der = @p6, @Reor der Level = @p7, @Di scont i nued
= @p8, @Or i gi nal _Pr o
duct I D = @p9
- - @p0: I nput NVar Char ( Si ze = 34; Pr ec = 0; Scal e = 0)
[ Doubl e Dut ch Nonf at Cho
col at e Mi l k]
- - @p1: I nput I nt ( Si ze = 0; Pr ec = 0; Scal e = 0) [ 32]
- - @p2: I nput I nt ( Si ze = 0; Pr ec = 0; Scal e = 0) [ 1]
- - @p3: I nput NVar Char ( Si ze = 18; Pr ec = 0; Scal e = 0) [ 12
car t ons per box]
- - @p4: I nput Money ( Si ze = 0; Pr ec = 19; Scal e = 4) [ 20]
- - @p5: I nput Smal l I nt ( Si ze = 0; Pr ec = 0; Scal e = 0) [ 50]
- - @p6: I nput Smal l I nt ( Si ze = 0; Pr ec = 0; Scal e = 0) [ 50]
- - @p7: I nput Smal l I nt ( Si ze = 0; Pr ec = 0; Scal e = 0) [ 50]
- - @p8: I nput Bi t ( Si ze = 0; Pr ec = 0; Scal e = 0) [ Fal se]
- - @p9: I nput I nt ( Si ze = 0; Pr ec = 0; Scal e = 0) [ 82]
- - @RETURN_VALUE: Out put I nt ( Si ze = 0; Pr ec = 0; Scal e = 0)
[ Nul l ]
- - Cont ext : Sql Pr ovi der ( Sql 2005) Model : At t r i but edMet aModel
Bui l d: 3. 5. 30729. 1

Chai cost s $18. 00
Chang cost s $19. 00
Guar an Fant st i ca cost s $4. 50
Sasquat ch Al e cost s $14. 00
St eel eye St out cost s $18. 00
Ct e de Bl aye cost s $263. 50
Char t r euse ver t e cost s $18. 00
I poh Cof f ee cost s $46. 00
Laughi ng Lumber j ack Lager cost s $14. 00
Out back Lager cost s $15. 00
Rhnbr u Kl ost er bi er cost s $7. 75
Lakkal i kr i cost s $18. 00
Doubl e Dut ch Nonf at Chocol at e Mi l k cost s $20. 00
Figure 72. This example changes some information about the product.

Lab 4:
LINQ to SQL
4-136 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

40. Create the following method to remove the product:

Pr i vat e Sub Exer ci se3_9( )
nwi ndDat aCont ext = New Nor t hwi ndDat aCont ext

Di mdoubl eDut ch = _
nwi ndDat aCont ext . Pr oduct s. Si ngl e( _
Funct i on( p) p. Pr oduct Name = _
" Doubl e Dut ch Nonf at Chocol at e Mi l k" )

nwi ndDat aCont ext . Pr oduct s. Del et eOnSubmi t ( _
doubl eDut ch)

nwi ndDat aCont ext . Log = Consol e. Out

nwi ndDat aCont ext . Submi t Changes( )

nwi ndDat aCont ext . Log = Not hi ng

Di mbever ages = _
Fr ompr oduct I n nwi ndDat aCont ext . Pr oduct s _
Wher e pr oduct . Cat egor yI D = _
doubl eDut ch. Cat egor yI D _
Sel ect pr oduct . Pr oduct Name, pr oduct . Uni t Pr i ce

For Each pr od I n bever ages
Consol e. Wr i t eLi ne( " {0} cost s {1: C}" , _
pr od. Pr oduct Name, pr od. Uni t Pr i ce)
Next
End Sub

41. Modify the Main method so that it calls the Exercise3_9 method.
42. Save and run the application. You should see the results shown in
Figure 73. Press any key to return to Visual Studio.
Modify Data
Microsoft LINQ Using Visual Basic 2008 4-137
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

EXEC @RETURN_VALUE = [ dbo] . [ Del et ePr oduct ]
@Or i gi nal _Pr oduct I D = @p0
- - @p0: I nput I nt ( Si ze = 0; Pr ec = 0; Scal e = 0) [ 82]
- - @RETURN_VALUE: Out put I nt ( Si ze = 0; Pr ec = 0; Scal e = 0)
[ Nul l ]
- - Cont ext : Sql Pr ovi der ( Sql 2005) Model : At t r i but edMet aModel
Bui l d: 3. 5. 30729. 1

Chai cost s $18. 00
Chang cost s $19. 00
Guar an Fant st i ca cost s $4. 50
Sasquat ch Al e cost s $14. 00
St eel eye St out cost s $18. 00
Ct e de Bl aye cost s $263. 50
Char t r euse ver t e cost s $18. 00
I poh Cof f ee cost s $46. 00
Laughi ng Lumber j ack Lager cost s $14. 00
Out back Lager cost s $15. 00
Rhnbr u Kl ost er bi er cost s $7. 75
Lakkal i kr i cost s $18. 00
Figure 73. This example removes the product you just added.
Lab 4:
LINQ to SQL
4-138 Microsoft LINQ Using Visual Basic 2008
Copyright by Application Developers Training Company
All rights reserved. Reproduction is strictly prohibited.

You might also like