Download as doc, pdf, or txt
Download as doc, pdf, or txt
You are on page 1of 115

Using LINQ to SQL (Part 1)

Over the last few months I wrote a series of blog posts that covered some of the new language features
that are coming with the Visual Studio and .NET Framework Orcas release. !ere are pointers to the
posts in m" series#
$utomatic %roperties& Ob'ect Initiali(er and )ollection Initiali(ers
E*tension +ethods
,ambda E*pressions
-uer" S"nta*
$non"mous T"pes
The above language features help make querying data a first class programming concept. .e call this
overall /uer"ing programming model ,IN- 0 which stands for .NET Language Integrated Query.
1evelopers can use ,IN- with an" data source. The" can e*press efficient /uer" behavior in their
programming language of choice& optionall" transform2shape data /uer" results into whatever format the"
want& and then easil" manipulate the results. ,IN-0enabled languages can provide full t"pe0safet"
and compile0time checking of /uer" e*pressions& and development tools can provide full intellisense&
debugging& and rich refactoring support when writing ,IN- code.
,IN- supports a ver" rich e*tensibilit" model that facilitates the creation of ver" efficient domain0specific
operators for data sources. The Orcas version of the .NET Framework ships with built0in libraries that
enable ,IN- support against Ob'ects& 3+,& and 1atabases.
What Is LINQ to SQL?
,IN- to S-, is an O24+ 5ob'ect relational mapping6 implementation that ships in the .NET Framework
Orcas release& and which allows "ou to model a relational database using .NET classes. 7ou can then
/uer" the database using ,IN-& as well as update2insert2delete data from it.
,IN- to S-, full" supports transactions& views& and stored procedures. It also provides an eas" wa" to
integrate data validation and business logic rules into "our data model.
Modeling Databases Using LINQ to SQL:
Visual Studio Orcas ships with a ,IN- to S-, designer that provides an eas" wa" to model and
visuali(e a database as a ,IN- to S-, ob'ect model. +" ne*t blog post will cover in more depth how to
use this designer 5"ou can also watch this video I made in 8anuar" to see me build a ,IN- to S-, model
from scratch using it6.
9sing the ,IN- to S-, designer I can easil" create a representation of the sample Northwind database
like below#
+" ,IN- to S-, design0surface above defines four entit" classes# %roduct& )ategor"& Order and
Order1etail. The properties of each class map to the columns of a corresponding table in the database.
Each instance of a class entit" represents a row within the database table.
The arrows between the four entit" classes above represent associations2relationships between the
different entities. These are t"picall" modeled using primar"0ke"2foreign0ke" relationships in the
database. The direction of the arrows on the design0surface indicate whether the association is a one0to0
one or one0to0man" relationship. Strongl"0t"ped properties will be added to the entit" classes based on
this. For e*ample& the )ategor" class above has a one0to0man" relationship with the %roduct class. This
means it will have a )ategories propert" which is a collection of %roduct ob'ects within that categor".
The %roduct class then has a )ategor" propert" that points to a )ategor" class instance that represents
the )ategor" to which the %roduct belongs.
The right0hand method pane within the ,IN- to S-, design surface above contains a list of stored
procedures that interact with our database model. In the sample above I added a single
:et%roducts;")ategor" S%4O). It takes a categor"I1 as an input argument& and returns a se/uence
of %roduct entities as a result. .e<ll look at how to call this S%4O) in a code sample below.
9nderstanding the 1ata)onte*t )lass
.hen "ou press the save button within the ,IN- to S-, designer surface& Visual Studio will persist
out .NET classes that represent the entities and database relationships that we modeled. For each ,IN-
to S-, designer file added to our solution& a custom 1ata)onte*t class will also be generated. This
1ata)onte*t class is the main conduit b" which we<ll /uer" entities from the database as well as appl"
changes. The 1ata)onte*t class created will have properties that represent each Table we modeled
within the database& as well as methods for each Stored %rocedure we added.
For e*ample& below is the Northwind1ata)onte*t class that is persisted based on the model we designed
above#
LINQ to SQL Code Examples
Once we<ve modeled our database using the ,IN- to S-, designer& we can then easil" write code to
work against it. ;elow are a few code e*amples that show off common data tasks#
1) Qe!" #!od$ts %!om the Database
The code below uses ,IN- /uer" s"nta* to retrieve an IEnumerable se/uence of %roduct ob'ects. Note
how the code is /uer"ing across the %roduct2)ategor" relationship to onl" retrieve those products in the
;everages categor"#
C#:
VB:
&) Update a #!od$t in the Database
The code below demonstrates how to retrieve a single product from the database& update its price& and
then save the changes back to the database#
C#:
VB:
Note: VB in "Orcas" Beta1 doesn't suort La!"das yet. It #i$$% t&oug&% in Beta' ( at #&ic& oint t&e
a"o)e query can "e re#ritten to "e !ore concise.
') Inse!t a Ne( Catego!" and )(o Ne( #!od$ts into the Database
The code below demonstrates how to create a new categor"& and then create two new products and
associate them with the categor". $ll three are then saved into the database.
Note below how I don<t need to manuall" manage the primar" ke"2foreign ke" relationships. Instead& 'ust
b" adding the %roduct ob'ects into the categor"<s %roducts collection& and then b" adding the )ategor"
ob'ect into the 1ata)onte*t<s )ategories collection& ,IN- to S-, will know to automaticall" persist the
appropriate %=2F= relationships for me.
C#
VB:
*) Delete #!od$ts +!om the Database
The code below demonstrates how to delete all To" products from the database#
C#:
VB:
,) Call a Sto!ed #!o$ed!e
The code below demonstrates how to retrieve %roduct entities not using ,IN- /uer" s"nta*& but rather b"
calling the :et%roducts;")ategor" stored procedure we added to our data model above. Note that
once I retrieve the %roduct results& I can update2delete them and then call db.Submit)hanges56 to persist
the modifications back to the database.
C#:
VB:
-) .et!ie/e #!od$ts (ith Se!/e! Side #aging
The code below demonstrates how to implement efficient server0side database paging as part of a ,IN-
/uer". ;" using the Skip56 and Take56 operators below& we<ll onl" return >? rows from the database 0
starting with row @??.
C#:
VB:
Smma!"
,IN- to S-, provides a nice& clean wa" to model the data la"er of "our application. Once "ou<ve defined
"our data model "ou can easil" and efficientl" perform /ueries& inserts& updates and deletes against it.
!opefull" the above introduction and code samples have helped whet "our appetite to learn more. Over
the ne*t few weeks I<ll be continuing this series to e*plore ,IN- to S-, in more detail.
!ope this helps&
Scott
LINQ to SQL (Part 2 - Defining our Data Model Classes)
In %art > of m" ,IN- to S-, blog post series I discussed .hat is ,IN- to S-, and provided a
basic overview of some of the data scenarios it enables.
In m" first post I provided code samples that demonstrated how to perform common data scenarios using
,IN- to S-, including#
!ow to /uer" a database
!ow to update rows in a database
!ow to insert and relate multiple rows in a database
!ow to delete rows in a database
!ow to call a stored procedure
!ow to retrieve data with server0side paging
I performed all of these data scenarios using a ,IN- to S-, class model that looked like the one below#
In this second blog post in the series I<m going to go into more detail on how to create the above ,IN- to
S-, data model.
,IN- to S-,& the ,IN- to S-, 1esigner& and all of the features that I<m covering in this blog post series
will ship as part of the .NET A.B and Visual Studio Orcas release.
7ou can follow all of the steps below b" downloading either Visual Studio Orcas ;eta > or Visual .eb
1eveloper E*press Orcas ;eta>. ;oth can be installed and used side0b"0side with VS @??B.
C!eate a Ne( LINQ to SQL Data Model
7ou can add a ,IN- to S-, data model to an $S%.NET& )lass ,ibrar" or .indows client pro'ect b" using
the $dd New Item option within Visual Studio and selecting the ,IN- to S-, item within it#
Selecting the ,IN- to S-, item will launch the ,IN- to S-, designer& and allow "ou to model classes
that represent a relational database. It will also create a strongl"0t"ped 1ata)onte*t class that will have
properties that represent each Table we modeled within the database& as well as methods for each Stored
%rocedure we modeled. $s I described in %art > of this blog post series& the 1ata)onte*t class is the
main conduit b" which we<ll /uer" entities from the database as well as appl" changes back to it.
;elow is a screen0shot of an empt" ,IN- to S-, O4+ designer surface& and is what "ou<ll see
immediatel" after creating a new ,IN- to S-, data model#

Entit" Classes
,IN- to S-, enables "ou to model classes that map to2from a database. These classes are t"picall"
referred to as Entit" )lasses and instances of them are called Entities. Entit" classes map to tables
within a database. The properties of entit" classes t"picall" map to the table<s columns. Each instance of
an entit" class then represents a row within the database table.
Entit" classes defined with ,IN- to S-, do not have to derive from a specific base class& which means
that "ou can have them inherit from an" ob'ect "ou want. $ll classes created using the ,IN- to S-,
designer are defined as partial classes 0 which means that "ou can optionall" drop into code and add
additional properties& methods and events to them.
9nlike the 1ataSet2Table$dapter feature provided in VS @??B& when using the ,IN- to S-, designer "ou
do not have to specif" the S-, /ueries to use when creating "our data model and access la"er.
Instead& "ou focus on defining "our entit" classes& how the" map to2from the database& and the
relationships between them. The ,IN- to S-, O42+ implementation will then take care of generating the
appropriate S-, e*ecution logic for "ou at runtime when "ou interact and use the data entities. 7ou can
use ,IN- /uer" s"nta* to e*pressivel" indicate how to /uer" "our data model in a strongl" t"ped wa".
C!eating Entit" Classes %!om a Database
If "ou alread" have a database schema defined& "ou can use it to /uickl" create ,IN- to S-, entit"
classes modeled off of it.
The easiest wa" to accomplish this is to open up a database in the Server E*plorer within Visual Studio&
select the Tables and Views "ou want to model in it& and drag2drop them onto the ,IN- to S-, designer
surface#

.hen "ou add the above @ tables 5)ategories and %roducts6 and > view 5Invoices6 from the Northwind
database onto the ,IN- to S-, designer surface& "ou<ll automaticall" have the following three entit"
classes created for "ou based on the database schema#

9sing the data model classes defined above& I can now run all of the code samples 5e*pect the S%4O)
one6 described in %art > of this ,IN- to S-, series. I don<t need to add an" additional code or
configuration in order to enable these /uer"& insert& update& delete& and server0side paging scenarios.
Naming and #l!ali0ation
One of the things "ou<ll notice when using the ,IN- to S-, designer is that it automaticall" plurali(es
the various table and column names when it creates entit" classes based on "our database schema. For
e*ample# the %roducts table in our e*ample above resulted in a %roduct class& and the )ategories
table resulted in a )ategor" class. This class naming helps make "our models consistent with the .NET
naming conventions& and I usuall" find having the designer fi* these up for me reall" convenient
5especiall" when adding lots of tables to "our model6.
If "ou don<t like the name of a class or propert" that the designer generates& though& "ou can alwa"s
override it and change it to an" name "ou want. 7ou can do this either b" editing the entit"2propert" name
in0line within the designer or b" modif"ing it via the propert" grid#

