1. Trang chủ
  2. » Công Nghệ Thông Tin

ASP.NET 4 Unleased - p 100 pdf

10 260 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Tiêu đề Data Access With LINQ To SQL
Thể loại Bài báo
Định dạng
Số trang 10
Dung lượng 495,22 KB

Các công cụ chuyển đổi và chỉnh sửa cho tài liệu này

Nội dung

When you build a query using LINQ to SQL, on the hand, the query does not execute until you start enumerating the results.. Consider the following valid LINQ to SQL query: var query = tM

Trang 1

Performing Standard Database Commands with

LINQ to SQL

In this section, you learn how to use LINQ to SQL as a replacement for working directly

with SQL We start by discussing how LINQ to SQL queries differ from standard LINQ

queries Next, we examine how you can perform standard database queries and commands

using LINQ to SQL such as Select, Update, Insert, and Delete commands We’ll also discuss

how you can create dynamic queries with LINQ Finally, we investigate the important

topic of how you can debug LINQ to SQL queries

LINQ to Objects Versus LINQ to SQL

You can use standard LINQ (LINQ to Objects) with any object that implements the

IEnumerable<T> interface interface> You can use LINQ to SQL, on the other hand, with

any object that implements the IQueryable<T> interface Standard LINQ is implemented

with the extension methods exposed by the System.Linq.Enumerable class LINQ to SQL,

on the other hand, uses the extension methods exposed by the System.Linq.Queryable

class Why the difference?

When you build a query using standard LINQ, the query executes immediately When you

build a query using LINQ to SQL, on the hand, the query does not execute until you start

enumerating the results In other words, the query doesn’t execute until you use a foreach

loop to walk through the query results

Consider the following valid LINQ to SQL query:

var query = tMovie.Where(m => m.Director == “Steven Spielberg”)

.OrderBy( m => m.BoxOfficeTotals ) .Select( m => m.Title );

This query returns a list of movies directed by Steven Spielberg in order of the movie box

office totals You want LINQ to SQL to execute this query against the database in the most

efficient way possible In particular, you don’t want LINQ to SQL to execute each method

independently; you want LINQ to SQL to execute one smart database query

When executing this query, it would be bad if LINQ to SQL (1) grabbed all the Movie

records that were directed by Steven Spielberg; (2) sorted the records; and then (3)

discarded all the columns except the Title column You want LINQ to SQL to perform one

smart database query that looks like this:

SELECT [t0].[Title] FROM [Movie] AS [t0] WHERE [t0].[Director] = @p0

ORDER BY [t0].[BoxOfficeTotals]

This SQL query is the exact query that LINQ to SQL performs LINQ to SQL defers

execu-tion of a query until you start iterating through the results of the query When you build a

query, you are in reality building a representation of the query Technically, you are

build-ing an expression tree That way, LINQ to SQL can translate the query into one efficient

SQL statement when it comes time to actually execute it

Trang 2

To summarize, when you build a query using standard LINQ, the query executes as you

build it When you build a query using LINQ to SQL, you are building a representation of

a query that doesn’t actually execute until you start iterating through the query’s results

NOTE

When people first start using LINQ, they always worry about how they can build the

equivalent of dynamic SQL commands Later in this section, you learn how to create

dynamic LINQ to SQL queries by dynamically building expression trees

Selecting with LINQ to SQL

If you want to perform a simple, unordered select, you can use the following query

(assuming that you have an entity named Movie that represents the Movies database table):

MyDatabaseDataContext db = new MyDatabaseDataContext();

var query = db.Movies;

No LINQ extension methods are used in this query All the items are retrieved from the

Movies table If you prefer, you can use query syntax instead of method syntax, like this:

MyDatabaseDataContext db = new MyDatabaseDataContext();

var query = from m in db.Movies select m;

Selecting Particular Columns

If you want to select only particular columns, and not all the columns, from a database

table, you can create an anonymous type on-the-fly, like this:

MyDatabaseDataContext db = new MyDatabaseDataContext();

var query = db.Movies.Select( m => new {m.Id, m.Title} );

The expression new {m.Id, m.Title} creates an anonymous type that has two properties:

Id and Title The names of the properties of the anonymous type are inferred If you

want to be more explicit, or if you want to change the names of the anonymous type’s

