End Sub C# protected void Page_Loadobject sender, EventArgs e { MoviesDataContext dc = new MoviesDataContext; var query = from m in dc.Movies select m; System.Diagnostics.Debug.WriteLine
Trang 1End Sub
C#
protected void Page_Load(object sender, EventArgs e)
{
MoviesDataContext dc = new MoviesDataContext();
var query = from m in dc.Movies
select m;
System.Diagnostics.Debug.WriteLine(query);
this.GridView1.DataSource = query;
this.GridView1.DataBind();
}
Now, when you debug the Web site using Visual Studio, you can see the SQL query, as shown
in Figure 9-11
Figure 9-11 The SQL query generated by LINQ to SQL
As you can see, the SQL generated is standard SQL syntax, and LINQ is quite good at optimizing the
queries it generates, even for more complex queries such as the grouping query shown in Listing 9-26
Listing 9-26: Grouping LINQ to SQL data
VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Dim dc As New MoviesDataContext()
Dim query = From m In dc.Movies _
Group By m.Genre Into g = Group, Count() System.Diagnostics.Debug.WriteLine(query)
Me.GridView1.DataSource = query
Trang 2End Sub
C#
protected void Page_Load(object sender, EventArgs e)
{
MoviesDataContext dc = new MoviesDataContext();
var query = from m in dc.Movies
group m by m.Genre into g
System.Diagnostics.Debug.WriteLine(query);
this.GridView1.DataSource = query;
this.GridView1.DataBind();
}
The generated SQL for this query is shown in Figure 9-12
Figure 9-12 Grouping SQL data using LINQ to SQL
Note that SQL to LINQ generates SQL that is optimized for SQL Server 2005
LINQ also includes a logging option you can enable by setting the Log property of the data context
While LINQ to SQL does an excellent job generating the SQL query syntax, there may be times where it is more appropriate to use other SQL query methods, such as Stored Procedures, or Views LINQ supports using the predefined queries as well
To use a SQL View with LINQ to SQL, you simply drag the View onto the LINQ to SQL design surface just as you would a standard SQL table Views appear on the design surface, just as the tables we added earlier Once the View is on the design surface, you can execute queries against it, just as you did the SQL tables This is shown in Listing 9-27
Trang 3Listing 9-27: Querying LINQ to SQL data using a View
VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Dim dc As New MoviesDataContext()
Dim query = From m In dc.AllMovies _
Select m System.Diagnostics.Debug.WriteLine(query)
Me.GridView1.DataSource = query
Me.GridView1.DataBind()
End Sub
C#
protected void Page_Load(object sender, EventArgs e)
{
MoviesDataContext dc = new MoviesDataContext();
var query = from m in dc.AllMovies
select m;
System.Diagnostics.Debug.WriteLine(query);
this.GridView1.DataSource = query;
this.GridView1.DataBind();
}
Unlike Tables or Views, which LINQ to SQL exposes as properties, Stored Procedures can require
param-eters Therefore, LINQ to SQL exposes from the data context object them as method calls, allowing you to
provide method parameter values which are translated by LINQ into store procedure parameters Listing
2-28 shows a simple stored procedure you can use to retrieve a specific Genre from the database
Listing 9-28: Simple SQL Stored procedure
CREATE PROCEDURE dbo.GetGenre
(
@id int
)
AS
SELECT * FROM Genre WHERE ID = @id
You can add a Stored Procedure to your LINQ to SQL designer just as you did the Tables and Views,
by dragging them from the Server Explorer onto the LINQ to SQL Classes design surface If you expect
your stored procedure to return a collection of data from a table in your database, you should drop
the stored procedure onto the LINQ class that represents the types returned by the query In the case
of the stored procedure shown in Listing 9-28, it will return all of the Genre records that match the
provided ID, therefore you should drop the GetGenres stored procedure onto the Genres table in the
Visual Studio designer This tells the designer to generate a method which returns a generic collection of
Genre objects Once you drop the stored procedure onto the design surface, unlike the Tables and Views,
Trang 4the Stored Procedure will be displayed in a list on the right-hand side of the design surface The GetGenre stored procedure is shown after being added in Figure 9-13
Figure 9-13 The GetGenre stored procedure has been added to the Method Pane in the LINQ to SQL
design surface
After you have added the Stored Proceedures, you can access them through the data context, just
as the Table and Views we accessed As was stated earlier, however, LINQ to SQL exposes them
as method calls Therefore, they may require you to provide method parameters, as shown in
Listing 9-29
Listing 9-29: Selecting data from a Stored Procedure
VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Dim dc As New MoviesDataContext()
Me.GridView1.DataSource = dc.GetGenre(1)
Me.GridView1.DataBind()
End Sub
Continued
Trang 5protected void Page_Load(object sender, EventArgs e)
{
MoviesDataContext dc = new MoviesDataContext();
this.GridView1.DataSource = dc.GetGenre(1);
this.GridView1.DataBind();
}
Insert, Update, and Delete Queries through LINQ
Not only can LINQ to SQL be used to create powerful queries that select data from a data source, but it
can also manage insert, updates, and delete operations By default, LINQ to SQL does this in much the
same manner as selecting data LINQ to SQL uses the object class representations of the SQL structures
and dynamically generates SQL Insert, Update, and Delete commands As with selection, you can also
use Stored Procedures to perform the insert, update, or deletes
Insert Data Using LINQ
Inserting data using LINQ to SQL is as easy as creating a new instance of the object you want to insert,
and adding that to the object collection The LINQ classes provide two methods called InsertOnSubmit
and InsertAllOnSubmit which make it simple to create and add any object to a LINQ collection The
InsertOnSubmit accepts a single entity as its method parameter, allowing you to insert a single entity,
while the InsertAllOnSubmit method accepts a collection as its method parameter, allowing you to insert
an entire collection of data in a single method call
Once you have added your objects, LINQ to SQL does require the extra step of calling the Data Context
objects SubmitChanges method Calling this method tells LINQ to initiate the Insert action Listing 9-30
shows an example of creating a new Movies object, and then Adding it to the Movies collection and
calling SubmitChanges to persist the change back to the SQL database
Listing 9-30: Inserting data using LINQ to SQL
VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Dim dc As New MoviesDataContext()
Dim m As New Movie With {.Title = "The Princess Bride", Director =
"Rob Reiner", _
.Genre = 0, ReleaseDate = DateTime.Parse("9/25/1987"), Runtime = 98}
dc.Movies.InsertOnSubmit(m)
dc.SubmitChanges()
End Sub
C#
protected void Page_Load(object sender, EventArgs e)
Trang 6MoviesDataContext dc = new MoviesDataContext();
Movie m = new Movie { Title="The Princess Bride", Director="Rob Reiner", Genre=0,
ReleaseDate=DateTime.Parse("9/25/1987"), Runtime=98 } ; dc.Movies.InsertOnSubmit(m);
dc.SubmitChanges();
}
Using Stored Procedures to Insert Data
Of course, you may already have a complex stored procedure written to handle the insertion of data into your database table LINQ makes it simple to use an existing Stored Procedure to insert data into a table
To do this, on the LINQ to SQL design surface, select the entity you want to insert data into, which in this case is the Movies entity After selecting the entity, open its properties window and locate the Default
Methods section, as shown in Figure 9-14
Figure 9-14 The properties of the Movies Default Methods section enable you to configure the Delete,
Insert, and Update behavior of LINQ to SQL for this table
Trang 7The Default Methods section contains three properties, Delete, Insert, and Update, which define the
behavior LINQ should use when executing these actions on the Movies table By default, each property
is set to the valueUseRuntime, which tells LINQ to dynamically generate SQL statements at runtime
Because you want to insert data into the table using a Stored Procedure, open the Insert properties
Con-figure Behavior dialog
In the dialog, change the Behavior radio button selection from Use Runtime to Customize Next, select
the appropriate stored procedure from the drop-down list below the radio buttons When you select the
stored procedure, LINQ automatically tries to match the table columns to the stored procedure input
parameters However, you can change these manually, if needed
The final Configure Behavior dialog is shown in Figure 9-15
Figure 9-15 Configure Behavior dialog configured for the InsertMovie Stored Procedure
Trang 8Now, when you run the code from Listing 9-30, LINQ will use the stored procedure you configured
instead of dynamically generating a SQL Insert statement
Update Data using LINQ
Updating data with LINQ is very similar to inserting data The first set is to get the specific object you
want to update You can do this by using the Single method of the collection you want to change The
scalar Single method returns a single object from the collection based on its input parameter If more than one record matches the parameters, the Single method simply returns the first match
Once you have the record you want to update, you simply change the object’s property values, and then call the data context’s SubmitChanges method Listing 9-31 shows the code required to update a specific Movie
Listing 9-31: Updating data using LINQ to SQL
VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Dim dc As New MoviesDataContext()
Dim movie = dc.Movies.Single(Function(m) m.Title = "Fletch")
movie.Genre = 1
dc.SubmitChanges()
End Sub
C#
protected void Page_Load(object sender, EventArgs e)
{
MoviesDataContext dc = new MoviesDataContext();
var movie = dc.Movies.Single(m => m.Title == "Fletch");
movie.Genre = 1;
dc.SubmitChanges();
}
Handling Data Concurrency
LINQ to SQL also includes and uses by default optimistic concurrency That means that if two users
retrieve the same record from the database and both try to update it, the first user to submit their update
to the server wins If the second user attempts to update the record after the first, LINQ to SQL will detect that the original record has changed and will raise a ChangeConflictException
Deleting Data Using LINQ
Finally, LINQ to SQL also enables you to delete data from your SQL data source Each data class object generated by the LINQ to SQL designer also includes two methods that enable you to delete objects
from the collection, theDeleteOnSubmitandDeleteAllOnSubmitmethods As the names imply, the
DeleteOnSubmitmethod removes a single object from the collection, whereas theDeleteAllOnSubmit
method removes all records from the collection
Trang 9Listing 9-32 shows how you can use LINQ and theDeleteOnSubmitandDeleteAllOnSubmitmethods to
delete data from your data source
Listing 9-32: Deleting data using LINQ to SQL
VB
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Dim dc As New MoviesDataContext()
’Select and remove all Action movies Dim query = From m In dc.Movies _
Where (m.Genre = 2) _ Select m
dc.Movies.DeleteAllOnSubmit(query)
’Select a single movie and remove it Dim movie = dc.Movies.Single(Function(m) m.Title = "Fletch") dc.Movies.DeleteOnSubmit(movie)
dc.SubmitChanges() End Sub
C#
protected void Page_Load(object sender, EventArgs e)
{
MoviesDataContext dc = new MoviesDataContext();
//Select and remove all Action movies
var query = from m in dc.Movies
where m.Genre == 2 select m;
dc.Movies.DeleteAllOnSubmit(query);
//Select a single movie and remove it
var movie = dc.Movies.Single(m => m.Title == "Fletch");
dc.Movies.DeleteOnSubmit(movie);
dc.SubmitChanges();
}
As with the other SQL commands, you must remember to call the Data ContextsSubmitChangesmethod
in order to commit the changes back to the SQL data source
Extending LINQ
This chapter focuses primarily on the LINQ capabilities included in the NET framework, but LINQ is
highly extensible and can be used to create query frameworks over just about any data source While
showing you how to implement you own LINQ provider is beyond the scope of this chapter, there are
lots of implementations of LINQ that query a wide variety of data stores such as LDAP, Sharepoint, and
evenAmazon.com
Trang 10Roger Jennings from Oakleaf Systems maintains a list of third-party LINQ providers on his blog which can be found athttp://oakleafblog.blogspot.com/2007/03/third-party-linq-providers.html
Summar y
This chapter has introduced you to the new Language Integrated Query, or LINQ, features of NET 3.5, which greatly simplifies the querying of data in NET LINQ makes query a first class concept, embedded directly in NET
In this review of LINQ, we first looked at the current methods for performing object queries, including
basic data filtering, grouping, and sorting We looked at the shortcomings of current object query
tech-niques, including the requirement for developers to not only define what the query should do, but also exactly how it should do it Additionally, we looked at how even simple operations can result in highly complex code that can be difficult to read and maintain
Next, we began looking at the three basic types of LINQ — LINQ to Objects, LINQ to XML, and LINQ
to SQL Each flavor of LINQ uses the same basic query syntax to dramatically simplify the querying
of Objects, XML or SQL We looked at how you can use the basic SQL-like query syntax for selection,
filtering, and grouping This query syntax is clean and easily readable, and also includes many of the
same operator features as SQL
We also looked at the basic O/R mapper that is included with LINQ to SQL The O/R mapper makes it easy to create CLR objects that represent SQL structures such as Tables, Views, and Stored Procedures
Once the CLR objects are created, LINQ can be used to query the objects
Finally we looked at how using LINQ to SQL, you can easily change the data in your database, using
generated SQL statements, or using custom Stored Procedures