The abilit" to have entit"2propert"2association names be different from "our database schema ends up
being ver" useful in a number of cases. In particular#
>6 .hen "our backend database table2column schema names change. ;ecause "our entit" models can
have different names from the backend schema& "ou can decide to 'ust update "our mapping rules and
not update "our application or /uer" code to use the new table2column name.
@6 .hen "ou have database schema names that aren<t ver" clean. For e*ample& rather than use
auClname and auCfname for the propert" names on an entit" class& "ou can 'ust name them to
,astName and FirstName on "our entit" class and develop against that instead 5without having to
rename the column names in the database6.
.elationship 1sso$iations
.hen "ou drag ob'ects from the server e*plorer onto the ,IN- to S-, designer& Visual Studio will inspect
the primar" ke"2foreign ke" relationships of the ob'ects& and based on them automaticall" create
default relationship associations between the different entit" classes it creates. For e*ample& when I
added both the %roducts and )ategories tables from Northwind onto m" ,IN- to S-, designer "ou can
see that a one to man" relationship between the two is inferred 5this is denoted b" the arrow in the
designer6#
The above association will cause cause the %roduct entit" class to have a )ategor" propert" that
developers can use to access the )ategor" entit" for a given %roduct. It will also cause the )ategor"
class to have a %roducts collection that enables developers to retrieve all products within that )ategor".
If "ou don<t like how the designer has modeled or named an association& "ou can alwa"s override it. 8ust
click on the association arrow within the designer and access its properties via the propert" grid to
rename& delete or modif" it.
Dela"2La0" Loading
,IN- to S-, enables developers to specif" whether the properties on entities should be prefetched or
dela"2la("0loaded on first access. 7ou can customi(e the default pre0fetch2dela"0load rules for entit"
properties b" selecting an" entit" propert" or association in the designer& and then within the propert"0grid
set the 1ela" ,oaded propert" to true or false.
For a simple e*ample of when I<d want to0do this& consider the )ategor" entit" class we modeled
above. The categories table inside Northwind has a %icture column which stores a 5potentiall" large6
binar" image of each categor"& and I onl" want to retrieve the binar" image from the database when I<m
actuall" using it 5and not when doing a simpl" /uer" 'ust to list the categor" names in a list6.
I could configure the %icture propert" to be dela" loaded b" selecting it within the ,IN- to S-, designer
and b" settings its 1ela" ,oaded value in the propert" grid#
Note# In addition to configuring the default pre0fetch2dela" load semantics on entities& "ou can also
override them via code when "ou perform ,IN- /ueries on the entit" class 5I<ll show how to0do this in the
ne*t blog post in this series6.
Using Sto!ed #!o$ed!es
,IN- to S-, allows "ou to optionall" model stored procedures as methods on "our 1ata)onte*t class.
For e*ample& assume we<ve defined the simple S%4O) below to retrieve product information based on a
categor"I1#
I can use the server e*plorer within Visual Studio to drag2drop the S%4O) onto the ,IN- to S-, designer
surface in order to add a strongl"0t"ped method that will invoke the S%4O). If I drop the S%4O) on top
of the %roduct entit" in the designer& the ,IN- to S-, designer will declare the S%4O) to return an
IEnumerableD%roductE result#
I can then use either ,IN- -uer" S"nta* 5which will generate an adhoc S-, /uer"6 or alternativel" invoke
the S%4O) method added above to retrieve product entities from the database#
9sing S%4O)s to 9pdate21elete2Insert 1ata
;" default ,IN- to S-, will automaticall" create the appropriate S-, e*pressions for "ou when "ou
insert2update2delete entities. For e*ample& if "ou wrote the ,IN- to S-, code below to update some
values on a %roduct entit" instance#
;" default ,IN- to S-, would create and e*ecute the appropriate 9%1$TE statement for "ou when "ou
submitted the changes 5I<ll cover this more in a later blog post on updates6.
7ou can also optionall" define and use custom INSE4T& 9%1$TE& 1E,ETE sprocs instead. To configure
these& 'ust click on an entit" class in the ,IN- to S-, designer and within its propert"0grid click the ...
button on the 1elete2Insert29pdate values& and pick a particular S%4O) "ou<ve defined instead#
.hat is nice about changing the above setting is that it is done purel" at the mapping la"er of ,IN- to
S-, 0 which means the update code I showed earlier continues to work with no modifications re/uired.
This avoids developers using a ,IN- to S-, data model from having to change code even if the" later
decide to put in a custom S%4O) optimi(ation later.
Smma!"
,IN- to S-, provides a nice& clean wa" to model the data la"er of "our application. Once "ou<ve defined
"our data model "ou can easil" and efficientl" perform /ueries& inserts& updates and deletes against it.
9sing the built0in ,IN- to S-, designer within Visual Studio and Visual .eb 1eveloper E*press "ou can
create and manage "our data models for ,IN- to S-, e*tremel" fast. The ,IN- to S-, designer also
provides a lot of fle*ibilit" that enables "ou to customi(e the default behavior and override2e*tend the
s"stem to meet "our specific needs.
In upcoming posts I<ll be using the data model we created above to drill into /uer"ing& inserts& updates
and deletes further. In the update& insert and delete posts I<ll also discuss how to add custom
business2data validation logic to the entities we designed above to perform additional validation logic.
+ike Tault" also has a number of great ,IN- to S-, videos that I recommend checking out here. These
provide a great wa" to learn b" watching someone walkthrough using ,IN- to S-, in action.
!ope this helps&
Scott
LINQ to SQL (Part 3 - Querying our Dataase)
,ast month I started a blog post series covering ,IN- to S-,. ,IN- to S-, is a built0in O24+ 5ob'ect
relational mapping6 framework that ships in the .NET Framework A.B release& and which enables "ou to
easil" model relational databases using .NET classes. 7ou can then use ,IN- e*pressions to /uer" the
database with them& as well as update2insert2delete data from it.
;elow are the first two parts of m" ,IN- to S-, series#
%art ># Introduction to ,IN- to S-,
%art @# 1efining our 1ata +odel )lasses
In toda"<s blog post I<ll be going into more detail on how to use the data model we created in the %art @
post& and show how to use it to /uer" data within an $S%.NET pro'ect.
No!th(ind Database Modeled sing LINQ to SQL
In %art @ of this series I walked through how to create a ,IN- to S-, class model using the ,IN- to S-,
designer that is built0into VS @??F. ;elow is the class model that we created for the Northwind sample
database#
.et!ie/ing #!od$ts
Once we have defined our data model classes above& we can easil" /uer" and retrieve data from our
database. ,IN- to S-, enables "ou to do this b" writing ,IN- s"nta* /ueries against the
Northwind1ata)onte*t class that we created using the ,IN- to S-, designer above.
For e*ample& to retrieve and iterate over a se/uence of %roduct ob'ects I could write code like below#
In the /uer" above I have used a where clause in m" ,IN- s"nta* /uer" to onl" return those products
within a specific categor". I am using the )ategor"I1 of the %roduct to perform the filter.
One of the nice things above ,IN- to S-, is that I have a lot of fle*ibilit" in how I /uer" m" data& and I
can take advantage of the associations I<ve setup when modeling m" ,IN- to S-, data classes to
perform richer and more natural /ueries against the database. For e*ample& I could modif" the /uer" to
filter b" the product<s )ategor"Name instead of its )ategor"I1 b" writing m" ,IN- /uer" like so#
Notice above how I<m using the )ategor" propert" that is on each of the %roduct ob'ects to filter b" the
)ategor"Name of the )ategor" that the %roduct belongs to. This propert" was automaticall" created for
us b" ,IN- to S-, because we modeled the )ategor" and %roduct classes as having a man" to one
relationship with each other in the database.
For another simple e*ample of using our data model<s association relationships within /ueries& we could
write the below ,IN- /uer" to retrieve onl" those products that have had B or more orders placed for
them#
Notice above how we are using the Order1etails collection that ,IN- to S-, has created for us on each
%roduct class 5because of the > to man" relationship we modeled in the ,IN- to S-, designer6.
3isali0ing LINQ to SQL Qe!ies in the Debgge!
Ob'ect relational mappers like ,IN- to S-, handle automaticall" creating and e*ecuting the appropriate
S-, code for "ou when "ou perform a /uer" or update against their ob'ect model.
One of the biggest concerns2fears that developers new to O4+s have is but what S-, code is it actuall"
e*ecutingG One of the reall" nice things about ,IN- to S-, is that it makes it super eas" to see e*act$y
what S-, code it is e*ecuting when "ou run "our application within the debugger.
Starting with ;eta@ of Visual Studio @??F "ou can use a new ,IN- to S-, visuali(er plug0in to easil" see
5and test out6 an" ,IN- to S-, /uer" e*pression. Simpl" set a breakpoint and then hover over a ,IN- to
S-, /uer" and click the magnif" glass to pull up its e*pression visuali(er within the debugger#
This will then bring up a dialog that shows "ou the e*act S-, that ,IN- to S-, will use when e*ecuting
the /uer" to retrieve the %roduct ob'ects#
If "ou press the E*ecute button within this dialog it will allow "ou to evaluate the S-, directl" within the
debugger and see the e*act data results returned from the database#
This obviousl" makes it super eas" to see precisel" what S-, /uer" logic ,IN- to S-, is doing for "ou.
Note that "ou can optionall" override the raw S-, that ,IN- to S-, e*ecutes in cases where "ou want to
change it 0 although in HFI of scenarios I think "ou<ll find that the S-, code that ,IN- to S-, e*ecutes is
reall"& reall" good.
Databinding LINQ to SQL Qe!ies to 1S#4NE) Cont!ols
,IN- /ueries return results that implement the IEnumerable interface 0 which is also an interface that
$S%.NET server controls support to databind ob'ect. .hat this means is that "ou can databind the results
of an" ,IN-& ,IN- to S-,& or ,IN- to 3+, /uer" to an" $S%.NET control.
For e*ample& we could declare an Dasp#gridviewE control in a .asp* page like so#
I could then databind the result of the ,IN- to S-, /uer" we wrote before to the :ridView like so#
This will then generate a page that looks like below#
Shaping o! Qe!" .eslts
4ight now when we are evaluating our product /uer"& we are retrieving b" default all of the column data
needed to populate the %roduct entit" classes.
For e*ample& this /uer" to retrieve products#
4esults in all of this data being returned#

Often we onl" want to return a subset of the data about each product. .e can use the new data shaping
features that ,IN- and the new )J and V; compilers support to indicate that we onl" want a subset of
the data b" modif"ing our ,IN- to S-, /uer" like so#
This will result in onl" this data subset being returned from our database 5as seen via our debug
visuali(er6#
.hat is cool about ,IN- to S-, is that I can take full advantage of m" data model class
associations when shaping m" data. This enables me to e*press reall" useful 5and ver" efficient6 data
/ueries. For e*ample& the below /uer" retrieves the I1 and Name from the %roduct entit"& the total
number of orders that have been made for the %roduct& and then sums up the total revenue value of each
of the %roduct<s orders#
The e*pression to the right of the 4evenue propert" above is an e*ample of using the Sum e*tension
method provided b" ,IN-. It takes a ,ambda e*pression that returns the value of each product order
item as an argument.
,IN- to S-, is smart and is able to convert the above ,IN- e*pression to the below S-, when it is
evaluated 5as seen via our debug visuali(er6#
The above S-, causes all of the NumOrders and 4evenue value computations to be done inside the
S-, server& and results in onl" the below data being retrieved from the database 5making it reall" fast6#
.e can then databind the result se/uence against our :ridView control to generate prett" 9I#
;T. 0 in case "ou were wondering& "ou do get full intellisense within VS @??F when writing these t"pes of
,IN- shaping /ueries#
In the e*ample above I<m declaring an anon"mous t"pe that uses ob'ect initiali(ation to shape and define
the result structure. .hat is reall" cool is that VS @??F provides full intellisense& compilation checking&
and refactoring support when working against these anon"mous result se/uences as well#

#aging o! Qe!" .eslts
One of the common needs in web scenarios is to be able to efficientl" build data paging 9I. ,IN-
provides built0in support for two e*tension methods that make this both eas" and efficient 0 the Skip56 and
Take56 methods.
.e can use the Skip56 and Take56 methods below to indicate that we onl" want to return >? product
ob'ects 0 starting at an initial product row that we specif" as a parameter argument#
Note above how I did not add the Skip56 and Take56 operator on the initial products /uer" declaration 0 but
instead added it later to the /uer" 5when binding it to m" :ridView datasource6. %eople often ask me but
doesn<t this mean that the /uer" first grabs all the data from the database and then does the paging in the
middle tier 5which is bad6G No. The reason is that ,IN- uses a deferred e*ecution model 0 which means
that the /uer" doesn<t actuall" e*ecute until "ou tr" and iterate over the results.
One of the benefits of this deferred e*ecution model is that it enables "ou to nicel" compose /ueries
across multiple code statements 5which improves code readabilit"6. It also enables "ou to compose
/ueries out of other /ueries 0 which enables some ver" fle*ible /uer" composition and re0use scenarios.
Once I have the ;ind%roduct56 method defined above& I can write the code below in m" page to retrieve
the starting inde* from the /uer"string and cause the products to be paged and displa"ed in the gridview#
This will then give us a products page& filtered to list onl" those products with more than B orders& showing
d"namicall" computed product data& and which is pageable via a /uer"string argument#
Note# .hen working against S-, @??B& ,IN- to S-, will use the 4O.CN9+;E456 S-, function to
perform all of the data paging logic in the database. This ensures that onl" the >? rows of data we want
in the current page view are returned from the database when we e*ecute the above code#
This makes it efficient and eas" to page over large data se/uences.
Smma!"
!opefull" the above walkthrough provides a good overview of some of the cool data /uer" opportunities
that ,IN- to S-, provides. To learn more about ,IN- e*pressions and the new language s"nta*
supported b" the )J and V; compilers with VS @??F& please read these earlier posts of mine#
$utomatic %roperties& Ob'ect Initiali(er and )ollection Initiali(ers
E*tension +ethods
,ambda E*pressions
-uer" S"nta*
$non"mous T"pes
In m" ne*t post in this ,IN- to S-, series I<ll cover how we can cleanl" add validation logic to our data
model classes& and demonstrate how we can use it to encapsulate business logic that e*ecutes ever"
time we update& insert& or delete our data. I<ll then cover more advanced la(" and eager loading /uer"
scenarios& how to use the new Dasp#,IN-1ataSourceE control to support declarative databinding of
$S%.NET controls& optimistic concurrenc" error resolution& and more.
!ope this helps&
Scott
LINQ to SQL (Part ! - U"dating our Dataase)
Over the last few weeks I<ve been writing a series of blog posts that cover ,IN- to S-,. ,IN- to S-, is
a built0in O24+ 5ob'ect relational mapper6 that ships in the .NET Framework A.B release& and which
enables "ou to easil" model relational databases using .NET classes. 7ou can use ,IN- e*pressions to
/uer" the database with them& as well as update2insert2delete data.
;elow are the first three parts of m" ,IN- to S-, series#
%art ># Introduction to ,IN- to S-,
%art @# 1efining our 1ata +odel )lasses
%art A# -uer"ing our 1atabase
In toda"<s blog post I<ll cover how we we can use the data model we created earlier& and use it to update&
insert& and delete data. I<ll also show how we can cleanl" integrate business rules and custom validation
logic with our data model.
No!th(ind Database Modeled sing LINQ to SQL
In %art @ of this series I walked through how to create a ,IN- to S-, class model using the ,IN- to S-,
designer that is built0into VS @??F. ;elow is a class model created for the Northwind sample database
and which I<ll be using in this blog post#


.hen we designed our data model using the ,IN- to S-, data designer above we defined five data
model classes# %roduct& )ategor"& )ustomer& Order and Order1etail. The properties of each class map
to the columns of a corresponding table in the database. Each instance of a class entit" represents a row
within the database table.
.hen we defined our data model& the ,IN- to S-, designer also created a custom 1ata)onte*t class
that provides the main conduit b" which we<ll /uer" our database and appl" updates2changes. In the
e*ample data model we defined above this class was named Northwind1ata)onte*t. The
Northwind1ata)onte*t class has properties that represent each Table we modeled within the database
5specificall"# %roducts& )ategories& )ustomers& Orders& Order1etails6.
$s I covered in %art A of this blog series& we can easil" use ,IN- s"nta* e*pressions to /uer" and
retrieve data from our database using this Northwind1ata)onte*t class. ,IN- to S-, will then
automaticall" translate these ,IN- /uer" e*pressions to the appropriate S-, code to e*ecute at runtime.
For e*ample& I could write the below ,IN- e*pression to retrieve a single %roduct ob'ect b" searching on
the %roduct name#
I could then write the ,IN- /uer" e*pression below to retrieve all products from the database that haven<t
"et had an order placed for them& and which also cost more than K>??#
Note above how I am using the Order1etails association for each product as part of the /uer" to onl"
retrieve those products that have not had an" orders placed for them.
Change )!a$5ing and DataContext4SbmitChanges6)
.hen we perform /ueries and retrieve ob'ects like the product instances above& ,IN- to S-, will b"
default keep track of an" changes or updates we later make to these ob'ects. .e can make an" number
of /ueries and changes we want using a ,IN- to S-, 1ata)onte*t& and these changes will all be tracked
together.
Note: LINQ to +QL c&ange trac,ing &aens on t&e consu!ing ca$$er side ( and not in t&e data"ase.
T&is !eans t&at you are not consu!ing any data"ase resources #&en using it% nor do you need to
c&ange-insta$$ anyt&ing in t&e data"ase to ena"$e it.
$fter making the changes we want to the ob'ects we<ve retrieved from ,IN- to S-,& we can then
optionall" call the Submit)hanges56 method on our 1ata)onte*t to appl" the changes back to the
database. This will cause ,IN- to S-, to d"namicall" calculate and e*ecute the appropriate S-, code to
update the database.
For e*ample& I could write the below code to update the price and J of units in stock of the )hai product
in the database#
.hen I call northwind.Submit)hanges56 above& ,IN- to S-, will d"namicall" construct and e*ecute a
S-, 9%1$TE statement that will update the two product propert" values we modified above.
I could then write the below code to loop over unpopular& e*pensive products and set the 4eorder,evel
propert" of them to (ero#
.hen I call northwind.Submit)hanges56 above& ,IN- to S-, will calculate and e*ecute an appropriate set
of 9%1$TE statements to modif" the products who had their 4eorder,evel propert" changed.
Note that if a %roduct<s propert" values weren<t changed b" the propert" assignments above& then the
ob'ect would not be considered changed and ,IN- to S-, would therefore not e*ecute an update for that
product back to the database. For e*ample 0 if the )hai product<s unitprice was alread" K@ and the
number of units in stock was L& then calling Submit)hanges56 would not cause an" database update
statements to e*ecute. ,ikewise& onl" those products in the second e*ample whose 4eorder,evel was
not alread" ? would be updated when the Submit)hanges56 method was called.
Inse!t and Delete Examples
In addition to updating e*isting rows in the database& ,IN- to S-, obviousl" also enables "ou to insert
and delete data. 7ou can accomplish this b" adding2removing data ob'ects from the 1ata)onte*t<s table
collections& and b" then calling the Submit)hanges56 method. ,IN- to S-, will keep track of these
additions2removals& and automaticall" e*ecute the appropriate S-, INSE4T or 1E,ETE statements when
Submit)hanges56 is invoked.
Inserting a New %roduct
I can add a new product to m" database b" creating a new %roduct class instance& setting its properties&
and then b" adding it to m" 1ata)onte*t<s %roducts collection#
.hen we call Submit)hanges56 above a new row will be created in our products table.
1eleting %roducts
8ust as I can e*press that I want to add a new %roduct to the database b" adding a %roduct ob'ect into
the 1ata)onte*t<s %roducts collection& I can likewise e*press that I want to delete a product from a
database b" removing it from the 1ata)onte*t<s %roducts collection#
Note above how I<m retrieving a se/uence of discontinued products that no one has ever ordered using a
,IN- /uer"& and then passing it to the 4emove$ll56 method on m" 1ata)onte*t<s %roducts collection.
.hen we call Submit)hanges56 above all of these %roduct rows will be deleted from our products table.
Updates a$!oss .elationships
.hat makes O24 mappers like ,IN- to S-, e*tremel" fle*ible is that the" enable us to easil" model
cross0table relationships across our data model. For e*ample& I can model each %roduct to be in a
)ategor"& each Order to contain Order1etails for line0items& associate each Order1etail line0item with a
%roduct& and have each )ustomer contain an associated set of Orders. I covered how to construct and
model these relationships in %art @ of this blog series.
,IN- to S-, enables me to take advantage of these relationships for both /uer"ing and updating m"
data. For e*ample& I could write the below code to create a new %roduct and associate it with an e*isting
;everages categor" in m" database like so#
Note above how I<m adding the %roduct ob'ect into the )ategor"<s %roducts collection. This will indicate
that there is a relationship between the two ob'ects& and cause ,IN- to S-, to automaticall" maintain the
foreign0ke"2primar" ke" relationship between the two when I call Submit)hanges56.
For another e*ample of how ,IN- to S-, can help manage cross0table relationships for us and help
clean up our code& let<s look at an e*ample below where I<m creating a new Order for an e*isting
customer. $fter setting the re/uired ship date and freight costs for the order& I then create two order line0
item ob'ects that point to the products the customer is ordering. I then associate the order with the
customer& and update the database with all of the changes.
$s "ou can see& the programming model for performing all of this work is e*tremel" clean and ob'ect
oriented.
)!ansa$tions
$ transaction is a service provided b" a database 5or other resource manager6 to guarantee that a series
of individual actions occur atomicall" 0 meaning either the" all succeed or the" all don<t& and if the" don<t
then the" are all automaticall" undone before an"thing else is allowed to happen.
.hen "ou call Submit)hanges56 on "our 1ata)onte*t& the updates will alwa"s be wrapped in a
Transaction. This means that "our database will never be in an inconsistent state if "ou perform multiple
changes 0 either all of the changes "ou<ve made on "our 1ata)onte*t are saved& or none of them are.
If no transaction is alread" in scope& the ,IN- to S-, 1ata)onte*t ob'ect will automaticall" start a
database transaction to guard updates when "ou call Submit)hanges56. $lternativel"& ,IN- to S-, also
enables "ou to e*plicitl" define and use "our own TransactionScope ob'ect 5a feature introduced in .NET
@.?6. This makes it easier to integrate ,IN- to S-, code with e*isting data access code "ou alread"
have. It also means that "ou can enlist non0database resources into the transaction 0 for e*ample# "ou
could send off a +S+- message& update the file0s"stem 5using the new transactional file0s"stem
support6& etc 0 and scope all of these work items in the same transaction that "ou use to update "our
database with ,IN- to S-,.
3alidation and 7siness Logi$
One of the important things developers need to think about when working with data is how to incorporate
validation and business rule logic. Thankfull" ,IN- to S-, supports a variet" of wa"s for developers to
cleanl" integrate this with their data models.
,IN- to S-, enables "ou to add this validation logic once 0 and then have it be honored regardless of
where2how the data model "ou<ve created is used. This avoids "ou having to repeat logic in multiple
places& and leads to a much more maintainable and clean data model.
S$hema 3alidation Sppo!t
.hen "ou define "our data model classes using the ,IN- to S-, designer in VS @??F& the" will b"
default be annotated with some validation rules inferred from the schema of the tables in the database.
The datat"pes of the properties in the data model classes will match the datat"pes of the database
schema. This means "ou will get compile errors if "ou attempt to assign a boolean to a decimal value& or
if "ou attempt to implicitl" convert numeric t"pes incorrectl".
If a column in the database is marked as being nullable& then the corresponding propert" in the data
model class created b" the ,IN- to S-, designer will be a nullable t"pe. )olumns not marked as
nullable will automaticall" raise e*ceptions if "ou attempt to persist an instance with a null value. ,IN- to
S-, will likewise ensure that identit"2uni/ue column values in the database are correctl" honored.
7ou can obviousl" use the ,IN- to S-, designer to override these default schema driven validation
settings if "ou want 0 but b" default "ou get them automaticall" and don<t have to take an" additional steps
to enable them. ,IN- to S-, also automaticall" handles escaping S-, values for "ou 0 so "ou don<t
need to worr" about S-, in'ection attacks when using it.
Cstom #!ope!t" 3alidation Sppo!t
Schema driven datat"pe validation is useful as a first step& but usuall" isn<t enough for real0world
scenarios.
)onsider for e*ample a scenario with our Northwind database where we have a %hone propert" on the
)ustomer class which is defined in the database as an nvarchar. 1evelopers using ,IN- to S-, could
write code like below to update it using a valid telephone number#
The challenge that we will run into with our application& however& is that the below code is also legal from
a pure S-, schema perspective 5because it is still a string even though it is not a valid phone number6#
To prevent bogus phone numbers from being added into our database& we can add a custom propert"
validation rule to our )ustomer data model class. $dding a rule to validate phone numbers using this
feature is reall" eas". $ll we need to0do is to add a new partial class to our pro'ect that defines the
method below#
The code above takes advantage of two characteristics of ,IN- to S-,#
>6 $ll classes created b" the ,IN- to S-, designer are declared as partial classes 0 which means that
developers can easil" add additional methods& properties& and events to them 5and have them live in
separate files6. This makes it ver" eas" to augment the data model classes and 1ata)onte*t classes
created b" the ,IN- to S-, designer with validation rules and additional custom helper methods that "ou
define. No configuration or code wire0up is re/uired.
@6 ,IN- to S-, e*poses a number of custom e*tensibilit" points in its data model and 1ata)onte*t
classes that "ou can use to add validation logic before and after things take place. +an" of these
e*tensibilit" points utili(e a new language feature called partial methods that is being introduced with V;
and )J in VS @??F ;eta@. .es 1"er from the )J team has a good e*planation of how partial methods
works in this blog post here.
In m" validation e*ample above& I<m using the On%hone)hanging partial method that is e*ecuted an"time
someone programmaticall" sets the %hone propert" on a )ustomer ob'ect. I can use this method to
validate the input however I want 5in this case I<m using a regular e*pression6. If ever"thing passes
successfull"& I 'ust return from the method and ,IN- to S-, will assume that the value is valid. If there
are an" issues with the value& I can raise an e*ception within the validation method 0 which will prevent
the assignment from taking place.
Cstom Entit" 8b9e$t 3alidation Sppo!t
%ropert" level validation as used in the scenario above is ver" useful for validating individual properties on
a data model class. Sometimes& though& "ou want2need to validate multiple propert" values on an ob'ect
against each other.
)onsider for e*ample a scenario with an Order ob'ect where "ou set both the Order1ate and the
4e/uired1ate properties#
The above code is legal from a pure S-, database perspective 0 even though it makes absolutel" no
sense for the re/uired deliver" date of the new order to be entered as "esterda".
The good news is that ,IN- to S-, in ;eta@ makes it eas" for us to add custom entit" level validation
rules to guard against mistakes like this from happening. .e can add a partial class for our Order entit"
and implement the OnValidate56 partial method that will be invoked prior to the entit"<s values being
persisted into the database. .ithin this validation method we can then access and validate all of the data
model class properties#
.ithin this validation method I can check an" of the entit"<s propert" values 5and even obtain read0onl"
access to its associated ob'ects6& and raise an e*ception as needed if the values are incorrect. $n"
e*ceptions raised from the OnValidate56 method will abort an" changes from being persisted in the
database& and rollback all other changes in the transaction.
Cstom Entit" Inse!t2Update2Delete Method 3alidation
There are times when "ou want to add validation logic that is specific to insert& update or delete
scenarios. ,IN- to S-, in ;eta@ enables this b" allowing "ou to add a partial class to e*tend "our
1ata)onte*t class and then implement partial methods to customi(e the Insert& 9pdate and 1elete logic
for "our data model entities. These methods will be called automaticall" when "ou invoke
Submit)hanges56 on "our 1ata)onte*t.
7ou can add appropriate validation logic within these methods 0 and if it passes then tell ,IN- to S-, to
continue with persisting the relevant changes to the database 5b" calling the 1ata)onte*t<s
E*ecute1"namic37M method6#
.hat is nice about adding the above methods is that the appropriate ones are automaticall" invoked
regardless of the scenario logic that caused the data ob'ects to be created2updated2deleted. For
e*ample& consider a simple scenario where we create a new Order and associate it with an e*isting
)ustomer#
.hen we call northwind.Submit)hanges56 above& ,IN- to S-, will determine that it needs to persist a
new Order ob'ect& and our InsertOrder partial method will automaticall" be invoked.
1d/an$ed: Loo5ing at the Enti!e Change List +o! the )!ansa$tion
There are times when adding validation logic can<t be done purel" b" looking at individual
insert2update2delete operations 0 and instead "ou want to be able to look at the entire change list of
operations that are occurring for a transaction.
Starting with ;eta@ of .NET A.B& ,IN- to S-, now enables "ou to get access to this change list b" calling
the public 1ata)onte*t.:et)hange,ist56 method. This will return back a )hange,ist ob'ect that e*poses
collections of each addition& removal and modification that has been made.
One approach "ou can optionall" emplo" for advanced scenarios is to sub0class the 1ata)onte*t class
and override its Submit)hange56 method. 7ou can then retrieve the )hange,ist56 for the update operation
and perform an" custom validation "ou want prior to e*ecuting it#

