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

ASP.NET 4.0 in Practice phần 2 ppsx

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 (15.34 MB, 50 trang )

25TECHNIQUE 2 Form validation
mind that they’re activated only if a value is present in the field that the validator is
associated with. Remember, you always need to include a
RequiredFieldValidator
if
you want to make sure an empty value won’t bypass your controls.
Validator controls use adaptive rendering, so they’ll send client-side JavaScript code
to recognized browsers. You need to access the
IsValid
property of the
Page
class to
ensure that validation is also done server side, as shown in the following listing.
Markup:

Your first name:
<asp:textbox runat="server" ID="FirstName" />
<asp:RequiredFieldValidator runat="server" ID="FirstNameValidator"

ControlToValidate="FirstName"

ErrorMessage="First name is required"

Text="*" />
<br />

<asp:ValidationSummary ID="MyValidationSummary" runat="server"
HeaderText="You need to check:" />

C#:
void HandleSubmit(Object sender, EventArgs e)


{
if (Page.IsValid)
{

}
}
VB:
Sub HandleSubmit(sender as Object, e as EventArgs)
If Page.IsValid then#3

End If
End Sub
ValidationSummary
has a boolean property called
ShowMessageBox
that pops up an
alert message when the validation isn’t passed. If you set this property to
true
and
ShowSummary
to
false
, you can display only this alert. Default values are respectively
false
and
true
.
Figure 1.10 shows you the results of the code in listing 1.3 if the user has omitted
the value for the field “Your first name” and PostBack has been invoked.
Other controls in this group do about the same thing; the difference is only in the

property you will use. If you need more examples of validator controls, check out the
ones included in the
MSDN documentation at
library/aa310913(VS.71).aspx.
Listing 1.3 Validation controls at work
Control to
act against
Summary of
validation
errors
Collection
to bind to
Your code
logic here

26 CHAPTER 1 Getting acquainted with ASP.NET 4.0
DISCUSSION
Input validation is a key factor in today applications. Both the client-side and server-
side validation offered by validator controls in Web Forms is a killer feature for web
applications, and you get it by default. It’s just one of the free services the
ASP.NET
infrastructure lets you use to enhance your UI.
Now that you’ve validated the form, the next step is to manipulate the page charac-
teristics, such as the header (title, meta, or keywords), style, and
CSS.
Page header, styling, and CSS
Programmatic access to the page header can help when you need to set some proper-
ties via code. A common problem when dealing with a dynamic page is that often the
page is composed of data coming from a database. In situations like this, you need to
set the page headers programmatically. By manipulating page headers you can

dynamically set the title, style sheets, or syndication feeds.
PROBLEM
You need to access the page headers from your code and programmatically set the val-
ues that correspond to the kind of header you’re manipulating.
SOLUTION
Starting with ASP.NET 2.0, you can manipulate page headers if you add a
runat="server"
attribute to the
<head

/>
tag. If you need to set the page title, the
Title
property on the
Page
class lets you access
Page.Header.Title
and programmat-
ically set this information.
Version 4.0 lets you set meta tags for search engines. You have to use the
Page.Keywords
and
Page.Description
properties to set the meta keywords and
description respectively, as in the following listing.
C#:
Page.Title = "My Page title";
Page.Keywords = "list separated by commas";
Page.Description = "Page description, shown by search engines.";
Listing 1.4 Dynamically setting page headers

Figure 1.10 A Web Form
with validator controls. As
you can see, the validator
generates a warning (dis-
played in red, by default)
and blocks the form from
being submitted.
TECHNIQUE 3

27TECHNIQUE 3 Page header, styling, and CSS
VB:
Page.Title = "My Page title"
Page.Keywords = "list separated by commas"
Page.Description = "Page description, shown by search engines."
The strongly typed model provided by the
Page
class is powerful. You can manipulate
the corresponding headers using a simple approach, from anywhere in your page,
before the whole page is rendered. This code is especially helpful when you’re dealing
with dynamic content coming from a database.
Styling and CSS
All web controls use a common approach to styling because they all derive from the
WebControl
class. You can modify some properties directly, using properties like
Back-
Color
,
ForeColor
,
BorderColor

, or
Font
. When you need to apply styles to controls,
it’s always better to rely on a CSS for formatting from a centralized point.
WebControl
(and derived controls, like
Label
and
TextBox
) offers a
CssClass
prop-
erty, which is a string containing the CSS class that you’re going to use. If you’re using
CSS IDs as a way to add style to your markup, you need to take a look at the new features
for
ClientID
that are included in ASP.NET 4.0 (which we’ll discuss in chapter 5). In any
case, it’s better to use CSS classes than CSS IDs; if multiple pieces of markup are being
generated by iteration (such as data coming from a database into a page list), you’ll
probably end up with autogenerated
IDs anyway.
Unfortunately, ASP.NET doesn’t provide a mechanism to register an external CSS
directly. You can always create an instance of the
HtmlLink
class and add the new
control to the
Controls
collection of the
Page.Header
property, as shown in the fol-

lowing listing.
C#:
HtmlLink cssLink = new HtmlLink();
cssLink.Href = "/styles/styles.css";
cssLink.Attributes.Add("rel", "stylesheet");
cssLink.Attributes.Add("type", "text/css");
Page.Header.Controls.Add(cssLink);
VB:
Dim cssLink As New HtmlLink()
cssLink.Href = "/styles/styles.css"
cssLink.Attributes.Add("rel", "stylesheet")
cssLink.Attributes.Add("type", "text/css")
Page.Header.Controls.Add(cssLink)
As previously noted, this technique is useful when you don’t know the path to the CSS
file, and you have to determine it at runtime. An example is when you need to person-
alize a link based on user preference.
Registering RSS feeds
Remember that you can use the code shown in listing 1.5 to add other kinds of
HtmlLink
controls, such as a reference to Internet Explorer (IE) Web Slice or an RSS
(Really Simple Syndication) feed.
Listing 1.5 Registering a CSS

