Tải bản đầy đủ (.pdf) (16 trang)

Using LINQ to Entities

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (345.89 KB, 16 trang )

Chapter 19
Using LINQ to Entities
After completing this chapter, you will be able to:

Create LINQ queries that access content from an Entity Framework data model

Call database-level functions from LINQ queries

Understand how LINQ treats entities differently from other data sources
The Entity Framework (EF) is a model-based interface between your application and an ex-
ternal database. As discussed earlier in this book, the Framework presents logical, database-
centric data content in a conceptual form expressed through object instances. This focus on
objects makes the Entity Framework a great match for LINQ.
The LINQ to Entities provider brings the world of entities and LINQ queries together. This
chapter introduces this EF-centric LINQ provider, a system that takes advantage of the Entity
Framework’s model-focused data and LINQ’s capability to develop native language queries
that target entities and their properties.
Note
The exercises in this chapter all use the same sample project, a tool that makes queries
using LINQ to Entities. Although you can run the application after each exercise, the expected
results for the full application might not appear until you complete all exercises in the chapter.
Understanding the LINQ to Entities Provider
The ObjectSet(Of TEntity) and ObjectQuery(Of T) classes—the two key collection-style base
classes used in the Entity Framework—are ready to use in LINQ queries. Both collection
types implement IEnumerable(Of T) and IQueryable(Of T), the same interfaces that LINQ
requires to enable query operations on a collection. Any entity collection exposed by an EF
context or built from an ObjectQuery instance—such as a query processed with Entity SQL—
can form the basis of a LINQ query.
EF entities referenced in a LINQ query expose properties that are available for projection,
filtering, sorting, and other LINQ operations. LINQ to Entities queries are much cleaner than
their LINQ to DataSet counterparts because each entity property already expresses its


model-defined data type.
Dwonloaded from: iDATA.ws
316
Like LINQ, the Entity Framework is a delayed-processing system. The actual retrieval of data
(from the database) does not occur at the time you build a data query; instead, data is pro-
cessed and returned to your application only when you attempt to reference specific entities
and properties. When you write an EF query, the Framework prepares a T-SQL query (when
SQL Server is used as the backend database) that it runs on the database server to obtain the
desired records. That database action occurs only when you access the results of the query
statement.
When you craft LINQ queries that involve EF objects, the application employs this same form
of delayed processing. The clauses in a LINQ query—and ultimately the extension methods
and lambda expressions that make up a LINQ expression tree—translate into SQL statements
and clauses that are played out on the data server. For this reason, all LINQ to Entities queries
can involve only objects and data elements that can be represented within a remotely run SQL
statement. While other LINQ providers can be mixed—Chapter 18, “Using LINQ to DataSet,”
combined LINQ to Objects and LINQ to DataSet content—LINQ to Entities imposes restric-
tions on the type of data involved in the queries.
Note
One of the exercises in this chapter will demonstrate one way that LINQ to Entities can be
used indirectly with other forms of LINQ.
Some LINQ features available with other LINQ providers are not supported by LINQ to
Entities. Projections, comparisons, and joins that are based on a locally-defined function
won’t work in LINQ to Entities because the local function cannot be represented in a SQL
query running elsewhere. Also, the Last, SkipWhile, and TakeWhile extension methods are not
available; Skip and Take (in both their SQL-style and extension method forms) will work.
Writing Queries with LINQ to Entities
As with all LINQ providers, the general structure of LINQ to Entities queries varies only a little
from the LINQ to Objects standard. In fact, looking at a LINQ to Entities query, it’s hard to
see that it isn’t working with standard .NET objects. The telltale sign is the use of an active

Entity Framework object context, either as a direct source for entities or as a way to run an
ObjectQuery that will feed data into LINQ.
Dwonloaded from: iDATA.ws
Chapter 19 Using LINQ to Entities
317
Here is a query that returns some properties from a Customer entity:
C#
using (SalesOrderEntities context = new SalesOrderEntities(connectionString))
{
var results = from cu in context.Customers
orderby cu.FullName
select new { CustomerID = cu.ID, CustomerName = cu.FullName };
}
Visual Basic
Using context As New SalesOrderEntities(connectionString)
Dim results = From cu In context.Customers
Order By cu.FullName
Select CustomerID = cu.ID, CustomerName = cu.FullName
End Using
Most of the standard LINQ clauses are included, in both their LINQ expression and their
extension method/lambda expression forms, including Where, Join, Group By, and so on.
As far as the LINQ syntax is concerned, LINQ to Entities is pretty full-featured. But there are
limitations. Some, such as the inability to use the SkipWhile and TakeWhile extension meth-
ods, were listed previously. Others follow this general rule: If it can’t be converted easily into a
storage-level function, it can’t be used directly in LINQ to Entities.
Querying with LINQ to Entities: C#
Note
This exercise parallels the exercise found in Chapter 18. It is nearly identical in functionality
and purpose, but uses LINQ to Entities instead of LINQ to DataSet to process database content.
1. Open the “Chapter 19 CSharp” project from the installed samples folder. The project