The above scenario is a somewhat advanced one 0 but it is nice to know that "ou alwa"s have the abilit"
to drop0down and take advantage of it if needed.
:andling Simltaneos Changes (ith 8ptimisti$ Con$!!en$"
One of the things that developers need to think about in multi0user database s"stems is how to handle
simultaneous updates of the same data in the database. For e*ample& assume two users retrieve a
product ob'ect within an application& and one of the users changes the 4eorder,evel to ? while the other
changes it to >. If both users then attempt to save the product back to the database& the developer needs
to decide how to handle the change conflicts.
One approach is to 'ust let the last writer win 0 which means that the first user<s submitted value will be
lost without the end0users reali(ing it. This is usuall" considered a poor 5and incorrect6 application
e*perience.
$nother approach which ,IN- to S-, supports is to use an optimistic concurrenc" model 0 where ,IN- to
S-, will automaticall" detect if the original values in the database have been updated b" someone else
prior to the new values being persisted. ,IN- to S-, can then provide a conflict list of changed values to
the developer and enable them to either reconcile the differences or provide the end0user of the
application with 9I to indicate what the" want to0do.
I<ll cover how to use optimistic concurrenc" with ,IN- to S-, in a future blog post.
Using S#.8Cs o! Cstom SQL Logi$ +o! Inse!t2Update2Delete S$ena!ios
One of the /uestions that developers 5and especiall" 1;$s6 who are used to writing S%4O)s with
custom S-, usuall" ask when seeing ,IN- to S-, for the first time is 0 but how can I have complete
control of the underl"ing S-, that is e*ecutedG
The good news is that ,IN- to S-, has a prett" fle*ible model that enables developers to override the
d"namic S-, that is automaticall" e*ecuted b" ,IN- to S-,& and instead call custom insert& update&
delete S%4O)s that the" 5or a 1;$6 define themselves.
.hat is reall" nice is that "ou can start off b" defining "our data model and have ,IN- to S-,
automaticall" handle the insert& update& delete S-, logic for "ou. 7ou can then at a later point customi(e
the data model to use "our own custom S%4O)s or S-, for updates 0 without having to change an" of
the application logic that is using "our data model& nor would "ou have to change an" of the validation or
business rules logic supporting it 5all of this sta"s the same6. This provides a lot of fle*ibilit" in how "ou
build "our application.
I<ll cover how to customi(e "our data models to use S%4O)s or custom S-, in a future blog post.
Smma!"
!opefull" the above post provides a good summar" of how "ou can easil" use ,IN- to S-, to update
"our database& and cleanl" integrate validation and business logic with "our data models. I think "ou<ll
find that ,IN- to S-, can dramaticall" improve "our productivit" when working with data& and enable "ou
to write e*tremel" clean ob'ect0oriented data access code.
In upcoming blog posts in this series I<ll cover the new Dasp#lin/datasourceE control coming in .NET A.B&
and talk about how "ou can easil" build data 9I in $S%.NET that takes advantage of ,IN- to S-, data
models. I<ll also cover some more specific ,IN- to S-, programming concepts including optimistic
concurrenc"& la(" and eager loading& table mapping inheritance& custom S-,2S%4O) usage& and more.
!ope this helps&
Scott
LINQ to SQL (Part # - $inding UI using t%e
&SP'Lin(DataSour)e Control)
Over the last few weeks I<ve been writing a series of blog posts that cover ,IN- to S-,. ,IN- to S-, is
a built0in O24+ 5ob'ect relational mapper6 that ships in the .NET Framework A.B release& and which
enables "ou to easil" model relational databases using .NET classes. 7ou can use ,IN- e*pressions to
/uer" the database with them& as well as update2insert2delete data.
;elow are the first four parts of m" ,IN- to S-, series#
%art ># Introduction to ,IN- to S-,
%art @# 1efining our 1ata +odel )lasses
%art A# -uer"ing our 1atabase
%art L# 9pdating our 1atabase
In these previous ,IN- to S-, blog posts I focused on how "ou can programmaticall" use ,IN- to S-,
to easil" /uer" and update data within a database.
In toda"<s blog post I<ll cover the new Dasp#,in/1ataSourceE control that is shipping as part of $S%.NET
in the upcoming .NET A.B release. This control is a new datasource control for $S%.NET 5like the
Ob'ect1ataSource and S-,1ataSource controls that shipped with $S%.NET @.?6 which makes
declarativel" binding $S%.NET 9I controls to ,IN- to S-, data models super eas".
Sample 1ppli$ation We;ll be 7ilding
The simple data editing web application I<ll walkthrough building in this tutorial is a basic data
entr"2manipulation front0end for products within a database#
The application will support the following end0user features#
>. $llow users to filter the products b" categor"
@. $llow users to sort the product listing b" clicking on a column header 5Name& %rice& 9nits In
Stock& etc6
A. $llow users to skip2page over multiple product listings 5>? products per page6
L. $llow users to edit and update an" of the product details in0line on the page
B. $llow users to delete products from the list
The web application will be implemented with a clean ob'ect0oriented data model built using the ,IN- to
S-, O4+.
$ll of the business rules and business validation logic will be implemented in our data model tier 0 and not
within the 9I tier or in an" of the 9I pages. This will ensure that# >6 a consistent set of business rules are
used ever"where within the application& @6 we write less code and don<t repeat ourselves& and A6 we can
easil" modif"2adapt our business rules at a later date and not have to update them in do(ens of different
places across our application.
.e will also take advantage of the built0in paging2sorting support within ,IN- to S-, to ensure that
features like the product listing paging2sorting are performed not in the middle0tier& but rather in the
database 5meaning onl" >? products are retrieved from the database at an" given time 0 we are not
retrieving thousands of rows and doing the sorting2paging within the web0server6.
What is the <asp:Lin=DataSo!$e> $ont!ol and ho( does it help?
The Dasp#,in/1ataSourceE control is an $S%.NET control that implements the 1ataSource)ontrol
pattern introduced with $S%.NET @.?. It is similar to the Ob'ect1ataSource and S/l1ataSource controls in
that it can be used to declarativel" bind other $S%.NET controls on a page to a datasource. .here it
differs is that instead of binding directl" to a database 5like the S/l1ataSource6 or to a generic class 5like
the Ob'ect1ataSource6& the Dasp#lin/datasourceE is designed to bind against a ,IN- enabled data
model.
One of the benefits of using the Dasp#lin/datasourceE control is that it leverages the fle*ibilit" that ,IN-
based O4+s provide. 7ou don<t need to define custom /uer"2insert2update2delete methods for the
datasource to call 0 instead "ou can point the Dasp#lin/datasourceE control at "our data model& identif"
what entit" table "ou want it to work against& and then bind an" $S%.NET 9I control against the
Dasp#lin/datasourceE and have them work with it.
For e*ample& to get a basic product listing 9I on m" page that works against %roduct entities within a
,IN- to S-, data model& I could simpl" declare a Dasp#lin/datasourceE on m" page that points to m"
,IN- to S-, dataconte*t class& and identif" the entities 5for e*ample# %roducts6 in the ,IN- to S-, data
model I want to bind against. I could then point a :ridView at it 5b" settings its 1ataSourceI1 propert"6 to
get a grid0like view of the %roduct content#
.ithout having to0do an"thing else& I can run the page and have a listing of m" %roduct data with built0in
support for paging and sorting over the data. I can add a edit2delete button on the :rid and automaticall"
have update support as well. I don<t need to add an" methods& map an" parameters& or write an" code
for the Dasp#,in/1ataSourceE to handle both these /uer"ing and updating scenarios 0 it can work against
the ,IN- to S-, data model we point it against and do these operations automaticall". .hen updates
are made& the ,IN- to S-, O4+ will automaticall" ensure that all business rules and validation logic
we<ve added 5as partial methods6 to the ,IN- to S-, data model pass before persisting an"thing to the
database.
Important: T&e "eauty o. LINQ and LINQ to +QL is t&at it o")ious$y isn't tied to "eing used on$y in /I
scenarios ( or #it& articu$ar /I "inding contro$s $i,e t&e Linq0ata+ource. 1s you')e seen in !y re)ious
osts in t&is series% #riting code using t&e LINQ to +QL O23 is e*tre!e$y c$ean. 4ou can a$#ays #rite
custo! /I code to direct$y #or, against your LINQ to +QL data !ode$ i. you re.er% or #&en you .ind a /I
scenario t&at isn't articu$ar$y suited to using t&e 5as:$inqdatasource6.
The below sections walkthrough using ,IN- to S-, and the Dasp#,in/1ataSourceE control to build the
web application scenario I defined above.
Step 1: De+ine o! Data Model
.e<ll begin working on the application b" first defining the data model we<ll use to represent our
database.
I discussed how to create a ,IN- to S-, data model using VS @??F<s ,IN- to S-, designer in %art @ of
this series. ;elow is a screenshot of the data model classes I can /uickl" create using the ,IN- to S-,
designer to model the Northwind sample database#
.e<ll revisit our data model in Step B of this tutorial below when we add some business validation rules to
it. ;ut to begin with we<ll 'ust use the above data model as0is to build our 9I.
Step &: C!eating a 7asi$ #!od$t Listing
.e<ll start our 9I b" creating an $S%.NET page with a Dasp#gridviewE control on it and use some )SS to
st"le it#
.e could write code to programmaticall" bind our data model to the :ridView 5like I did in %art A of this
series6& or alternativel" I could use the new Dasp#lin/datasourceE control to bind the :ridView to our data
model.
VS @??F includes build0in designer support to make it eas" to connect up our :ridView 5or an" other
$S%.NET server control6 to ,IN- data. To bind our grid above to the data model we created earlier& we
can switch into design0view& select the :ridView& and then select the New 1ata Source... option within
the )hoose 1ata Source# drop0down#
This will bring up a dialog bo* that lists the available datasource options to create. Select the new ,IN-
option in the dialog bo* and name the resulting Dasp#lin/datasourceE control "ou want to create#
The Dasp#lin/datasourceE designer will then displa" the available ,IN- to S-, 1ata)onte*t classes that
"our application can use 5including those in class libraries that "ou are referencing6#
.e<ll want to select the data model we created with the ,IN- to S-, designer earlier. .e<ll then want to
select the table within our data model that we want to be the primar" entit" for the Dasp#lin/datasourceE
to bind against. For this scenario we<ll want to select the %roducts entit" class we built. .e<ll also want
to select the $dvanced button and enable updates and deletes for the datasource#
.hen we click the Finish button above& VS @??F will declare a Dasp#lin/datasourceE within our .asp*
page& and update the Dasp#gridviewE to point to it 5via its 1ataSourceI1 propert"6. It will also
automaticall" provide column declarations in the :rid based on the schema of the %roduct entit" we
choose to bind against#
.e can then pull up the smart task conte*t 9I of the :ridView and indicate that we want to enable
paging& sorting& editing and deleting on it#
.e can then press FB to run our application& and have a product listing page with full paging and sorting
support 5note the paging inde*es at the bottom of the grid below6#
.e can also select the edit or delete button on each row to update the data#
If we flip into source view on the page& we<ll see that the markup of the page contains the content below.
The Dasp#lin/datasourceE control points at the ,IN- to S-, 1ata)onte*t we created earlier& as well as
the entit" table we want to bind against. The :ridView then points at the Dasp#lin/datasourceE control
5via its 1ataSourceI16 and indicates which columns should be included in the grid& what their header te*t
should be& as well as what sort e*pression to use when the column header is selected.
Now that we have the basics of our web 9I working against our ,IN- to S-, data0model& we can go
ahead and further customi(e the 9I and behavior.
Step ': Cleaning p o! Colmns
Our :ridView above has a lot of columns defined within it& and two of the column values 5the SupplierI1
and the )ategor"I16 are currentl" foreign0ke" numbers 00 which certainl" isn<t the ideal wa" to represent
them to an end0user.
4emoving 9nnecessar" )olumns
.e can start cleaning up our 9I b" deleting a few of the columns we don<t need. I can do this in source
mode 5simpl" nuke the Dasp#boundfieldE declarations6 or in designer mode 5'ust click on the column in the
designer and choose the 4emove task6. For e*ample& we could remove the -uantit"%er9nit column
below and re0run our application to get this slightl" cleaner 9I#
If "ou have used the Dasp#Ob'ect1ataSourceE control before and e*plicitl" passed update parameters to
update methods 5the default when using 1ataSet based Table$dapters6 one of the things "ou know can
be painful is that "ou have to change the method signatures of "our Table$dapter<s update methods when
the parameters based b" "our 9I are modified. For e*ample# if we deleted a column in our grid 5like
above6& we<d end up having to modif" our Table$dapter to support update methods without that
parameter.
One of the reall" nice things about the Dasp#,in/1ataSourceE control is that "ou do not need to0do these
t"pes of changes. Simpl" delete 5or add6 a column from "our 9I and re0run the application 0 no other
changes are re/uired. This makes changing web 9I built using the Dasp#,in/1ataSourceE much easier&
and enables much faster scenarios iterations within an application.
)leaning up the SupplierI1 and )ategor"I1 )olumns
)urrentl" we are displa"ing the foreign0ke" integer values in our :ridView for the Supplier and
)ategor" of each %roduct#
.hile accurate from a data model perspective& it isn<t ver" end0user friendl". .hat I reall" want to0do is to
displa" the )ategor"Name and SupplierName instead& and provide a drop0downlist while in Edit mode to
enable end0users to easil" associate the SupplierI1 and )ategor"I1 values.
I can change the :ridView to displa" the Supplier Name and )ategor" Name instead of the I1<s b"
replacing the default Dasp#;oundFieldE in our :ridView with an Dasp#TemplateFieldE. .ithin this
TemplateField I can add an" content I want to customi(e the look of the column.
In the source code below I<m going to take advantage of the fact that each %roduct class in the ,IN- to
S-, data model we created has a Supplier and )ategor" propert" on it. .hat this means is that I can
easil" databind their Supplier.)ompan"Name and )ategor".)ategor"Name sub0properties within our
:rid#