28 CHAPTER 1 Getting acquainted with ASP.NET 4.0
RSS or Atom feeds are quite popular these days in web applications because they
let users subscribe to updates and receive them in their news aggregator. This process
is similar to what mail readers do.
RSS differs from Atom in terms of format, but both
are XML based. You can dynamically register the path to RSS or Atom feeds by using
code similar to that shown in the following listing.

C#:
HtmlLink rssLink = new HtmlLink();
rssLink.Href = "/rss.aspx";
rssLink.Attributes.Add("rel", "alternate");
rssLink.Attributes.Add("type", "application/rss+xml");
Page.Header.Controls.Add(rssLink);
VB:
Dim cssLink As New HtmlLink()
rssLink.Href = "/rss.aspx"
rssLink.Attributes.Add("rel", "alternate")
rssLink.Attributes.Add("type", "application/rss+xml")
Page.Header.Controls.Add(rssLink)
If you’re using Web Slice, you need to set the
rel
attribute to
default-slice
and
type
to
application/x-hatom
. Web Slice is a special feature of IE 8.0+; for more infor-
mation, go to />DISCUSSION
You’ll usually need to generate and add controls at runtime in the page header when
you want to provide additional interactions to users visiting your pages. Syndication
feeds, page title or page description, and dynamic
CSS are used to leverage the
dynamic nature of ASP.NET and let your user get what he needs to fully use your web
application, but with his own personalization.
1.6 Summary
Almost everything we’ve talked about in this chapter applies to all versions of ASP.NET.

That said, ASP.NET 4.0 does introduce some interesting features, but the pillars of this
technology are the same as those that were used in the first version. If you’re relatively
new to
ASP.NET, this chapter should have helped you visualize the big picture sur-
rounding this technology.
ASP.NET is built on top of .NET Framework and gains a lot of its features from this
base. .NET Framework is full of interesting technologies, such as the Entity Frame-
work, WCF, and ADO.NET, and you can leverage them in your web application to
enhance functionalities. If you don’t know about these yet, you’ll find specific exam-
ples of each of them in the upcoming chapters.
Keep in mind that
ASP.NET is built with extensibility as a pillar, so the succeeding
chapters will contain advanced implementations of what you’ve learned in this one.
Listing 1.6 Programmatically adding an RSS feed to the current page
application/atom+
xml for Atom

29Summary
You’ll find concepts like Web Forms, PostBack, ViewState,
HttpRuntime
, and IIS inte-
gration in every new step you’ll take.
This chapter didn’t contain a lot of examples, but don’t worry. In the following
chapters, you’ll find plenty of tips and code to implement the most common scenarios
in web applications.
Now you’re ready for chapter 2. We’re going to delve into an analysis of the data
access options available in .
NET Framework 4.0 and specifically for ASP.NET 4.0.

30

Data access reloaded:
Entity Framework
When databases are in place, accessing data becomes a key concern. The way you
communicate with the database and, more importantly, the way you represent data
inside your application becomes one thing that can shift your application from one
that works to a real success.
You have a lot of options. The first option is to use
ADO.NET objects, like con-
nections, adapters, readers, and datasets. This approach is easy to understand and
enables you to immediately start writing code.
Another option is to use
ADO.NET classes to interact with the database and then
create your own classes (object model) to represent data inside the application.
The initial learning curve with such a pattern is higher compared with the previous
one, but in the long run, this pattern ensures higher maintainability.
This chapter covers

Designing an application

Understanding an ORM

Learning Entity Framework

Reading and updating data with Entity Framework

31Designing an application
The last option is to use an ORM tool, which hides the complexity of using ADO.NET
classes and lets you work only with objects in your application. An ORM tool includes the
best of the previous approaches because it offers immediate and sustained productivity.
Microsoft has developed an

ORM whose name is Entity Framework.
Microsoft touts Entity Framework as its best practice for data access. That’s why we
focus on Entity Framework only in this chapter. If you want to take a look at how to
perform data access using the classic
ADO.NET approach, take a look at appendix A.
Understanding data access using Entity Framework is vital because it lays the foun-
dation for the next chapter and for the rest of the book. We’ll be using Entity Framework
in the chapters about data binding, authentication, authorization, and performance.
If you’re an experienced Entity Framework developer, you can skip this chapter
and go straight to chapter 3. If you’re new to this topic, you’ll find this chapter to be a
good starting point to build on.
Before delving into the details of using Entity Framework, let’s take a step back and
analyze the pattern you should follow when you develop an application. By looking at
the pattern up close, you’ll clearly understand where Entity Framework stands in your
application design.
2.1 Designing an application
In this chapter, you’ll create an application that handles orders for the Northwind
database (more information about it is in the sidebar). This database contains data
about customers and products stored in several tables: Orders, Customers, Order
Details, and Products. The tables that contain this data are Orders, Customers,
Order Details, and Products.
You need to create an internal network of classes (the object model) that holds data
that can be filled from a query in the database. These classes also need to handle data
that updates the database. The classes are
Order
,
Customer
,
Order_Detail
, and

