To clarify, the following examples show both the C# LINQ query: var customers = from cust in custList where cust.FirstName.StartsWith"M" select cust; and the VB LINQ query: Dim cus
Trang 1options found after clicking the arrow button to expand Database Tools and then selecting Table And Database Designers is “Prevent saving changes that require table re-creation.”
VS will not allow you to save a foreign key change to existing tables However, by unchecking “Prevent saving changes that require table re-creation,” you’ll be able to save foreign key changes to an existing table
As with so many other features of VS, there are literally dozens of database settings; most are intuitive if you already understand SQL Server Other options differ, depending on the version of VS you have, and your Options screen might not look the same as Figure 7-10 Now that you know how to create databases, tables, and stored procedures, you’ll need
to know how to use your database from code The rest of this chapter shows you how to use LINQ to work with data First, we’ll look at the basic syntax of LINQ through LINQ
to Objects and then follow with working with SQL Server through LINQ to SQL
Learning Language Integrated Query (LINQ)
LINQ is a set of features built into programming languages, such as C# and VB, for working with data It’s called Language Integrated Query because the LINQ syntax is part of the language, as opposed to being a separate library This section will show you the essentials of LINQ with LINQ to Objects, a LINQ provider for querying in-memory collections of objects The great news is that the syntax you learn here is not only
applicable to LINQ to Objects, but to all other LINQ providers, such as LINQ to SQL and more, that you’ll encounter
The examples in this chapter will use a Console project for simplicity Later chapters will show you how to display data in desktop and Web applications If you want to run the code in this chapter, you can create a Console application and type the examples into the
Main method, as has been explained in each previous chapter of this book
Querying Object Collections with LINQ
One way to use LINQ is via LINQ to Objects, which allows you to query collections
of objects You can use LINQ to query any collection that implements the IEnumerable
interface As you may recall, we discussed interfaces in Chapter 4; now you can see one more example of how important interfaces are to NET development Listing 7-2 shows
a program that uses LINQ to query a collection The object type is a custom class, named
Customer The Main method creates a generic list of Customer and uses a LINQ query to extract the Customer objects that have a first name that starts with the letter M.
Trang 2Listing 7-2 A program demonstrating how to make a LINQ to objects query
C#:
using System;
using System.Collections.Generic;
using System.Linq;
class Customer
{
public string FirstName { get; set; }
public string LastName { get; set; }
}
class Program
{
static void Main(string[] args)
{
List<Customer> custList = new List<Customer>
{
new Customer
{
FirstName = "Joe",
LastName = "Zev"
},
new Customer
{
FirstName = "May",
LastName = "Lee"
},
new Customer
{
FirstName = "Meg",
LastName = "Han"
}
};
var customers =
from cust in custList
where cust.FirstName.StartsWith("M")
select cust;
foreach (var cust in customers)
{
Console.WriteLine(cust.FirstName);
}
Trang 3Console.ReadKey();
}
}
VB:
Class Customer
Property FirstName As String
Property LastName As String
End Class
Module Module1
Sub Main()
Dim custList As New List(Of Customer) From {
New Customer With
{
FirstName = "Joe",
LastName = "Zev"
},
New Customer With
{
FirstName = "May",
LastName = "Lee"
},
New Customer With
{
FirstName = "Meg",
LastName = "Han"
}
}
Dim customers =
From cust In custList
Where cust.FirstName.StartsWith("M") Select cust
For Each cust In customers
Console.WriteLine(cust.FirstName) Next
Console.ReadKey()
End Sub
End Module
Trang 4Both the C# and VB examples from Listing 7-2 contain similar LINQ queries To
clarify, the following examples show both the C# LINQ query:
var customers =
from cust in custList
where cust.FirstName.StartsWith("M")
select cust;
and the VB LINQ query:
Dim customers =
From cust In custList
Where cust.FirstName.StartsWith("M")
Select cust
The customers variable in the LINQ queries references a new collection that holds the
result of running the LINQ query, which contains all of the customers where the first letter
of the FirstName property is the letter M The from clause specifies the range variable
that you name, cust is the name I chose, and the collection object to query, custList, was
created and populated in the previous line of code The range variable is what you use to
specify parameters of the LINQ query In the preceding example, we use the where clause
to filter the results of the query This where clause calls the StartsWith method on each
FirstName property of the cust range variable to specify the filter.
The select clause specifies that each individual customer object is returned into our
new customers collection, which we declared as type var (Dim in VB), which means our
customers variable winds up being whatever collection type is returned from our LINQ
query This also means that the resulting customers collection will contain zero or more
Customer type instances, depending on the filter we specified and whether our custList
contained any Customer objects in the first place as a result of the Select cust portion of
the LINQ statement The select clause for C# queries is required, but the select clause for
VB queries is optional and will return the range variable instance if omitted
What our LINQ statement is essentially saying in English is “Create a new collection
object and assign it to our variable customers (we don’t really care what type of object
customers turns out to be as long as we can use it later), then go through every object in
our previously defined and loaded custList collection, selecting only the ones that have for their FirstName property a string that begins with the letter M, and ignore all the rest, then
take the ones that match this filter and stuff them into whatever collection you created for
me earlier that you assigned to my variable customers.”
Trang 5Creating a LINQ Projection with Anonymous Types
You can customize what is returned by the select clause by using what is called an
anonymous type This customization of return values is called a projection Anonymous
types facilitate custom projections, allowing you to return the results of a LINQ query
in a form that you specify without needing to declare a new type ahead of time Here’s
an example of creating a query that declares a new anonymous type for combining the
FirstName and LastName properties of Customer into a variable, FullName, that is created
as a string-type property associated with the object returned into cust in the foreach
statement:
C#:
var customers =
from cust in custList
where cust.FirstName.StartsWith("M")
select new
{
FullName =
cust.FirstName + " " +
cust.LastName
};
foreach (var cust in customers)
{
Console.WriteLine(cust.FullName);
}
VB:
Dim customers =
From cust In custList
Where cust.FirstName.StartsWith("M")
Select New With
{
.FullName =
cust.FirstName & " " &
cust.LastName
}
For Each cust In customers
Console.WriteLine(cust.FullName)
Next
In both the C# and VB select clauses you see a new statement (New With in VB) that defines the anonymous type The new anonymous type has a single property, FullName, that is the combination of FirstName and LastName in Customer, but the new type will
Trang 6only have a FullName property Notice how the foreach loop uses the FullName property,
instead of the FirstName property from Listing 7-2 The beauty of this anonymous type
is that we don’t really care what type of object is generated for us by the LINQ query, as
long as that object has the new property associated with it that we specified, FullName in
this case, which it does
The variable, cust, in the preceding listing is used in two different scopes: the LINQ
query and the foreach statement Although the identifier, cust, is the same, the two usages
are separate instances Although you might not use the same practice in your own code,
I wanted to demonstrate this so that you can see that range variables, such as cust, are
scoped to the query they are defined in
Another nuance of the preceding code is that cust, in the foreach loop, is not type
Customer. Rather, it is an instance of the anonymous type created by the projection (select
clause) of the LINQ query Therefore, FullName is the only property each anonymous
type instance, cust, contains.
Using LINQ to Sort Collection Results
Another common task you’ll want to perform with data is sorting so that you can put
objects in a certain order The following example modifies the example from Listing 7-2
to sort items from the customer List in descending order:
C#:
var customers =
from cust in custList
orderby cust.FirstName descending
select cust;
VB:
Dim customers =
From cust In custList
Order By cust.FirstName Descending
Select cust
The orderby (Order By in VB) clause specifies the properties to sort on This example
sorts the list by the FirstName property in descending order.
This was a quick taste of what you could do with LINQ, and there is much more
In fact, I wrote an entire book on the subject titled LINQ Programming (McGraw-Hill/
Professional, 2008) The remaining section of this book takes what you’ve learned here
and expands, showing you more samples of LINQ queries The difference will be that you will be working with SQL Server data instead of in-memory objects
Trang 7Handling Data with LINQ to SQL
The LINQ to SQL provider allows you to communicate with SQL Server databases There are many other types of providers, such as LINQ to Entities for generic databases (which includes SQL Server), LINQ to XML for XML data sources, and LINQ to Oracle for Oracle databases The preceding section showed you how to use the in-memory provider, LINQ to Objects However, LINQ to SQL is the easiest database provider to learn and ships with VS Once you learn LINQ to SQL, the journey to other providers is easier The following sections will show you how to set up LINQ to SQL, perform queries, and modify data
Setting Up LINQ to SQL
Setting up LINQ to SQL involves running the LINQ to SQL Wizard and adding classes and methods Behind the scenes, LINQ to SQL generates code, saving you a lot of work
The result of setting up LINQ to SQL is that you will have a data model, which is an
environment with classes that you can use to query and modify database data and call methods for invoking stored procedures
Before setting up LINQ to SQL, you’ll need to create a project (a Console project for the purposes of this chapter) See Chapter 5 if you need a refresher on how to set up
a Console project Select Add | New Item, select LINQ to SQL Classes, name the file
MyShop.dbml, and click Add This will show you the LINQ to SQL Designer, with two
surfaces for classes and methods Figure 7-11 shows the LINQ to SQL Designer with
a couple of classes and a method
Figure 7-11 The LINQ to SQL Designer