properties, you can construct your query like this:

MyDatabaseDataContext db = new MyDatabaseDataContext();

var query = db.Movies.Select( m => new {Id = m.Id, MovieTitle = m.Title} );

Selecting Particular Rows

If you want to select only particular rows from a database table and not all the rows, you

can take advantage of the Where() method The following LINQ to SQL query retrieves all

the movies directed by George Lucas with box office totals greater than $100,000:

Trang 3

MyDatabaseDataContext db = new MyDatabaseDataContext();

var query = db.Movies

.Where( m => m.Director == “George Lucas” && m.BoxOfficeTotals > 100000.00m)

.Select( m => new {m.Title, m.Director, m.BoxOfficeTotals});

Remember to always call the Where() method before the Select() method You need to

filter your data with Where() before you shape it with Select()

Selecting Rows in a Particular Order

You can use the following methods to control the order in which rows are returned from a

LINQ to SQL query:

OrderBy()—Returns query results in a particular ascending order

OrderByDescending()—Returns query results in a particular descending order

ThenBy()—Returns query results using in an additional ascending order

ThenByDescending()—Returns query results using an additional descending order

The OrderBy() and OrderBy() methods return an IOrderedQueryable<T> collection

instead of the normal IQueryable<T> collection type collection type> If you want to

perform additional sorting, you need to call either the ThenBy() or ThenByDescending()

method

The following query returns movies in order of release date and then in order of box

office totals:

MyDatabaseDataContext db = new MyDatabaseDataContext();

var query = db.Movies.OrderBy(m=>m.DateReleased).ThenBy(m=>m.BoxOfficeTotals);

Executing this LINQ to SQL query executes the following SQL query:

SELECT

[t0].[Id],

[t0].[CategoryId],

[t0].[Title],

[t0].[Director],

[t0].[DateReleased],

[t0].[InTheaters],

[t0].[BoxOfficeTotals],

[t0].[Description]

FROM [dbo].[Movie] AS [t0]

ORDER BY [t0].[DateReleased], [t0].[BoxOfficeTotals]

Selecting a Single Row

If you want to select a single row from the database, you can use one of the following two

query methods:

Trang 4

Single()—Selects a single record

SingleOrDefault()—Selects a single record or a default instance

The first method assumes there is at least one element to be returned (If not, you get an

exception.) The second method returns null (for a reference type) when no matching

element is found

Here’s a sample query that retrieves the only record where the movie Id has the value 1:

MyDatabaseDataContext db = new MyDatabaseDataContext();

Movie result = db.Movies.SingleOrDefault(m => m.Id == 1);

if (result != null)

Response.Write(result.Title);

This query returns a single object of type Movie If there is no movie record that matches

the query, result is null, and the value of the Movie Title property is not written

NOTE

When you execute a query that returns a single result, there is no deferred query

exe-cution The LINQ query is translated into a SQL command and executed immediately

Performing a LIKE Select

You can perform the equivalent of a LIKE Select with LINQ to SQL in several ways First,

you can use String methods such as Length, Substring, Contains, StartsWith, EndsWith,

IndexOf, Insert, Remove, Replace, Trim, ToLower, ToUpper, LastIndexOf, PadRight, and

PadLeft with LINQ to SQL queries For example, the following query returns all movies

that start with the letter t:

MyDatabaseDataContext db = new MyDatabaseDataContext();

var query = db.Movies.Where(m=>m.Title.StartsWith(“t”));

Behind the scenes, this query is translated into a SQL query that uses the LIKE operator:

SELECT [t0].[Id], [t0].[CategoryId], [t0].[Title], [t0].[Director],

[t0].[DateReleased], [t0].[InTheaters], [t0].[BoxOfficeTotals], [t0].[Description]

FROM [dbo].[Movie] AS [t0]

WHERE [t0].[Title] LIKE @p0

An alternative, more flexible way to make LIKE queries is to use the

System.Data.Linq.SqlClient.SqlMethods.Like() method:

MyDatabaseDataContext db = new MyDatabaseDataContext();

var query = db.Movies.Where(m=>SqlMethods.Like(m.Title, “t%”));

Using the SqlMethods.Like() method is more flexible than using the standard String