Product
.
They contain properties that represent data on
the database and that are useful for business.
These classes hide the complexity of the
database structure from the business code (also
known as the Business Logic Layer or
BLL), let-
ting the code communicate only with them and
with a specific layer that will be responsible for
interacting with the database (the Data Access
Layer or
DAL). The Business Logic Layer knows
nothing about the database and interacts only
with the four classes. The
DAL is responsible for
communicating with the database. With this
nifty organization, the classes we create
become the business Logic Layer database. Fig-
ure 2.1 shows an example of this design.
Database
Business
layer
Data access
layer
Order
Customer
Model
OrderDetail
Product

Figure 2.1 The Business Logic Layer uses
classes in the model and then persists
modifications through the Data Access
Layer. The business code doesn’t
communicate with the database.

32 CHAPTER 2 Data access reloaded: Entity Framework
Separating the code inside isolated layers is a technique that guarantees faster devel-
opment and, maybe more important, easier maintenance.
So far, we’ve said that the model contains classes that in turn contain data that is
persisted into the database. But how do you make a model? What techniques do you
need to use to build it? The answer is: it depends.
2.1.1 What’s an object model?
In many, possibly most, applications, a model can be a simple set of classes that con-
tain data coming from a database and that have only a little behavior. This kind of
model is known as an object model. Let’s look at a few of the characteristics of the
object model classes.
DATA VALIDATION
One of the behaviors that an object model class contains is data validation. For
instance, the
Customer
class has the
CustomerID
property. Because it’s the key of the
class (and the primary key in the
Customers
table), this property can’t be null or
empty. Placing validation code in the property setter makes sense because it prevents
the property from being set with an invalid value.
PROPERTY JOINING

Another behavior that is commonly added to an object model class is property join-
ing. You often need the full customer address in a single string. Writing a piece of
code that joins all address-related properties into a string every time you need the cus-
tomer’s full address is feasible, but it’s repetitive and error prone. The
Customer
class
contains an additional property,
FullAddress
, which internally joins the address prop-
erties and returns them as a string so you don’t have to write the code to retrieve the
full address every time you need it.
Why the Northwind database?
In this chapter and throughout the rest of the book, we’ll use the Northwind database.
Although it’s a simple database, it has lots of useful characteristics. First of all, it
represents a real-world scenario but exposes it in a manner that’s pretty easy to un-
derstand. Secondly, it’s been around for a long time, and it’s probably the most used
demo database in the world. We’ve attended countless conferences and courses and
this database is always used.
With the advent of SQL Server 2005, Microsoft introduced the AdventureWorks data-
base. This database represents a complex scenario and uses lots of SQL server fea-
tures. It also has an online transaction processing (OLTP) database and a data
warehouse so that every aspect of the business problem is covered.
Explaining SQL Server using AdventureWorks is wonderful, but we’re talking about
ASP.NET. We need a simpler model that allows us to focus on what matters so the
complexity of the database doesn’t bog us down.

33Designing an application
CONNECTING CLASSES TO EACH OTHER
Classes in an object model are not standalone; they’re connected to each other. For
instance, the

Order
class is connected to
Customer
and
Order_Detail
classes and
Order_Detail
is connected to
Product
.
In a database, tables are connected by foreign key columns. In an object model,
referencing another class simply by using a property that acts as a foreign key isn’t the
optimal solution because you can directly reference another class using a property of
the referenced class type. For example, the
Order
class keeps a reference to the
Cus-
tomer
class by using the
Customer
property (we used the
Customer
name but you can
use any name you like) whose type is
Customer
.
If an object must reference multiple objects, you can create an enumeration prop-
erty whose type is
List<T>,
where

T
is the type of the objects in the collection. For
instance, an order must reference a list of details. To do that, The
Order
class contains
the
Order_Details
property, which is of type
List<Order_Detail>
.
NOTE You don’t have to use
List<T>
. You can use any other collection
classes, like
Collection<T>
,
HashSet<T>
, or even the non generic
ArrayList
.
When you’ve completed the design process for the object model relationships, you
end up with the model shown in figure 2.2.
As I said before, an object model works perfectly well in lots of applications, but its
data-only nature is a limitation in complex scenarios. For some applications, you want
a higher level of interaction between the object model and the environment. In other
words, the object model must contain behavior.
2.1.2 The evolution of the object model: the domain model
A domain model is an object model where classes have a lot more behavior. The behav-
ior that’s added to domain model classes creates a broad and rich integration between
the classes and the environment.

Customer
Class
Order_Detail
Class
Product
Class
Order
Class
Order Details
Customer
Product
Figure 2.2 The Order class is connected to the Customer class by the Customer property. The
Order class also contains details through the Order_Details property. Eventually, each detail is
connected to the product via the Product property.

34 CHAPTER 2 Data access reloaded: Entity Framework
More exactly, a domain model doesn’t involve just classes and their data. It introduces
a new design for your application. The classes are integrated in the BLL and commu-
nicate with repository modules that are the new gateways to the database. All these
classes and modules becomes a single layer: the domain model.
The domain model itself doesn’t communicate directly with the database. An infra-
structure layer that’s underneath the model does the actual work. This layer hides
database communication. The repositories deal with the infrastructure layer, which
they use to send commands that retrieve data from a database or update data in it. Fig-
ure 2.3 shows the result of such a design.
You probably know that because classes are aware of the repositories, they can
retrieve data from the database. Because the classes can do this, they offer a brand
new range of services to the developers who use them. Not only that, the domain
model pattern contains lots of other features that are outside the scope of this book. If
you’re interested in knowing more about the domain model, check out the book