$nd now when I run the application I get the human readable )ategor" and Supplier name values
instead#
To get drop0down list 9I for the Supplier and )ategor" columns while in Edit0+ode in the :rid& I will
first add two additional Dasp#,in/1ataSourceE controls to m" page. I will configure these to bind against
the )ategories and Suppliers within the ,IN- to S-, data model we created earlier#
I can then go back to the Dasp#TemplateFieldE columns we added to our :ridView earlier and customi(e
their edit appearance 5b" specif"ing an EditItemTemplate6. .e<ll customi(e each column to have a
dropdownlist control when in edit mode& where the available values in the dropdownlists are pulled from
the categories and suppliers datasource controls above& and where we two0wa" databind the selected
value to the %roduct<s SupplierI1 and )ategor"I1 foreign ke"s#
$nd now when end0users click edit in the :ridView& the" are presented a drop0down list of all valid
Supplier<s to associate the product with#
$nd when the" hit save the %roduct is updated appropriatel" 5the :ridView will use the 1rop1own,ist<s
currentl" selected value to bind the SupplierI16.
Step *: %ilte!ing o! #!od$t Listing
4ather than show all products within the database& we can update our 9I to include a dropdownlist that
allows the user to filter the products b" a particular categor".
;ecause we alread" added a Dasp#,in/1ataSourceE control to the page earlier that references our
)ategories within our ,IN- to S-, data model& all I need to0do to create a drop0downlist control at the top
of the page that binds against this. For e*ample#
.hen I run the page I<ll now get a filter dropdownlist of all categories at the top of the page#
+" last step is to configure the :ridView to onl" show those %roducts in the categor" the end0user selects
from the dropdownlist. The easiest wa" to0do this is b" selecting the )onfigure 1ataSource option in
the :ridView smart task#
This will bring me back to the Dasp#,in/1ataSourceE control<s design0time 9I that we used at the ver"
beginning of this tutorial. I can select the .here button within this to add a binding filter to the
datasource control. I can add an" number of filter e*pressions& and declarativel" pull the values to filter
b" from a variet" of places 5for e*ample# from the /uer"string& from form0values& from other controls on
the page& etc6#
$bove I<m going to choose to filter b" the %roducts b" their )ategor"I1 value& and then retrieve this
)ategor"I1 from the 1rop1own,ist control we 'ust created on our page#
.hen we hit finish& the Dasp#lin/datasourceE control in our page will have been updated to reflect this
filter clause like so#
$nd when we now run the page the end0user will now be able to select from the available )ategories in
the filter drop0downlist and page& sort& edit and delete 'ust the products in that categor"#
The Dasp#,in/1ataSourceE control will automaticall" appl" the appropriate ,IN- filter e*pression when
working against our ,IN- to S-, data model classes to ensure that onl" the re/uired data is retrieved
from the database 5for e*ample# in the :rid above onl" the A rows of %roduct data from the second page
of )onfection products will be retrieved from the database6.
7ou can optionall" handle the Selecting event on the Dasp#,in/1ataSourceE if "ou want to write a custom
,IN- e*pression in code to completel" customi(e the /uer" instead.
Step ,: 1dding 7siness 3alidation .les
$s I discussed in %art L of this ,IN- to S-, series& when we define ,IN- to S-, data models we will
automaticall" have a default set of schema based validation constraints added to our data model classes.
This means that if I tr" and enter a null value for a re/uired column& tr" and assign a string to an integer&
or assign a foreign0ke" value to a row that doesn<t e*ist& our ,IN- to S-, data model will raise an error
and ensure that our database integrit" is maintained.
;asic schema validation is onl" a first step& though& and is rarel" enough for most real0world applications.
T"picall" we<ll want2need to add additional business rules and application0level validation to our data
model classes. Thankfull" ,IN- to S-, makes adding these t"pes of business validation rules eas" 5for
details on the various validation approaches available& please read %art L of m" ,IN- to S-, series6.
E*ample ;usiness Validation 4ule Scenario
For e*ample& let<s consider a basic business logic rule we might want to enforce. Specificall"& we want to
ensure that a user of our application can<t discontinue a product while we still have units on backorder for
it#
If a user tries to save the above row& we<ll want to prevent this change from being persisted and throw an
appropriate error telling the user how to fi* it.
$dding a 1ata +odel Validation 4ule
The #rong $ace to add this t"pe of business validation rule is in the 9I la"er of our application. $dding it
in the 9I la"er of our application will mean that the rule will be specific to onl" that one place& and will not
be automaticall" enforced when we add another page to our application that also updates %roducts.
1istributing business rules2logic in our 9I la"er will also make life e*tremel" painful as our application
grows in si(e 0 since changes2updates to our business will necessitate making code changes all over the
place.
The right place to specif" this t"pe of business logic validation is instead in our ,IN- to S-, data model
classes that we defined earlier. $s I discussed in %art L of this series& all classes generated b" the ,IN-
to S-, designer are defined as partial classes 0 which means that we can easil" add additional
methods2events2properties to them. The ,IN- to S-, data model classes automaticall" call validation
methods that we can implement to enforce custom validation logic within them.
For e*ample& I could add a partial %roduct class to m" pro'ect that implements the OnValidate56 partial
method that ,IN- to S-, calls prior to persisting a %roduct entit". .ithin this OnValidate56 method I could
add the following business rule to enforce that products can<t have a 4eorder ,evel if the product is
discontinued#
Once I add the above class into m" ,IN- to S-, pro'ect& the above business rule will be enforced
an"time an"one uses m" data model to tr" and modif" the database. This is true for both updating
e*isting %roducts& as well as adding new %roducts into the database.
;ecause the Dasp#,in/1ataSourceE that we defined in our pages above works against our ,IN- to S-,
data model classes& all of its update2insert2delete logic will now have to pass the above validation check
prior to the change being persisted. .e do not need to0do an"thing to our 9I tier in order for this
validation to occur 0 it will automaticall" be applied an"where and ever"where our ,IN- to S-, data
model is used.
$dding Nice Error !andling in our 9I Tier
;" default if a user now uses our :ridView 9I to enter a non0valid 9nitsOnOrder21iscontinued
combination& our ,IN- to S-, data model classes will raise an e*ception. The Dasp#,in/1ataSourceE
will in turn catch this error and provides an event that users can use to handle it. If no one handles the
event then the :ridView 5or other6 control bound to the Dasp#,in/1ataSourceE will catch the error and
provide an event for users to handle it. If no one handles the error there then it will be passed up to the
%age to handle& and if not there to the global $pplicationCError56 event handler in the :lobal.asa* file.
1evelopers can choose an" place along this path to insert appropriate error handling logic to provide the
right end0user e*perience.
For the application we defined above& probabl" the best place to handle an" update errors is b" handling
the 4ow9pdated event on our :ridView. This event will get fired ever" time an update is attempted on
our datasource& and we can access the e*ception error details if the update event fails. .e can add the
below code to check if an error occurs& and if so displa" an appropriate error message to the end0user#
Notice above how we have not added an" validation specific logic into our 9I. Instead& I am retrieving the
validation error message string we raised in our business logic and am using it to displa" an appropriate
message to the end0user 5I am then displa"ing a more generic error message in the event of other
failures6.
Notice how I<m also indicating above that I want the :ridView to sta" in Edit mode when an error occurs 0
that wa" the user can avoid losing their changes& and can modif" the values the" entered and click
update again to tr" and save them. .e can then add a Dasp#literalE control with the Error+essage
I1 an"where we want on our page to control where where we want the error message to be displa"ed#
$nd now when we tr" and update the %roduct with an invalid value combination we<ll see an error
message indicating how to fi* it#
The nice thing about using this approach is that I can now add or change m" data model<s business rules
and not have to modif" an" of m" 9I tier<s code to have them pick up and honor the changes. The
validation rules& and corresponding error messages& can be written and centrali(ed in one place in m"
data model and automaticall" applied ever"where.
Smma!"
The Dasp#,in/1ataSourceE control provides an eas" wa" to bind an" $S%.NET 9I control to a ,IN- to
S-, data model. It enables 9I controls to both retrieve data from a ,IN- to S-, data model& as well as
cleanl" appl" updates2inserts2deletes to it.
In our application above we used the ,IN- to S-, O4+ designer to create a clean& ob'ect oriented data
model. .e then added three $S%.NET 9I controls to our page 5a :ridView& a 1rop1own,ist& and a
Error+essage ,iteral6& and added three Dasp#,in/1ataSourceE controls to bind %roduct& )ategor"& and
Supplier data from it#
.e then wrote B lines of business validation logic in our data model& and >> lines of 9I error handling
logic.
The end result is a simple web application with custom 9I that allows users to d"namicall" filter product
data b" categor"& efficientl" sort and page over the product results& inline0edit the product data to save
updates 5providing our business rules pass6& and delete products from the s"stem 5also providing our
business rules allow it6.
In future posts in this series I<ll cover more ,IN- to S-, scenarios including optimistic concurrenc"& la("
and eager loading& table mapping inheritance& and custom S-,2S%4O) usage.
Ne*t week I also plan to start a new series of blog posts that cover the new Dasp#,istViewE control 0
which is a new control that will ship with the $S%.NET release in .NET A.B. It provides total control over
the markup generated for data scenarios 5no tables& no spans& no inline st"les...6& while also delivering
built0in support for paging& sorting& editing& and insertion scenarios. For e*ample& we could optionall" use
it to replace the default :rid la"out look of our application above with a completel" custom look and feel.
;est of all& I could replace it within the above page in m" application and not have to change m" 1ata
+odel& the Dasp#lin/datasourceE declaration& or m" code0behind 9I error handling logic at all.
!ope this helps&
Scott
LINQ to SQL (Part * - +etrie,ing Data Using Stored
Pro)edures)
Over the last few weeks I<ve been writing a series of blog posts that cover ,IN- to S-,. ,IN- to S-, is
a built0in O24+ 5ob'ect relational mapper6 that ships in the .NET Framework A.B release& and which
enables "ou to model relational databases using .NET classes. 7ou can use ,IN- e*pressions to /uer"
the database with them& as well as update2insert2delete data.
;elow are the first five parts of m" ,IN- to S-, series#
%art ># Introduction to ,IN- to S-,
%art @# 1efining our 1ata +odel )lasses
%art A# -uer"ing our 1atabase
%art L# 9pdating our 1atabase
%art B# ;inding 9I using the $S%#,in/1ataSource )ontrol
In these previous ,IN- to S-, blog posts I demonstrated how "ou could use ,IN- /uer" e*pressions to
programmaticall" retrieve data from a database.
In toda"<s blog post I<ll cover how "ou can also use database stored procedures 5S%4O)s6 and user
defined functions 591Fs6 with "our ,IN- to S-, data model. Toda"<s blog post will specificall" cover how
to call S%4O)s to /uer" and retrieve data from the database. In m" ne*t blog post in this series I<ll then
show how "ou can optionall" also use S%4O)s to update2insert2delete data from the database.
)o S#.8C o! not to S#.8C? )hat is the =estion4444
The /uestion of whether to use 1"namic S-, generated b" an O4+ or instead use Stored %rocedures
when building a data la"er is a topic that generates endless 5ver" passionate6 debate amongst
developers& architects and 1;$s. $ lot of people much smarter than me have written on this topic& so I
won<t rehash the arguments for and against each side here.
The ,IN- to S-, O4+ that ships in .NET A.B is prett" fle*ible& and can be used to create data model
classes whose ob'ect model can be independent of the underl"ing database schema& and which can
encapsulate business logic and validation rules that work regardless of whether the data model is
populated2persisted via d"namic S-, or via S%4O)s.
In m" ,IN- to S-, %art A# -uer"ing our 1atabase post I discussed how "ou can write ,IN- /uer"
e*pressions against a ,IN- to S-, data model using code like below#
.hen "ou write ,IN- /uer" e*pressions like this the ,IN- to S-, O4+ will e*ecute the necessar"
d"namic S-, for "ou to retrieve %roduct ob'ects that matches "our /uer".
$s "ou<ll learn in this post& "ou can also optionall" map S%4O)s in the database to "our ,IN- to S-,
1ata)onte*t class& which allows "ou to alternativel" retrieve the same %roduct ob'ects b" calling a stored
procedure instead#