methods because you can add as many wildcards to the match pattern as you need

Trang 5

NOTE

The SqlMethods class also contains a number of useful methods for expressing the

SQL DateDiff() function in a LINQ to SQL Query

Paging Through Records

Doing database paging right when working with ADO.NET is difficult The SQL language

is not designed to make it easy to retrieve a range of records Doing database paging using

LINQ to SQL queries, on the other hand, is trivial

You can take advantage of the following two query methods to perform database paging:

Skip()—Enables you to skip a certain number of records

Take()—Enables you to take a certain number of records

For example, the class in Listing 20.18 contains a method named SelectedPaged() that

gets a particular page of movie records from the Movie database table

LISTING 20.18 Standard\App_Code\Movie.cs

using System;

using System.Collections.Generic;

using System.Linq;

using System.Data.Linq;

public partial class Movie

{

public static IEnumerable<Movie> Select()

{

MyDatabaseDataContext db = new MyDatabaseDataContext();

return db.Movies;

}

public static IEnumerable< Movie> SelectPaged

(

int startRowIndex,

int maximumRows

)

{

return Select().Skip(startRowIndex).Take(maximumRows);

}

public static int SelectCount()

{

Trang 6

return Select().Count();

}

}

I’m assuming, in the case of Listing 20.18, that you have already created a Movie entity by

using the LINQ to SQL Designer The Movie class in Listing 20.18 is a partial class that

extends the existing Movie class generated by the Designer

The ASP.NET page in Listing 20.19 illustrates how you can use the Movie class with the

ObjectDataSource control to page through movie records

LISTING 20.19 Standard\ShowPagedMovies.aspx

<%@ Page Language=”C#” %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”

“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml”>

<head runat=”server”>

<title>Show Paged Movies</title>

</head>

<body>

<form id=”form1” runat=”server”>

<div>

<asp:GridView

id=”grdMovies”

DataSourceID=”srcMovies”

AllowPaging=”true”

PageSize=”5”

Runat=”server” />

<asp:ObjectDataSource

id=”srcMovies”

TypeName=”Movie”

SelectMethod=”SelectPaged”

SelectCountMethod=”SelectCount”

EnablePaging=”true”

Runat=”server” />

</div>

</form>

</body>

</html>

Trang 7

Joining Records from Different Tables

You can perform joins when selecting entities just like you can when joining database

tables For example, imagine that you want to join the Movie and MovieCategory tables

on the CategoryId key Assuming that you have both a Movie and MovieCategory entity,

you can use the following query:

MyDatabaseDataContext db = new MyDatabaseDataContext();

var query = db.MovieCategories

.Join(db.Movies, c=>c.Id, m=>m.CategoryId, (c,m)=>new {c.Id,c.Name,m.Title});

This LINQ query gets translated into the following SQL command:

SELECT [t0].[Id], [t0].[Name], [t1].[Title]

FROM [dbo].[MovieCategory] AS [t0]

INNER JOIN [dbo].[Movie] AS [t1] ON [t0].[Id] = [t1].[CategoryId]

This query performs an inner join If you want to perform an outer join, the syntax is a

little more complicated Here’s how you do a left outer join using query syntax:

MyDatabaseDataContext db = new MyDatabaseDataContext();

var query = from c in db.MovieCategories

join m in db.Movies

on c.Id equals m.CategoryId into cm

from m in cm.DefaultIfEmpty()

select new { c.Id, c.Name, m.Title };

This LINQ query gets translated into the following SQL SELECT:

SELECT [t0].[Id], [t0].[Name], [t1].[Title] AS [value]

FROM [dbo].[MovieCategory] AS [t0]

LEFT OUTER JOIN [dbo].[Movie] AS [t1] ON [t0].[Id] = [t1].[CategoryId]

As an alternative to using joins, consider taking advantage of the associations between

entities Remember that the following type of query is perfectly valid:

MyDatabaseDataContext db = new MyDatabaseDataContext();

var category = db.MovieCategories.Single( c => c.Name == “Drama” );

var query = category.Movies;

Caching Records

Getting caching to work with LINQ to SQL is a little tricky Remember that a LINQ to SQL

query represents a query expression and not the actual query results The SQL command is

not executed, and the results are not retrieved until you start iterating through the query