Domain Driven Design by Eric Evans.
Now you know how to effectively layer an application to create a better design and
more maintainable code. Layering is the foundation of every successful application
and the thing to keep in mind as you progress through the rest of the book.
All this discussion about object model and domain model includes a concept that
has always remained the same: you have to deal with a database and with objects
whose data must be persisted into it. Let’s discover how you can do that using
an
ORM.
Database
Domain Model
Order
Customer
OrderDetail
Product
Infrastructure
OrderRepository
OrderRepository
CustomerRepository
Figure 2.3 The domain model comprises the model classes and the repositories.
The model uses the infrastructure layer to abstract the physical interaction with
the database.

35Using an ORM to build a data layer
2.2 Using an ORM to build a data layer
An ORM is a framework that lets you build applications based on a paradigm that’s
completely different from the one you use when you work directly with ADO.NET. You
can just work with objects and ignore the database.
An
ORM lets you map your classes and properties against tables and columns in the

database. You can design your classes and tables independently and then let the ORM
do the dirty work of using the mapping information to generate SQL code to read data
from a database, create objects with it, and persist data inside objects in the database.
The
SQL code is then executed through ADO.NET, which remains at the lowest layer.
Given this definition, you might think that an ORM is a mere code generator, but
it’s not. An ORM stores modifications made to objects, ensures that only one object
with a given identity is in place, supports many optimization tweaks, and a lot more.
An
ORM does another vital thing: it handles the differences between a relational
database and the OOP paradigm (a.k.a the object/relational mismatch). The rela-
tional database and OOP paradigms are different in terms of data granularity, the way
relationships are defined, inheritance, and available datatypes. Before we tell you how
to use an
ORM, let’s examine the problems it solves so that you better understand how
an ORM makes your life easier. In this section, we’re going to analyze each problem
separately, starting with the easiest one: data granularity.
2.2.1 The granularity mismatch
In the Northwind database, the customer’s full address consists of the street address,
city, region, Zip Code, and country. The shipping address for orders has the same
information. In a database, you put the columns in each table, but when you’re
designing the classes in your model, you’ll probably create an
AddressInfo
class that
contains all the address-related properties. You’ll reuse this class in the
Customer
and
Order
classes. This design gives you three classes and two tables, as shown in figure 2.4.
Customer

Class
AdressInfo
Class
Order
Class
Address
Address
Customers Orders
Figure 2.4 The Customer and Order classes have an Address property of the type
AddressInfo that contains address information. Address-related columns are repeated
in the Customers and Orders tables.

36 CHAPTER 2 Data access reloaded: Entity Framework
Because the number of classes is different from the number of tables in the database,
you have a mismatch. This mismatch is known as the granularity problem.
2.2.2 The relationship mismatch
Another difference between the relational and OOP models is in the way they main-
tain relationships. Think about the order/customer relationship. In a database, you
create a
CustomerId
foreign key column in the
Orders
table (child table) that points
to the
CustomerId
primary key column of the
Customers
table (parent table). In the
object model, you can reference the customer from the order using a property with
the type

Customer
, so there’s no need for a foreign key property.
In a database the associations are unidirectional from the child table to the parent
table. In the object model, associations can be both unidirectional and bidirectional.
You can have the
Customer
property in
Order
, but you can also have an
Orders
prop-
erty in the
Customer
class. Figure 2.5 shows an example of this design.
In the case of a many-to-many relationship, the differences between a relational
database and
OOP paradigms grow. Think about the relationship between the
Employees
and
Territories
tables in the Northwind database. They’re not related
to each other through foreign keys but via a third table:
EmployeeTerritories
. In
the object model, you let the classes refer directly to each other without resorting to
a middle class.
The differences we discussed in this section are known as the relationship mismatch.
What’s more, in the many-to-many scenario you face a granularity mismatch because
you have three tables and two classes.
2.2.3 The inheritance mismatch

Suppose that customers in Germany require different data than customers from other
countries. You could create a base class for all customers and then create a separate
class for German customers and another class for all other customers. Both these cus-
tomer classes inherit from the base class.
CustomerID
Customer
Class
Order
Class
Orders
Customer
Customers
Orders
OrderID
CustomerID
Figure 2.5 Orders are related
to their customers using a
foreign key in the database.
The OOP model uses a
reference to the object.

37Introducing Entity Framework
In the database, the concept of inheritance doesn’t exist at all. What you can do is
create an artifact to simulate inheritance. You can create inheritance in the database
using one of three methods:

Tab le-per-hierarchy (TPH)—One table contains the data for all the classes in the
inheritance hierarchy and usually uses a discriminator column to determine
the kind of object that’s stored.


Tab le-per-type (TPT)—Each class in the inheritance hierarchy has one table. Each
table adds only the columns that are necessary for the type.

Tab le-per-concre te (TPC)—Again, each class has a table, but each table contains all
the columns mapped to all the properties of the mapped class.
Whatever approach you choose, you’re bending the relational model to represent
something it’s not designed for. This mismatch is known as the inheritance problem.
THE DATATYPE MISMATCH
Last, but not least, there’s the data type problem. In a database, you have
varchar
,
int
,
datetime
, and other datatypes that might or might not have a counterpart
in .NET.
Let’s use as an example the
int
datatype in SQL server. You can map it to an
Int32
property, and it works perfectly. Now, think about the
varchar
datatype, which can be
easily mapped to a string. But if the column has a maximum length, you can’t repre-
sent that in the .
NET string type unless you write code to check the length. The situa-
tion worsens for datatypes like
RowVersion
or
Timestamp