This abilit" to use both d"namic S-, and S%4O)s with a clean data model la"er is prett" powerful& and
provides a great deal of fle*ibilit" when working on pro'ects.
)he Steps to Map and Call a S#.8C sing LINQ to SQL
In m" %art @# 1efining our 1ata +odel )lasses tutorial I discussed how to use the ,IN- to S-, O4+
designer to create a ,IN- to S-, class model like below#
Notice above how there are two panes on the ,IN- to S-, O4+ designer surface. The left pane enables
us to define data model classes that map to our database. The right method pane allows us to optionall"
map S%4O)s 5and 91Fs6 to our ,IN- to S-, 1ata)onte*t ob'ect& which we can then use in0place of
d"namic S-, to populate the data model ob'ects.
:o( to Map a S#.8C to a LINQ to SQL DataContext
To map S%4O)s to our 1ata)onte*t class& let<s first go to the VS @??F Server E*plorer window and look
at the S%4O)s within our database#
.e can double click an" of the S%4O)s above to open and edit them. For e*ample& below is the
)ustOrder!ist S%4O) in Northwind#
To map the above S%4O) to our ,IN- to S-, 1ata)onte*t& we can drag2drop it from the Server E*plorer
onto our ,IN- to S-, O4+ designer. This will automaticall" create a new method on our ,IN- to S-,
1ata)onte*t class like below#
;" default the method name created on the 1ata)onte*t class will be the same as the S%4O) name&
and the return t"pe of the method will be an automaticall" created t"pe that follows the
NSprocNameO4esult naming pattern. For e*ample# the S%4O) above would return a se/uence of
)ustOrder!ist4esult ob'ects. .e could optionall" change the name of the method b" selecting it in the
designer and then use the propert" grid to rename it.
:o( to Call o! Ne(l" Mapped S#.8C
Once we<ve done the steps above to map a S%4O) onto our 1ata)onte*t class& it is eas" to use it to
programmaticall" retrieve data. $ll we need to0do is call the new method we mapped on our 1ata)onte*t
class to get back a se/uence of strongl" t"ped results from the S%4O)#
)alling the S%4O) in V;#
)alling the Sproc in )J#
In addition to programming looping over the result like in the code samples above& I could also obviousl"
bind the results to an" 9I control to displa" them. For e*ample& the below code databinds the result of
our S%4O) to a Dasp#gridviewE control#
.hich then displa"s the product histor" of our customer on a page like so#
Mapping the .et!n )"pe o+ S#.8C Methods to Data Model Classes
In the )ustOrder!ist S%4O) e*ample above the stored procedure returned a se/uence of product
histor" results containing two columns of data# the %roductName of the product& and the Total Number of
orders the customer has made for that product. The ,IN- to S-, designer automaticall" defined a new
)ustOrder!ist4esult class to represent this result.
.e could alternativel" choose to have the return result of a S%4O) map to an e*isting data model class
we have alread" defined in the ,IN- to S-, designer 5for e*ample# an e*isting %roduct or Order entit"
class6.
For e*ample& assume we have a :et%roducts;")ategor" S%4O) in our database that returns product
information like so#
,ike before we can create a :et%roducts;")ategor" method on our 1ata)onte*t that calls this S%4O)
b" dragging it onto our ,IN- to S-, designer. 4ather than 'ust dropping the S%4O) an"where on the
designer& though& we<ll instead drop the S%4O) on top of the e*isting %roduct class in our data model
designer#
This gesture of dropping the S%4O) onto the %roduct class tells the ,IN- to S-, designer to have the
:et%roducts;")ategor" method return a se/uence of %roduct ob'ects as a return result#