results

For example, imagine that you declare the following ObjectDataSource control in a page

and that this ObjectDataSource control represents a class that returns a LINQ to SQL

query:

Trang 8

<asp:ObjectDataSource

id=”srcMovies”

TypeName=”Movie”

SelectMethod=”Select”

EnableCaching=”true”

CacheDuration=”9999”

Runat=”server” />

This ObjectDataSource has been set up to cache its results Its EnableCaching and

CacheDuration properties are set However, what gets cached here is the query expression

and not that actual query results The SQL select statement that corresponds to the LINQ

to SQL query executes every time the page is requested

To get caching to work, we need to force the query results and not the query into the cache

The Movie class in Listing 20.20 contains a SelectCached() method that successfully caches

database data with a LINQ to SQL query

LISTING 20.20 Standard\App_Code\Movie.cs

using System;

using System.Web;

using System.Collections.Generic;

using System.Linq;

using System.Data.Linq;

public partial class Movie

{

public static IEnumerable<Movie> Select()

{

MyDatabaseDataContext db = new MyDatabaseDataContext();

return db.Movies;

}

public static IEnumerable<Movie> SelectCached()

{

HttpContext context = HttpContext.Current;

List<Movie> movies = (List<Movie>)context.Cache[“Movies”];

if (movies == null)

{

movies = Select().ToList();

context.Cache[“Movies”] = movies;

context.Trace.Warn(“Retrieving movies from database”);

}

return movies;

}

}

Trang 9

The SelectCached() method attempts to retrieve movie records from the cache If the

records can’t be retrieved from the cache, the movies are retrieved from the database The

vast majority of the time, the movies are retrieved from the cache

The trick here is to use the ToList() method to convert the IEnumerable<Movie> into a

List<Movie> When the List<Movie> is created, the SQL query associated with the LINQ

to SQL query is executed and the actual data is returned

You can use the class in Listing 20.20 with the ASP.NET page in Listing 20.21

LISTING 20.21 Standard\ShowCachedMovies.aspx

<%@ Page Language=”C#” Trace=”true” %>

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”

“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>

<html xmlns=”http://www.w3.org/1999/xhtml”>

<head runat=”server”>

<title>Show Cached Movies</title>

</head>

<body>

<form id=”form1” runat=”server”>

<div>

<asp:GridView

id=”grdMovies”

DataSourceID=”srcMovies”

Runat=”server” />

<asp:ObjectDataSource

id=”srcMovies”

TypeName=”Movie”

SelectMethod=”SelectCached”

Runat=”server” />

</div>

</form>

</body>

</html>

The ObjectDataSource in Listing 20.21 does not have caching enabled All the caching

happens in the Data Access layer (the Movie class)

Trang 10

Inserting with LINQ to SQL

There are two steps to adding and inserting a new record with LINQ to SQL First, you

need to use the InsertOnSubmit() method to add an entity to an existing table Next, you

call SubmitChanges() on the DataContext to execute the SQL INSERT statement against the

database

The class in Listing 20.22 illustrates how you can write a method to add a new record into

the Movie database table

LISTING 20.22 Standard\App_Code\Movie.cs

using System;

using System.Web;

using System.Collections.Generic;

using System.Linq;

using System.Data.Linq;

public partial class Movie

{

public static int Insert(Movie movieToInsert)

{

MyDatabaseDataContext db = new MyDatabaseDataContext();

db.Movies.InsertOnSubmit( movieToInsert );

db.SubmitChanges();

return movieToInsert.Id;

}

public static IEnumerable<Movie> Select()

{

MyDatabaseDataContext db = new MyDatabaseDataContext();

return db.Movies.OrderByDescending(m=>m.Id);

}

}

The Movie class includes an Insert() method that inserts a new movie into the database

The Insert() method returns an integer that represents the identity value of the new

record As soon as SubmitChanges() is called, the Id property is updated with the new

identity value from the database

NOTE

I’m assuming in this section that you have used the LINQ to SQL Designer to create

entities for the Movie and MovieCategories database tables

Ngày đăng: 06/07/2014, 18:20

TỪ KHÓA LIÊN QUAN

TÀI LIỆU CÙNG NGƯỜI DÙNG

TÀI LIỆU LIÊN QUAN