that are represented as an
array of bytes. This mismatch is known as the datatype problem.
When you write code using
ADO.NET, you have to handle all these differences on
your own. An ORM handles these differences for you so that you can focus on objects
that demand database interaction.
NOTE Never commit the suicide of ignoring the database. It might be masked
by the ORM, but it’s still there. Always measure the performance of SQL code
generated by the ORM. Plenty of profiler tools can help you trace commands
and measure performance.
You’ve learned what problems an ORM addresses and why it can ease your mind when
you’re developing data access. Now let’s see how to use it. In the coming sections, we’ll
use Entity Framework, which is the
ORM introduced by Microsoft in the .NET Frame-
work 3.5 SP1. Entity Framework is now in its second version (named 4.0 only because
its versioning has been aligned with that of the .NET Framework).
2.3 Introducing Entity Framework
The first step you take to introduce Entity Framework in an application is to generate
the Entity Data Model (EDM). The EDM is the heart of the Entity Framework. It’s where
the mapping information between the classes and database is stored. The EDM is
made up of three XML files. The first one describes the object model classes, the

38 CHAPTER 2 Data access reloaded: Entity Framework
second one describes the tables in the database, and the last one stores their mapping.
Let’s see now how to handle these files.
Creating a model using Entity Framework
Manually creating and maintaining EDM files is a time consuming operation. That’s
why the Entity Framework team has created a wizard and a designer inside Visual Studio
that you can use to handle these files visually without worrying about their structure.
PROBLEM

Suppose you have to write an application that manages orders in the
Northwind
data-
base. You have to work with the
Orders
,
Order Details
,
Customers
, and
Products
tables, and with the
Order
,
Order_Detail
,
Customer
, and
Product
classes. You also
have to generate the EDM to map these classes and tables, and generate code for
classes so that you’re productive immediately.
SOLUTION
To create the EDM, add a new item of the type ADO.NET Entity Data Model to the proj-
ect. In a three-layer application, the best place to put this item is in the model assem-
bly. If you adopt the domain model way of designing, you’ll probably create a separate
assembly that references the repository.
After you’ve added the item, Visual Studio starts a wizard. The first step lets you
choose whether you want to create a model starting from a database or from scratch
and then create a database from it. Because we already have a database, we’re opting

for the first choice. Figure 2.6 shows the form where you make this choice.
TECHNIQUE 4
Figure 2.6
The first form of the
Visual Studio wizard
lets you choose to
create a model from
a database (first op-
tion) or from scratch
(second option).

39TECHNIQUE 4 Creating a model using Entity Framework
Choosing this design option means that at the end of the wizard, you’ll have the tables
described in the EDM and an automatically generated class for each of them. The
properties and the columns will also be mapped one-to-one. What’s more, the wizard
inspects foreign keys on the database and reflects them in the classes. For example, it
places the property
Customer
in the
Order
class and the property
Orders
in
Customer
.
On the second form, you first choose the database you want to connect to. Use
the drop-down list that shows the database already configured inside Visual Studio
(you can create a new connection on the fly by clicking the New Connection button).
After you’ve chosen the database, you’ll see the connection string that Entity Frame-
work uses to connect to that database in the Entity connection string box. Use the

check box at the bottom of the form to choose whether to store the connection
string in the configuration file; if you select the check box, type the name of the key
that the connection string has in the configuration file in the text box. All this is
shown in figure 2.7.
The third, and last, form connects to the selected database; scans its tables, views,
stored procedures, and functions; and shows them in a check box tree. Here you
select the tables that you want to use (in this case,
Orders
,
Order Details
,
Customers
and
Products)
.
Figure 2.7 In the second form of the wizard, you choose the database to connect
to or create a new connection on the fly (by clicking the New Connection button).
Finally, you choose the name of the connection string in the configuration file.

40 CHAPTER 2 Data access reloaded: Entity Framework
Below the tree are two options that deserve your attention. The first one lets you
choose whether to pluralize or singularize the class names. If you select this check
box, the
Orders
table generates a class named
Order
and vice versa. If you don’t select
this check box, the
Orders
table only generates a class named

Orders
. The second
option lets you choose whether to create a foreign key property along with the prop-
erty that references another object. For instance, in addition to the
Customer
prop-
erty, you can decide to include the
CustomerId
property in the
Order
class. This last
choice is enabled by default, and you should keep it. Using foreign key properties
makes relationship management a whole lot easier. Figure 2.8 shows this last form.
When you’ve made your selections, click Finish. The wizard creates the classes and
shows them in a designer.
TIP The designer shows the classes, not the tables.
You can edit the classes to modify their names or the names of their properties to add
relationships with other classes, to add inheritance, and so on. You have full control
over your model.
If you look at the Solution Explorer window in Visual studio, the wizard has gener-
ated a file with the extension .edmx that’s associated with the designer. It contains the
three
EDM files merged into one so that each time you modify an entity visually, its
modifications are recorded inside that file.
Figure 2.8 The last form lets you choose the tables to import into the EDM.

41TECHNIQUE 5 Generating POCO code
EDMX VERSUS EDM The EDMX file is not the EDM. The EDMX is an artifact
for enabling the designer. It is not understood by Entity Framework. At com-
pile time, the compiler splits the EDMX into the three EDM files and then

embeds those files into the assembly or saves them in the output directory so
that the runtime of Entity Framework can read them. What the compiler does
depends on the value of the
Metadata

Artifact

Processing
property of the
designer. Its possible values are
Embed

in

Output

Assembly
and
Copy

to

Out-
put

Directory
.
In the Solution Explorer window, nested into the EDMX file, you see either a .cs file or
a .vb file, depending on your programming language. This file contains the code for
the classes described in the