includes three Windows.Forms classes: OrderViewer, StatesByYear, and Switchboard. This
example focuses on the OrderViewer form.
Dwonloaded from: iDATA.ws
318
Microsoft ADO.NET 4 Step by Step
2. Open the source code view for the General class. Locate the GetConnectionString func-
tion; this is a routine that uses a SqlConnectionStringBuilder to create a valid connection
string to the sample database. It currently includes the following statements:
sqlPortion.DataSource = @"(local)\SQLExpress";
sqlPortion.InitialCatalog = "StepSample";
sqlPortion.IntegratedSecurity = true;
Adjust these statements as needed to provide access to your own test database.
3. Open the source code view for the OrderViewer form. Locate the ActView_Click event
handler. This routine displays a list of orders, either for all customers in the database or
for a specific customer by ID number. Just after the “Retrieve all customer orders” com-
ment, add the following statement:
var result = from cu in OrderContext.Customers
from ord in OrderContext.OrderEntries
where cu.ID == ord.Customer
orderby cu.FullName, ord.ID
select new { CustomerID = cu.ID,
CustomerName = cu.FullName,
OrderID = ord.ID,
OrderDate = ord.OrderDate,
OrderTotal = ord.Total,
ord.StatusCode };
This query combines two entity collections, Customers and OrderEntries, both of which
are members of the SalesOrderEntities class, a derived Entity Framework context. It
forms implicit inner joins between the entity collections via the where clause and per-
forms a sorted projection of fields from each source table.

4. Just after the “Add in the status code” comment, add the following query:
var result2 = from cu in result.ToArray()
from sts in statusTable
where cu.StatusCode == sts.Code
select new { cu.CustomerID, cu.CustomerName, cu.OrderID,
OrderStatus = sts.Description, cu.OrderDate, cu.OrderTotal };
This query extends the original query by linking in a local object collection. This is nec-
essary because LINQ to Entities cannot transmit an entire local collection to the data-
base for SQL processing. Instead, the original query must be converted into a regular
.NET collection, as is done with the result.ToArray() clause. The original query is pro-
cessed at that moment, and the results are placed in a standard anonymous array. The
result2 query is actually doing its work using LINQ to Objects.
Dwonloaded from: iDATA.ws
Chapter 19 Using LINQ to Entities
319
5. Run the program. When the Switchboard form appears, click Order Viewer. When the
OrderViewer form appears, select the Include All Customers option and then click View.
The grid displays content from the Customer and OrderEntries entities, plus a column
from the local statusTable collection.
Querying with LINQ to Entities: Visual Basic
Note
This exercise parallels the exercise found in Chapter 18. It is nearly identical in functionality
and purpose, but uses LINQ to Entities instead of LINQ to DataSet to process database content.
1. Open the “Chapter 19 VB” project from the installed samples folder. The project in-
cludes three Windows.Forms classes: OrderViewer, StatesByYear, and Switchboard. This
example focuses on the OrderViewer form.
2. Open the source code view for the General module. Locate the GetConnectionString
function; this is a routine that uses a SqlConnectionStringBuilder to create a valid con-
nection string to the sample database. It currently includes the following statements:
sqlPortion.DataSource = "(local)\SQLExpress"

sqlPortion.InitialCatalog = "StepSample"
sqlPortion.IntegratedSecurity = True
Adjust these statements as needed to provide access to your own test database.
Dwonloaded from: iDATA.ws
320
Microsoft ADO.NET 4 Step by Step
3. Open the source code view for the OrderViewer form. Locate the ActView_Click event
handler. This routine displays a list of orders, either for all customers in the database or
for a specific customer by ID number. Just after the “Retrieve all customer orders” com-
ment, add the following statement:
Dim result = From cu In OrderContext.Customers,
ord In OrderContext.OrderEntries
Where cu.ID = ord.Customer
Select CustomerID = cu.ID,
CustomerName = cu.FullName,
OrderID = ord.ID,
OrderDate = ord.OrderDate,
OrderTotal = ord.Total,
ord.StatusCode
Order By CustomerName, OrderID
This query combines two entity collections, Customers and OrderEntries, both of which
are members of the SalesOrderEntities class, a derived Entity Framework context. It
forms implicit inner joins between the entity collections via the Where clause and per-
forms a sorted projection of fields from each source table.
4. Just after the “Add in the status code” comment, add the following query:
Dim result2 = From cu In result.ToArray(), sts In statusTable
Where cu.StatusCode = sts.Code
Select cu.CustomerID, cu.CustomerName, cu.OrderID,
OrderStatus = sts.Description, cu.OrderDate, cu.OrderTotal
This query extends the original query by linking in a local object collection. This is nec-

essary because LINQ to Entities cannot transmit an entire local collection to the database
for SQL processing. Instead, the original query must be converted into a regular .NET
collection, as is done with the result.ToArray() clause. The original query is processed
at that moment and the results are placed in a standard anonymous array. The result2
query is actually doing its work using LINQ to Objects.
5. Run the program. When the Switchboard form appears, click Order Viewer. When the
OrderViewer form appears, select the Include One Customer By ID option, enter 1 in
the Customer ID field and then click View.
Dwonloaded from: iDATA.ws

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×