One of the cool things about having our S%4O) return %roduct ob'ects like above is that ,IN- to S-,
will automaticall" track the changes made to the returned %roduct ob'ects 'ust like it would %roduct
ob'ects returned via ,IN- /ueries. .hen we call the Submit)hanges56 method on our 1ata)onte*t& the
changes we have made to these ob'ects will automaticall" be saved back to the database.
For e*ample& we could write the code below to retrieve 5using a S%4O)6 and change the price of all
products within a specific )ategor" to be H?I of their current value#
.hen we call Submit)hanges56 at the end it will transactionall" update all of the product prices. To
understand more about how change tracking and the Submit)hanges56 method work& as well as about
how Validation ;usiness ,ogic can be added to data model entities& please read m" ,IN- to S-, %art L#
9pdating our 1atabase tutorial.
In m" ne*t blog post in this ,IN- to S-, series I<ll also cover how "ou can replace the d"namic
insert2update2delete S-, generated b" the O4+ with custom S%4O)s that handle the database updates
instead. The nice thing is that the code above wouldn<t change at all if I configured m" 1ata)onte*t to
use S%4O)s for updates 0 it would purel" be a mapping la"er change and the code written against m"
data model would be oblivious to it.
:andling S#.8C 8tpt #a!amete!s
,IN- to S-, maps out parameters in S%4O)s as reference parameters 5ref ke"word6& and for value
t"pes declares the parameter as nullable.
For e*ample& consider the below :et)ustomer1etails S%4O) which takes a )ustomerI1 as an input
parameter& and which returns the compan" name as an output parameter in addition to its order histor" as
a /uer" result#
If we drag the above S%4O) onto our Order class in the ,IN- to S-, designer& we could then write the
below code to call it#
V;#
)J#
Notice in the code above how the S%4O) helper method returns back a se/uence of Order ob'ects 0 but
also then returns the )ompan"Name as an output parameter to the helper method.
:andling Mltiple .eslt Shapes +!om S#.8Cs
.hen a stored procedure can return multiple result shapes& the return t"pe of the S%4O) method on the
1ata)onte*t cannot be strongl" t"ped to a single class shape. For e*ample& consider the S%4O) below
which returns either a product result or an order result depending on the input parameter#
,IN- to S-, supports the abilit" to create S%4O) helper methods that can return either a %roduct or
Order shape b" adding a partial Northwind1ata)onte*t class to the pro'ect that defines a method 5which
in this case we<ll call VariablesShapeSample6 that invokes the S%4O) and returns an I+ultiple4esult
ob'ect like so#
V;#
)J#
Once this method is added into our pro'ect we can then call it and convert the result to be either a %roduct
or Order se/uence when we are using it#
V;#
)J#
Sppo!ting Use! De+ined %n$tions 6UD%s)
In addition to S%4O)S& ,IN- to S-, also supports both scalar0valued and table0valued user
defined functions 591Fs6& as well as the in0line counterpart to both. Once added to "our 1ata)onte*t as
a method& "ou can use these 91F functions within "our ,IN- /ueries.
For e*ample& consider a simple scalar user defined function called +"9pperFunction#
.e can drag2drop it from the Visual Studio Server E*plorer onto our ,IN- to S-, 1esigner to add it as a
method on our 1ata)onte*t#
.e can then use this 91F function inline within our ,IN- e*pressions when writing /ueries against our
,IN- to S-, data model 5notice it is being used within the where clause below6#
V;#
)J#
If "ou use the ,IN- to S-, 1ebug Visuali(er that I blogged about here& "ou can see how ,IN- to S-,
transforms the above e*pression /ueries into raw S-, that e*ecute the 91F inside the database at
runtime#
Smma!"
,IN- to S-, supports the abilit" to call Stored %rocedures and 91Fs within the database and nicel"
integrate them into our data model. In this blog post I demonstrated how "ou can use S%4O)s to easil"
retrieve data and populate our data model classes. In m" ne*t blog post in this series I<ll cover how "ou
can also use S%4O)s to override the update2insert2delete logic when "ou Submit)hanges56 on "our
1ata)onte*t to persist back to the database.
!ope this helps&
Scott
LINQ to SQL (Part - - U"dating our Dataase using Stored
Pro)edures)
Over the last few weeks I<ve been writing a series of blog posts that cover ,IN- to S-,. ,IN- to S-, is
a built0in O24+ 5ob'ect relational mapper6 that ships in the .NET Framework A.B release& and which
enables "ou to model relational databases using .NET classes. 7ou can use ,IN- e*pressions to /uer"
the database with them& as well as update2insert2delete data.
;elow are the first si* parts in this series#
%art ># Introduction to ,IN- to S-,
%art @# 1efining our 1ata +odel )lasses
%art A# -uer"ing our 1atabase
%art L# 9pdating our 1atabase
%art B# ;inding 9I using the $S%#,in/1ataSource )ontrol
%art P# 4etrieving 1ata 9sing Stored %rocedures
In part P I demonstrated how "ou can optionall" use database stored procedures 5S%4O)s6 and user
defined functions 591Fs6 to /uer" and retrieve data using "our ,IN- to S-, data model. In toda"<s blog
post I<m going to discuss how "ou can also optionall" use S%4O)s to update2insert2delete data from the
database.
To help illustrate this 0 let<s start from scratch and build0up a data access la"er for the Northwind sample
database#
Step 1: C!eating o! Data 1$$ess La"e! 6(ithot sing S#.8Cs "et)
In m" %art @# 1efining our 1ata +odel )lasses tutorial I discussed how to use the ,IN- to S-, O4+
designer that is built0in to VS @??F to create a ,IN- to S-, class model like below#
1dding 3alidation .les to o! Data Model Classes
$fter defining our data model classes and relationships we<ll want to add some business logic validation
to our data model. .e can do this b" adding partial classes to our pro'ect that add validation rules to our
data model classes 5I cover how to0do this in0depth in m" %art L# 9pdating our 1atabase ,IN- to S-,
tutorial6.
For e*ample& we could add validation rules to enforce that the )ustomer<s phone number follows a valid
phone pattern& and that we don<t add Orders where the customer<s 4e/uired1ate for deliver" is before the
actual Order1ate of the Order. Once defined in partial classes like below& these validation methods will
automaticall" be enforced an"time we write code to update our data model ob'ects in an application.
V;#
)J#