EDM and one important class: the context (we’ll get back to
this later).
The last step you have to take is to enable Entity Framework in your application is
to copy the connection string generated by the wizard into the configuration file of
the application. (The connection string is in the app.config file of the assembly in
which you generated the
EDMX file). Now Entity Framework is correctly set up, and
you can start writing data access code.
DISCUSSION
When all’s said and done, enabling Entity Framework is as easy as completing a wiz-
ard. Naturally, if you don’t have a database and you need to start from the object
model, the path is harder because you have to design classes from scratch. Fortu-
nately, the designer is powerful enough to help you do that rather painlessly. It lets
you create properties, associations, inheritance hierarchies, and so on.
Speaking of classes, if you take a look at their code, you’ll see that it’s cluttered by
lots of uninteresting stuff. Attributes decorate the class definition, the property, and
even the assembly. The getters and setters of the properties are full of infrastructure
code. In other words, the classes are aware of Entity Framework, which is wrong. In a
domain model design, classes can be aware of the data layer, but they must not be
aware of the technology that it uses. Classes must be ignorant of persistence. Each
must be a Plain Old
CLR Object (POCO) and worry only about business code.
Generating POCO code
The reason the generated code is not POCO is that the first version of Entity Frame-
work didn’t support POCO classes. One of the new features in the current version of
Entity Framework is support for POCO classes. Developing with POCO classes is far bet-
ter than developing with classes that are generated by default. POCO classes contain
only business code and not persistence-related code. What’s more, if you change the
persistence tool (say, from pure
ADO.NET to Entity Framework or vice versa), you

don’t have to change your model classes but only the layer that talks to the database.
To let you generate legacy classes,
POCO classes and, more broadly speaking, any
code you want, the Entity Framework team has leveraged a feature of Visual Studio
called T4 templates. By using templates, you can fully customize the way classes are
generated so that you can add your logic.
TECHNIQUE 5

42 CHAPTER 2 Data access reloaded: Entity Framework
PROBLEM
For this example, our scenario is that before you start your development work, you
want to change from default code generation and customize the process. You need
POCO classes, and you want to both customize their generation and extend them.
SOLUTION
Templates are the key to custom code generation. A template is a markup file where
you can dynamically add content. You can think of it as a Classic ASP page that creates
C# or VB code instead of generating HTML. The syntax is only slightly different: classic
ASP uses
<%
markers and templates use
<#
.
Fortunately, the Entity Framework team has already created a template that gener-
ates
POCO code. Unfortunately, this template is not integrated in the .NET Framework
and Visual Studio. You’ve got to download and install it using the Extension Manager
tool inside Visual Studio.
This template is available for both C# and
VB in two flavors: one for web site appli-
cations and one for others. Figure 2.9 shows how to search for the templates in the

Extension Manager window.
After installing the templates, you can right-click on the designer and choose the
Add Code Generation Item. Visual Studio opens the Add File wizard. Here’s where
you select the
POCO template.
Figure 2.9 The Extension Manager window lets you search for and install the templates in your
Visual Studio.

43TECHNIQUE 6 Reading data using Entity Framework
Now the project contains two new template files. One generates POCO classes and the
other one creates the context class (we’ll talk more about this in the next section). In
the Solution Explorer window, The
POCO template contains a nested file for each
class in the model; the other template contains only one nested file.
Because we generated the
EDMX file inside the model assembly, the POCO tem-
plate must remain there because it generates classes. The other template generates
the context that’s required only by the real data access code, so you must move it into
the assembly that’s responsible for accessing data. Because it points to the
EDMX file,
you have to open it after you move it and change its reference to the file by modifying
the
inputFile
variable.
DISCUSSION
With a few clicks, you’ve created a well-structured application. In fact, now you’ve got
.NET classes, the database, the class mappings, and a data access gateway (the con-
text). At last! You’re ready to write real code. In the next section, you’re going to see
how to query with Entity Framework.
Reading data using Entity Framework

Querying a database using the classic ADO.NET approach requires you to write SQL
code and leverage several classes to execute it and read returned data. Querying
with Entity Framework is different. Because you don’t work directly with the data-
base, the only structure you need to know about is the model. That’s how the model
becomes your database and why your queries are written against it. The burden of
translating everything into
SQL and executing it against the database is shifted to
Entity Framework.
Entity Framework is a huge step towards development simplicity. Remember that
in section 2.2.1, we discussed that the classes in the model can be different from the
database tables that classes are mapped to. Classes have inheritance. The number of
classes and tables does not have to match, and so on. You don’t have to worry about
any of these problems. You write queries against the model, and then Entity Frame-
work generates
SQL for you. What’s more, classes express business better than data-
base tables do, so writing queries against them is a more business oriented approach.
PROBLEM
Suppose you have to create a web page that shows orders in a grid. The user must be
able to filter orders by customer name, shipping city, total amount, and the product
sold. The user must also be able to sort the orders by any column, and data must be
paged because we’re in a web environment. Finally, the data shown in the list is the
full shipping address, the customer name, and the amount of the order.
SOLUTION
For a single web page, that’s a lot of requirements. For now, let’s ignore the page and
focus on the data access code you need to satisfy them. As we hinted before, the sec-
ond template generates the context class. The context class is your gateway to the
database. This class inherits from
ObjectContext
and has an entity set for each class
TECHNIQUE 6


44 CHAPTER 2 Data access reloaded: Entity Framework
that doesn’t inherit from any other in the model. In our case, we have four classes and
four entity sets, but if there were a
SpecialProduct
class that inherited from
Product
,
we would have five classes and four entity sets.
If the context is your gateway to the database, the entity sets are your gateway to
the data. Think of them as an in-memory representation of a table (data doesn’t
reside solely in memory). The context class exposes each entity set as a property
whose name is the name of the table (identical, pluralized, or singularized, depending
on your choice) and whose type is
ObjectSet<T>,
where
T
is the model class it
exposes (you can modify the name of the entity set by using the designer). The follow-
ing listing shows what the context class looks like.
C#:
public partial class NorthwindEntities : ObjectContext
{

public ObjectSet<Customer> Customers { }
public ObjectSet<Order_Detail> Order_Details { }
public ObjectSet<Order> Orders { }
public ObjectSet<Product> Products { }
}
VB:

Public Partial Class NorthwindEntities
Inherits ObjectContext

Public Property Customers() As ObjectSet(Of Customer)
Public Property Order_Details() As ObjectSet(Of Order_Detail)
Public Property Orders() As ObjectSet(Of Order)
Public Property Products() As ObjectSet(Of Product)
End Class
To quer y the model, you have to perform a LINQ to Entities query against an entity
set. LINQ to Entities is just a dialect of LINQ that triggers the process that transforms
the LINQ query in SQL (instead of performing an in-memory search).
Now that you have the fundamentals, let’s start writing the query that returns
orders. The first search parameter is the shipping city. Applying this type of filter is
extremely simple.
C#:
using (var ctx = new NorthwindEntities())
{
return ctx.Orders.Where(o => o.ShipCity == shippingAddress);
}
VB:
Using ctx = New NorthwindEntities()
Return ctx.Orders.Where(Function(o) o.ShipCity = shippingAddress)
End Using
Listing 2.1 The generated context class

45TECHNIQUE 6 Reading data using Entity Framework
Isn’t that expressive? We love LINQ expressiveness when querying, and these snippets
are proof of that power.
NOTE From now on, we’ll remove context instantiation and will always use
the

ctx
name to identify it.
The second filtering parameter is the customer name. Here, the filtering is applied
not on the order but on an entity that’s associated with it. Because the order has a ref-
erence to the customer entity, we can navigate the model from the order to the cus-
tomer and filter by its name.
C#:
ctx.Orders.Where(o => o.Customer.CompanyName == customerName);
VB:
ctx.Orders.Where(Function(o) o.Customer.CompanyName = customerName)
As you see, we don’t need to specify joins as we would do in SQL code. Entity Frame-
work reads relationships from the EDM and automatically generates correct joins for
us. Thumbs up for Entity Framework.
The third search parameter is a bit harder. We have to calculate the total amount
of an order and compare that with the user value. Performing such a query in
SQL is
challenging and requires a
GROUP BY
clause. In LINQ to Entities, we can do it with a
couple of methods that are unbelievably simple.
C#:
ctx.Orders.Where(o =>
o.Order_Details.Sum(d => (d.UnitPrice * d.Quantity)) > amount);
VB:
ctx.Orders.Where(Function(o) _
o.Order_Details.Sum(Function(d) (d.UnitPrice * d.Quantity)) > amount)
These snippets navigate from the orders to their details and sum the total of each of
them. Then they check that the sum is greater than the given input. Isn’t that awe-
some?
The last search parameter is the product. The user searches for orders that include

that product in the list of those sold. Here we have another type of search because we
have to determine whether a product is included in the associated list of details. Once
again,
LINQ makes it simple.
C#:
ctx.Orders.Where(o =>
o.Order_Details.Any(d => d.ProductID == productId));
VB:
ctx.Orders.Where(Function(o) _
o.Order_Details.Any(Function(d) d.ProductID = productId))
The
Any
method checks whether a product with the same ID is in the details associ-
ated with the order and returns a boolean.

46 CHAPTER 2 Data access reloaded: Entity Framework
So far we’ve applied filters statically, but because the user can enter some and
ignore others, we have to find a way to apply them dynamically. The solution is the
IQueryable<T>
interface. Take a look at the following listing.
C#:
IQueryable<Order> result = ctx.Orders;
if (!String.IsNullOrEmpty(shippingAddress))
result = result.Where(o =>
o.Order_Details.Any(d => d.ProductID == productId));
if (!String.IsNullOrEmpty(customerName))
result = result.Where(o => o.Customer.CompanyName == customerName);
VB:
Dim result As IQueryable(Of Order) = ctx.Orders
If Not String.IsNullOrEmpty(shippingAddress) Then

result = result.Where(Function(o) _
o.Order_Details.Any(Function(d) d.ProductID = productId))
End If
If Not String.IsNullOrEmpty(customerName) Then
result = result.Where(Function(o) _
o.Customer.CompanyName = customerName)
End If
Each LINQ method returns an
IQueryable<T>
object, so you can add filters to it
dynamically. Easy as pie, isn’t it?
Another requirement is data paging. Doing it in
SQL requires you to write a long
statement. In LINQ to Entities, you can leverage the power of the
Skip
and
Take
meth-
ods.
Skip
ignores the first n rows, and
Take
takes only the following n rows.
C#:
result = result.Skip(10).Take(10);
VB:
result = result.Skip(10).Take(10)
This query skips the first 10 rows and returns the next 10 rows. If the grid you show
data in shows 10 rows per page, this query retrieves rows from the second page. All the
methods we’ve been discussing are reason enough for you to move to Entity Frame-

work and
LINQ.
Another important requirement is the ability to sort orders. Thanks to the
OrderBy
method, once again this is a simple task. Because the user decides what column to sort
by, we have to check at runtime which column the user has selected and sort the data
by that column. The following listing shows how to achieve this goal.
C#:
if (sortField == "shipcity")
result = result.OrderBy(o => o.ShipCity);
else if (sortField == "shipaddress")
Listing 2.2 Applying filters dynamically
Listing 2.3 Sorting data dynamically

