One of the most significant differences between
profiles and other types of state management is that profiles are
designed to store information permanently, using a back-end data source
such as a database. Most other types of state management are designed to
maintain information for a series of requests occurring in a relatively
short space of time (such as session state) or in the current browser
session (such as view state and nonpersistent cookies) or to transfer
information from one page to another (such as the query string and
cross-page posting). If you need to store information for the longer
term in a database, profiles simply provide a convenient model that
manages the retrieval and persistence of this information for you.
Before you begin using profiles, you need to assess them carefully. In the following sections, you'll learn how they stack up.
1. Profile Performance
The goal of ASP.NET's
profiles feature is to provide a transparent way to manage user-specific
information, without forcing you to write custom data access code using
the ADO.NET data classes. Unfortunately, many features that seem
convenient suffer from poor performance or scalability. This is
particularly a concern with profiles, because they involve database
access, and database access can easily become a scalability bottleneck
for any web application.
So, do profiles suffer
from scalability problems? This question has no simple answer. It all
depends on how much data you need to store and how often you plan to
access it. To make an informed decision, you need to know a little more
about how profiles work.
Profiles plug into the page life cycle in two ways:
The first time you
access the Profile object in your code, ASP.NET retrieves the complete
profile data for the current user from the database. If you read the
profile information more than once in the same request, ASP.NET reads it
once and then reuses it, saving your database from unnecessary extra
work.
If you
change any profile data, the update is deferred until the page
processing is complete. At that point (after the PreRender,
PreRenderComplete, and Unload events have fired for the page), the
profile is written back to the database. This way, multiple changes are
batched into one operation. If you don't change the profile data, no
extra database work is incurred.
Overall, the profiles feature
could result in two extra database trips for each request (in a
read-write scenario) or one extra database trip (if you are simply
reading profile data). The profiles feature doesn't integrate with
caching, so every request that uses profile data requires a database
connection.
From a performance standpoint, profiles work best when the following is true:
They tend to work less well when the following is true:
You have a large number of pages needing to use profile information.
You
are storing large amounts of data. This is particularly inefficient if
you need to use only some of that data in a given request (because the
profile model always retrieves the full block of profile data).
Of course, you can
combine profiles with another type of state management. For example,
imagine your website includes an order wizard that walks the user
through several steps. At the beginning of this process, you could
retrieve the profile information and store it in session state. You
could then use the Session collection for the remainder of the process.
Assuming you're using the in-process or out-of-process state server to
maintain session data, this approach is more efficient because it saves
you from needing to connect to the database repeatedly.
2. How Profiles Store Data
The most significant
limitation with profiles doesn't have anything to do with
performance—instead, it's a limitation of how the profiles are
serialized. The default profile provider included with ASP.NET
serializes profile information into a block of data that's inserted into
a single field in a database record. For example, if you serialize
address information, you'll end up with something like this:
Marty Soren315 Southpart DriveLompocCalifornia93436U.S.A.
Another field indicates where each value starts and stops, using a format like this:
Name:S:0:11:Street:S:11:19:City:S:30:6:State:S:36:10:ZipCode:S:46:5:Country:S:51:6
Essentially, this string
identifies the value (Name, Street, City, and so on), the way it's
stored (S for string), the starting position, and the length. So the
first part of this string
Name:S:0:11
indicates that the first profile property is Name, which is stored as a string, starts at position 0, and is 11 characters long.
Although this approach gives
you the flexibility to store just about any combination of data, it
makes it more difficult to use this data in other applications. You can
write custom code to parse the profile data to find the information you
want, but depending on the amount of data and the data types you're
using, this can be an extremely tedious process. And even if you do
this, you're still limited in the ways you can reuse this information.
For example, imagine you use profiles to store customer address
information. Because of the proprietary format, it's no longer possible
to generate customer lists in an application such as Microsoft Word or
perform queries that filter or sort records using this profile data.
(For example, you can't easily perform a query to find all the customers
living in a specific city.)
This problem has two solutions:
Of the two options, creating a
custom data access component is easier, and it gives you more
flexibility. You can design your data component to have any interface
you want, and you can then reuse that component with other .NET
applications.
The second option is
interesting because it allows your page to keep using the profile model.
In fact, you could create an application that uses the standard profile
serialization with the SqlProfileProvider and then switch it later to
use a custom provider. To make this switch, you don't need to change any
code. Instead, you simply modify the profile settings in the web.config
file. As it becomes more common for websites to use the profiles
features, custom profile providers will become more attractive.
NOTE
It's also important to
consider the type of data that works best in a profile. As with many
other types of state management, you can store any serializable types
into a profile, including simple types and custom classes.
One significant difference
between profiles and other types of state management is that profiles
are stored as individual records, each of which is uniquely identified
by user name. This means profiles require you to use some sort of
authentication system. It makes no difference what type of
authentication system you use (Windows, forms, or a custom
authentication system)—the only requirement is that authenticated users
are assigned a unique user name. That user name is used to find the
matching profile record in the database.