1dding a ?etCstome!6) :elpe! Method to o! DataContext
Now that we have our data model classes created& and have applied validation rules to them& we can
/uer" and interact with the data. .e can do this b" writing ,IN- e*pressions against our data model
classes to /uer" the database and populate them 5I cover how to0do this in m" %art A# -uer"ing our
1atabase ,IN- to S-, tutorial6. $lternativel" we could map S%4O)s to our 1ata)onte*t and use them
to populate the data model classes 5I cover how to0do this in m" %art P# 4etrieving 1ata using Stored
%rocedures ,IN- to S-, tutorial6.
.hen building a ,IN- to S-, data la"er "ou<ll usuall" want to encapsulate common ,IN- /ueries 5or
S%4O) invocations6 into helper methods that "ou add to "our 1ata)onte*t class. .e can do this b"
adding a partial class to our pro'ect. For e*ample& we could add a helper method called :et)ustomer56
that enables us to lookup and retrieve a )ustomer ob'ect from the database based on their )ustomerI1
value#
V;#
)J#


Step &: Using o! Data 1$$ess La"e! 6still (ithot S#.8Cs)
.e now have a data access la"er that encapsulates our data model& integrates business validation rules&
and enables us to /uer"& update& insert& and delete the data.
,et<s look at a simple scenario using it where we retrieve an e*isting customer ob'ect& update the
customer<s )ontactName and %hone Number& and then create a new Order ob'ect and associate it with
them. .e can write the below code to do all of this within a single transaction. ,IN- to S-, will ensure
that our business logic validation rules are clean before saving an"thing in the database#
V;#
)J#
,IN- to S-, monitors the modifications we make to the ob'ects we retrieve from the 1ata)onte*t& and
keeps track of all of the ob'ects we add into it. .hen we call 1ata)onte*t.Submit)hanges56 at the end&
,IN- to S-, will check that our business logic rules are valid& and if so automaticall" generate the
appropriate d"namic S-, to update our )ustomer record above& and insert a new record into the Orders
table.
:ang on a se$ond @ I thoght this post (as abot sing S#.8Cs???
If "ou are still reading this& "ou might be feeling confused about where S%4O)s fit into this post. .h" did
I show "ou above how to write code that works with our data model ob'ects& and then causes d"namic
S-, to runG .h" haven<t I showed "ou how to call a S%4O) for doing inserts2updates2deletes instead
"etG
The reason is that t&e rogra!!ing !ode$ in LINQ to +QL .or #or,ing #it& data !ode$ o"7ects "ac,ed "y
+82OCs is t&e sa!e as t&ose udated )ia dyna!ic +QL. The wa" "ou add data model validation logic is
e*actl" the same 5so all the validation rules on our data model classes above still appl" when we use
S%4O)s6. The code snippet above where we use our data access la"er to retrieve a customer& update it&
and then add a new order associated with it is also e*actl" the same regardless of whether we are
using d"namic S-, for updates& or whether we have configured our data model classes to use S%4O)s
instead.
This programming model s"mmetr" is powerful both in that "ou don<t have to learn two wa"s of doing
things& and also because it means that "ou don<t have to decide up front at the beginning of "our pro'ect
whether "ou are going to use S%4O)s or not. 7ou can start off using the d"namic S-, support provided
b" the ,IN- to S-, O4+ for all /ueries& inserts& updates and deletes. 7ou can then add "our
business and validation rules to "our model. $nd then later "ou can optionall" update "our data mapping
model to use S%4O)s 0 or not if "ou decide "ou don<t want to. The code and tests "ou write against "our
data model classes can sta" the same regardless of whether "ou use d"namic S-, or S%4O)s.
.e<ll now spend the rest of this blog post demonstrating how we can update the data model we<ve built to
use S%4O)s for updates2inserts2deletes 0 while still using the same validation rules& and working with the
same code snippets above.
:o( to Use S#.8Cs +o! Inse!t2Update2Delete S$ena!ios
.e can modif" the data access la"er we<ve been building to use S%4O)s to handle updates& instead of
d"namic S-,& in one of two wa"s#
>6 ;" using the ,IN- to S-, designer to graphicall" configure S%4O)s to e*ecute in response to
Insert29pdate21elete operations on our data model classes.
or#
@6 ;" adding a Northwind1ata)onte*t partial class in our pro'ect& and then b" implementing the
appropriate Insert29pdate21elete partial methods provided on it 5for e*ample# InsertOrder& 9pdateOrder&
1eleteOrder6 that will be called when we insert2update2delete data model ob'ects. These partial methods
will be passed the data model instances we want to update& and we can then e*ecute whatever S%4O)
or S-, code we want to save it within the database.
.hen we use approach J> 5the ,IN- to S-, designer6 to graphicall" configure S%4O)s to call& it is
under the covers generating the same code 5in a partial class it creates6 that "ou<d write when using
approach J@. In general I<d recommend using the ,IN- to S-, designer to configure the S%4O)s for the
H?I case 0 and then in more advanced scenarios go in and custom tweak the S%4O) invocation code it
generates if "ou need to.
Step ': Doing 8!de! Inse!ts (ith a S#.8C
.e<ll begin switching our data model to use S%4O)s b" starting with the Order ob'ect.
.e<ll first go to the Visual Studio Server E*plorer window& e*pand into the Stored %rocedures node of
our database& and then right0click and choose $dd New Stored %rocedure#
.e<ll then create a new S%4O) that we<ll call InsertOrder that inserts a new order record into our
Orders table#
Notice above how the S%4O) defines the OrderI1 parameter as an output param. This is because the
OrderI1 column in the database is an identit" column that is set to auto0increment each time a new record
is added. The caller of the S%4O) will pass in N9,, as a value when calling it 0 and the S%4O) then
passes back the newl" created OrderI1 value as the output value 5b" calling the S)O%ECI1ENTIT756
function at the end of the S%4O)6.
$fter creating the S%4O) we<ll then open up the ,IN- to S-, O4+ designer for our data access la"er.
,ike I discussed in m" last blog post in this series 5%art P# 4etrieving 1ata 9sing Stored %rocedures6& we
can drag2drop S%4O)s from the server0e*plorer onto the method pane of our 1ata)onte*t designer.
.e<ll want to0do this with our newl" created InsertOrder S%4O)#
Our last step will be to tell our data access la"er to use the InsertOrder S%4O) when inserting new Order
ob'ects into the database. .e can do that b" selecting the Order class in the ,IN- to S-, O4+
designer& and then b" going to the propert" grid and clicking the ... button to override how Insert
operations happen for it#
)licking the ... button will bring up a dialog that allows us to customi(e how insert operations happen#
Notice above how the default mode 59se 4untime6 is to have ,IN- to S-, calculate and e*ecute
d"namic S-, to handle the insert operations. .e can change that b" selecting the )ustomi(e radio
button and then pick our InsertOrder S%4O) from the list of available S%4O)s#
The ,IN- to S-, designer will populate a parameter list for the S%4O) we picked& and enable us to map
properties on our Order class to parameters of our InsertOrder S%4O). ;" default it is smart and tries to
best match them based on name. 7ou can go in and override them if "ou want.
Once we click ok on the dialog& we are done. Now whenever a new Order is added to our 1ata)onte*t
and the Submit)hanges56 method is invoked& our InsertOrder S%4O) will be used instead of e*ecuting
d"namic S-,.
Important# Even though we are now using a S%4O) for persistence& the custom Order OnValidate56
partial method we created earlier 5in step > of this blog post6 to encapsulate Order validation rules still
e*ecutes before an" changes are saved or the S%4O) is invoked. This means we have a clean wa" to
encapsulate business and validation rules in our data models& and can re0use them regardless of whether
d"namic S-, or S%4O)s are used.
Step *: Doing Cstome! Updates (ith a S#.8C
Now let<s modif" our )ustomer ob'ect to handle updates using a S%4O).
.e<ll start b" creating a new 9pdate)ustomer S%4O) like below#

Notice above how in addition to passing in the Q)ustomerI1 parameter& we are also passing in a
QOriginalC)ustomerI1 parameter. The )ustomerI1 column in the )ustomers table is not an auto0
increment identit" column& and it can be modified as part of an update of the )ustomer ob'ect.
)onse/uentl" we need to be able to provide the S%4O) with both the original )ustomerI1 and the new
)ustomerI1 in order to update the record. .e<ll look at how we map this using the ,IN- to S-, designer
shortl".
7ou<ll notice above how I<m also passing in a QVersion parameter 5which is a timestamp6 to the S%4O).
This is a new column I<ve added to the Northwind )ustomers table to help handle optimistic concurrenc".
I will cover optimistic concurrenc" in much more depth in a later blog post in this ,IN- to S-, series 0 but
the short summar" is that ,IN- to S-, full" supports optimistic concurrenc"& and enables "ou to use
either a version timestamp or to suppl" both original2new values to "our S%4O)s to detect if changes
have been made b" another user since "ou last refreshed "our data ob'ects. For this sample I<m using a
timestamp since it makes the code much cleaner.
Once we<ve created our S%4O)& we can drag2drop it onto the ,IN- to S-, designer to add it as a
method on our 1ata)onte*t. .e can then select the )ustomer class in the O4+ designer and click the
... button to override the )ustomer ob'ect<s 9pdate behavior in the propert" grid#
.e<ll select the )ustomi(e radio button and pick our 9pdate)ustomer S%4O) to use#
.hen mapping our )ustomer ob'ect<s properties to the S%4O) parameters& "ou<ll notice that we<ll want to
be deliberate about whether we suppl" the current propert" value on the data ob'ect& or the original
value that was in the database when the ob'ect was first retrieved. For e*ample& we<ll want to make sure
we map the current value of the )ustomer.)ustomerI1 propert" for the Q)ustomerI1 S%4O)
parameter& and that we map the original value for the QoriginalCcustomerI1 S%4O) parameter.
Once we click ok on the dialog& we are done. Now whenever a new )ustomer is updated and the
Submit)hanges56 method is invoked& our 9pdate)ustomer S%4O) will be used instead of e*ecuting
d"namic S-,.
Important# Even though we are now using a S%4O) for persistence& the )ustomer On%hone)hanging56
partial method we created earlier 5in step > of this blog post6 to encapsulate %hone Number validation
rules still e*ecutes before an" changes are saved or the S%4O) is invoked. .e have a clean wa" to
encapsulate business and validation rules in our data models& and can re0use them regardless of whether
d"namic S-, or S%4O)s are used.
Step ,: Using o! Data 1$$ess La"e! 1gain 6this time (ith S#.8Cs)
Once we<ve updated our data la"er to use S%4O)s instead of d"namic S-, for persistence& we can re0
run the e*act same code we wrote in Step @ earlier against our data model classes#
Now the updates for the )ustomer ob'ect& and the insert for the Order ob'ect& are e*ecuting via S%4O)s
instead of d"namic S-,. The validation logic we defined still e*ecutes 'ust like before& though& and the
data access code we write to use the data model classes is e*actl" the same.
Some 1d/an$ed Notes When Using S#.8Cs
$ few /uick notes that "ou might find useful for more advanced S%4O) scenarios with ,IN- to S-,#
Usage o+ S#.8C 8tpt #a!ams:
In the Insert scenario 5Step A6 above I showed how we could return back the new OrderI1 value 5which is
an auto0increment identit" column in the Orders table6 using an output parameter of the S%4O). 7ou
aren<t limited to onl" returning back identit" column values when using S%4O)s with ,IN- to S-, 0 in
fact "ou can update and return back output values for an" parameter of "our S%4O). 7ou can use this
approach both for Insert and 9pdate scenarios. ,IN- to S-, will then take the return value and use it to
update the propert" value of "our data model ob'ect without "ou having to0do an" second /ueries against
the database to refresh2populate them.
What :appens i+ the S#.8C )h!o(s an E!!o!?
If a S%4O) raises an error when doing an Insert29pdate21elete operation& ,IN- to S-, will automaticall"
cancel and rollback the transaction of all changes associated with the current Submit)hanges56 call on
the 1ata)onte*t. This ensures that "our data is alwa"s kept in a clean& consistent state.
Can "o (!ite $ode instead o+ sing the 8.M designe! to $all S#.8Cs?
$s I mentioned earlier in this post& "ou can use either the ,IN- to S-, O4+ designer to map "our
insert2update2delete operations to S%4O)s& or "ou can add partial methods on "our 1ata)onte*t class
and programmaticall" invoke them "ourself. !ere is an e*ample of the e*plicit code "ou could write in a
partial class for the Northwind1ata)onte*t to override the 9pdate)ustomer behavior to call a S%4O)#
The code above was actuall" what was generated b" the ,IN- to S-, O4+ designer when we used the
designer to map the S%4O) and then associate the update behavior of the )ustomer ob'ect with it. 7ou
can use it as a starting point and then add an" additional logic "ou want to it to make it more advanced
5for e*ample# use the return value of the S%4O) to raise custom e*ceptions for error conditions&
optimistic concurrenc"& etc6.
Smma!"
,IN- to S-, is a ver" fle*ible O4+. It enables "ou to write clean ob'ect0oriented code to retrieve& update
and insert data.
;est of all 0 it enables "ou to cleanl" design data model classes independent of how the" are persisted
and loaded from a database. 7ou can use the built0in O4+ engine to efficientl" retrieve and update data
in the database using d"namic S-,. Or alternativel" "ou can configure "our data la"er to use S%4O)s.
The nice thing is that "our code consuming the data la"er& and all of the business logic validation rules
"ou annotate it with& can be the same regardless of which persistence approach "ou use.
In future blog posts in this series I<ll cover some remaining ,IN- to S-, concepts including# Single Table
Inheritance& 1eferred2Eager ,oading& Optimistic )oncurrenc"& and handling +ulti0Tier scenarios. I<m on
vacation ne*t week& and so will hopefull" have some free time to get a few of them written then.
!ope this helps&
Scott
to SQL (Part . - /0e)uting Custo1 SQL /0"ressions)
Over the last few weeks I<ve been writing a series of blog posts that cover ,IN- to S-,. ,IN- to S-, is
a built0in O24+ 5ob'ect relational mapper6 that ships in the .NET Framework A.B release& and which
enables "ou to model relational databases using .NET classes. 7ou can use ,IN- e*pressions to /uer"
the database with them& as well as update2insert2delete data.
;elow are the first seven parts in this series#
%art ># Introduction to ,IN- to S-,
%art @# 1efining our 1ata +odel )lasses
%art A# -uer"ing our 1atabase
%art L# 9pdating our 1atabase
%art B# ;inding 9I using the $S%#,in/1ataSource )ontrol
%art P# 4etrieving 1ata 9sing Stored %rocedures
%art R# 9pdating our 1atabase using Stored %rocedures
In m" last two posts 5%art P and %art R6 I demonstrated how "ou can optionall" use database stored
procedures 5S%4O)s6 to /uer"& insert& update and delete data using a ,IN- to S-, data model.
One of the /uestions a few people have asked me since doing these posts has been what if I want total
control over the S-, e*pressions used b" ,IN- to S-, 0 but I don<t want to use S%4O)s to0do itG
Toda"<s blog post will cover that 0 and discuss how "ou can use custom S-, e*pressions that "ou provide
to populate "our ,IN- to S-, data model classes& as well as perform insert& updates& and deletes.
Using LINQ Qe!" Exp!essions (ith LINQ to SQL
For the purposes of this blog post& let<s assume we<ve used the ,IN- to S-, O4+ designer in VS @??F
to define a set of data model classes like below for the Northwind database 5note# read %art @ of this
series to learn how to use the ,IN- to S-, O4+ designer to do this6#
In %art A of this blog series I covered how "ou can use the new ,IN- language support in V; and )J to
/uer" the above data model classes and return back a set of ob'ects that represent the rows2columns in
the database.
For e*ample& we could add a :et%roducts;")ategor" helper method to the 1ata)onte*t class of our
data model that uses a ,IN- /uer" to return back %roduct ob'ects from the database#
V;#
)J#
Once we<ve defined our encapsulated ,IN- helper method& we can then write code like below that uses it
to retrieve the products& and iterate over the results#
V;#