47TECHNIQUE 6 Reading data using Entity Framework
result = result.OrderBy(o => o.ShipAddress);
else
result = result.OrderBy(o => o.ShipCountry);
VB:
If sortField = "shipcity" Then
result = result.OrderBy(Function(o) o.ShipCity)
ElseIf sortField = "shipaddress" Then
result = result.OrderBy(Function(o) o.ShipAddress)
Else
result = result.OrderBy(Function(o) o.ShipCountry)
End If
The final requirement has to do with data to be shown on the mask. We need only the
full shipping address, the customer name, and the total amount, and we can optimize
the query to retrieve only this data. This data contains properties about the order, plus
its customer and its total amount. This kind of data is referred to as a projection.

In
LINQ to Entities, you can perform a projection using the
Select
method. The
result of a projection is an anonymous type. Now, you know that an anonymous type
can be exposed outside a method only as an instance of type
Object
. Having the result
of the query exposed as an
Object
instance isn’t good from a design point of view.
You can optimize design by creating a Data Transfer Object (DTO) with the prop-
erties that match the result of the projection. In the query, you pour the result into
the
DTO. Finally, you let the method in the DAL expose and return the DTO class. The
following listing shows the code for the query.
C#:
IQueryable<OrderDTO> finalResult = result.Select(o =>
new OrderDTO
{
CustomerName = o.Customer.CompanyName,
ShipAddress = o.ShipAddress,
ShipCity = o.ShipCity,
ShipCountry = o.ShipCountry,
ShipPostalCode = o.ShipPostalCode,
Total = o.Order_Details.Sum(d => (d.UnitPrice * d.Quantity)) );
}
VB:
Dim finalResult As IQueryable(Of OrderDTO) = result.Select(Function(o) _
New OrderDTO() With { _

.CustomerName = o.Customer.CompanyName, _
.ShipAddress = o.ShipAddress, _
.ShipCity = o.ShipCity, _
.ShipCountry = o.ShipCountry, _
.ShipPostalCode = o.ShipPostalCode, _
.Total = o.Order_Details.Sum(Function(d) (d.UnitPrice * d.Quantity))
The
OrderDTO
class is the class in the model assembly that acts as a DTO. Its only pur-
pose is letting data flow to the GUI in a typed way.
Listing 2.4 Returning a DTO with only necessary data

48 CHAPTER 2 Data access reloaded: Entity Framework
DISCUSSION
Well, putting it all together uses about 21 lines of code (we’re counting blank lines).
Now think about how much SQL and .NET code you would have written to do this in
classic ADO.NET style and ask yourself, isn’t this a better way? In an ASP.NET environ-
ment, everything needs to be optimized and using Entity Framework is a great way to
do that.
Before we get to the end of the chapter, let’s look at the other side of the coin: data
writing.
Writing data using Entity Framework
Writing data on the database is as simple as reading it. In most cases, you just need to
call the three basic methods of the entity set to add, modify, or delete data from the
database.
PROBLEM
Suppose that you have to create a form to edit customers’ data. You need to be able to
create, modify, and delete customers.
SOLUTION
As before, we’re not going to talk about the user interface here. We’re going to focus

on the data access code. The process of saving objects passes through two phases:

Tracking —During this phase, the context tracks modifications made to objects
that it references. The context references all objects that you read through it
and objects that you add or attach to it. More generally, the tracking phase starts
when you instantiate the context and ends when you trigger the next phase.

Persistence—During this phase, the context gathers modifications made to
objects during the tracking phase and persists them into the database.
Creating a customer is pretty simple. We need to create a
Customer
instance and pass
it to the
AddObject
method of the customer’s entity set (tracking phase). After that,
we call the context
SaveChanges
method to trigger persistence to the database. The
following listing puts this technique into practice.
C#:
var c = new Customer()
{
Address = "address",
City = "City",
CompanyName = "CompanyName",
ContactName = "ContactName",
ContactTitle = "ContactTitle",
Country = "Country",
CustomerID = "15455",
Fax = "222222",

Phone = "2333333",
PostalCode = "123445",
Listing 2.5 Creating a new customer
TECHNIQUE 7

49TECHNIQUE 7 Writing data using Entity Framework
Region = "Region"
};
ctx.Customers.AddObject(customer);
ctx.SaveChanges();
VB:
Dim c = New Customer() With _
{ _
.Address = "address", _
.City = "City", _
.CompanyName = "CompanyName", _
.ContactName = "ContactName", _
.ContactTitle = "ContactTitle", _
.Country = "Country", _
.CustomerID = "15455", _
.Fax = "222222", _
.Phone = "2333333", _
.PostalCode = "123445", _
.Region = "Region" _
}
ctx.Customers.AddObject(customer)
ctx.SaveChanges()
The
AddObject
method adds the customer instance to the context and marks the

instance as
Added
.
SaveChanges
transforms the added object into a new row in the
database.
Updating the customer is equally simple. You can do it in one of two ways. You can
retrieve the customer, update it, and then call
SaveChanges
to report modifications to
the database. This scenario is defined as connected because you use the same context to
read and update customer data.
C#:
var c = ctx.Customers.First(c => c.CustomerId == "15455");
c.Address = "newaddress";
ctx.SaveChanges();
VB:
Dim c = ctx.Customers.First(Function(c) c.CustomerId = "15455")
c.Address = "newaddress"
ctx.SaveChanges()
Another way to update an entity is to create a
Customer
instance, attach it to the con-
text using the
Attach
method of the customer’s entity set, and then mark it as
Modi-
fied
. This scenario is known as disconnected because the context you use to update
customer data is not the same one you use to read customer data. The code required

for the disconnected scenario is shown in the following listing.
C#:
ctx.Customers.Attach(customer);
ctx.ObjectStateManager.GetObjectStateEntry(customer).
Listing 2.6 Updating a customer

×