.hen the ,IN- e*pression within our :et%roducts;")ategor" method is evaluated& the ,IN- to S-,
O4+ will automaticall" e*ecute d"namic S-, to retrieve the %roduct data and populate the %roduct
ob'ects. 7ou can use the ,IN- to S-, 1ebug Visuali(er to see in the debugger how this ,IN- e*pression
is ultimatel" evaluated.
Using Cstom SQL Qe!ies (ith LINQ to SQL
In our sample above we didn<t have to write an" S-, code to /uer" the database and retrieve back
strongl"0t"ped %roduct ob'ects. Instead& the ,IN- to S-, O4+ automaticall" translated the ,IN-
e*pression to S-, for us and evaluated it against the database.
;ut what if we wanted total control over the S-, that is run against our database& and don<t want ,IN- to
S-, to0do it for us in this scenarioG One wa" to accomplish this would be to use a S%4O) like I
discussed in %art P and %art R of this series. The other approach is to use the E*ecute-uer" helper
method on the 1ata)onte*t base class and use a custom S-, e*pression that we provide.
Using the Exe$teQe!" Method
The E*ecute-uer" method takes a S-, /uer" e*pression as an argument& along with a set of parameter
values that we can use to optionall" substitute values into the /uer". 9sing it we can e*ecute an" raw
S-, we want against the database 5including custom 8OINs across multiple tables6.
.hat makes the E*ecute-uer" method reall" useful is that it allows "ou to specif" how "ou want the
return values of "our S-, e*pression to be t"ped. 7ou can do this either b" passing a t"pe0ob'ect as a
parameter to the method& or b" using a generic0based version of the method.
For e*ample& we could change the :et%roducts;")ategor"56 helper method we created earlier 0 using a
,IN- e*pression 0 to instead use the E*ecute-uer" method to e*ecute our own raw S-, e*pression
against the database and return %roduct ob'ects as a result#
V;#
)J#
.e can then call the :et%roducts;")ategor"56 helper method using the e*act same code as before#
;ut unlike before it will be our custom S-, e*pression that will run against the database 0 and not
d"namic S-, e*ecuted in response to using a ,IN- /uer" e*pression.
Cstom SQL Exp!essions and 8b9e$t )!a$5ing +o! Updates
;" default when "ou retrieve a data model ob'ect using ,IN- to S-,& it will track all changes and
updates "ou make to it. If "ou call the Submit)hanges56 method on the 1ata)onte*t class& it will then
transactionall" persist all of the updates back to the database. I cover this in more depth in %art L of this
,IN- to S-, series.
One of the cool features of the E*ecute-uer"56 method is that it can full" participate in this ob'ect tracking
and update model. For e*ample& we could write the code below to retrieve all products from a specific
categor" and discount their prices b" >?I#
;ecause we t"ped the return value of our E*ecute-uer" call in the :et%roducts;")ategor" method to be
of t"pe %roduct& ,IN- to S-, knows to track the %roduct ob'ects we returned from it. .hen we call
Submit)hanges56 on the conte*t ob'ect the" will be persisted back to the database.
Cstom SQL Exp!essions (ith Cstom Classes
The E*ecute-uer"56 method allows "ou to specif" an" class as the return t"pe of a S-, /uer". The class
does not have to be created using the ,IN- to S-, O4+ designer& or implement an" custom interface 0
"ou can pass in an" plain old class to it.
For e*ample& I could define a new %roductSummar" class that has a subset of %roduct properties like
below 5notice the use of the new )J $utomatic %roperties feature6#
.e could then create a :et%roductSummaries;")ategor"56 helper method on our
Northwind1ata)onte*t that returns results based on it. Notice how our S-, statement below re/uests
'ust the subset of product values we need 0 the E*ecute-uer" method then handles automaticall" setting
these on the %roductSumma" ob'ects it returns#
.e can then invoke this helper method and iterate over its results using the code below#
Cstom SQL Exp!essions +o! Inse!ts2Updates2Deletes
In addition to using custom S-, e*pressions for /ueries& we can also e*ecute them to perform
custom Insert29pdate21elete logic.
.e can accomplish this b" creating the appropriate partial Insert29pdate21elete method for the entit" we
want to change in a partial class on our 1ata)onte*t. .e can then use the E*ecute)ommand method on
the 1ata)onte*t base class to write the S-, we want to e*ecute. For e*ample& to override the 1elete
behavior for %roduct classes we could define this 1elete%roduct partial method#
$nd now if we write the below code to remove a specific %roduct instance from our database& ,IN- to
S-, will call the 1elete%roduct method 0 which will cause our custom S-, to e*ecute in place of the
default d"namic S-, that ,IN- to S-, would otherwise use#
Smma!"
The ,IN- to S-, O4+ automaticall" generates and e*ecutes d"namic S-, to perform /ueries& updates&
inserts and deletes against a database.
For advanced scenarios& or cases where "ou want total control over the S-, /uer"2command e*ecuted&
"ou also have the abilit" to customi(e the O4+ to use either S%4O)s& or "our own custom S-,
E*pressions& instead. This provides "ou with a great deal of fle*ibilit" when building and e*tending "our
data access la"er.
In future blog posts in this series I<ll cover some remaining ,IN- to S-, concepts including# Single Table
Inheritance& 1eferred2Eager ,oading& Optimistic )oncurrenc"& and handling +ulti0Tier scenarios.
!ope this helps&
Scott

You might also like