Download as pdf or txt
Download as pdf or txt
You are on page 1of 216

Using CSLA 4

Data Access

Rockford Lhotka
Using CSLA .NET 4: Data Access

Copyright © 2011-2012 by Marimer LLC

All rights reserved. No part of this work may be reproduced or transmitted in any form or by any
means, electronic or mechanical, including photocopying, recording, or by any information
storage or retrieval system, without the prior written permission of the copyright owner.

Trademarked names may appear in this book. Rather than use a trademark symbol with every
occurrence of a trademarked name, we use the names only in an editorial fashion and to the
benefit of the trademark owner, with no intention of infringement of the trademark.

Editor: Teresa Lhotka

The information in this book is distributed on an “as is” basis, without warranty. Although every
precaution has been taken in the preparation of this work, the author shall not have any liability
to any person or entity with respect to any loss or damage caused or alleged to be caused directly
or indirectly by the information contained in this work.

The source code for this book (CSLA 4 version 4.1.0) is available at
http://www.lhotka.net/cslanet.

Errata or other comments about this book should be emailed to errata@lhotka.net.

Revision: 1.0
Acknowledgements
Neither this book, nor CSLA 4, would have
been possible without support from Magenic.
Magenic is the premier .NET development
company in the US, and is a Microsoft Gold
Certified Partner.

You can reach Magenic at


http://www.magenic.com.

CSLA .NET has attracted a community of very


thoughtful, intelligent and dedicated people.
You can find many of them at
http://forums.lhotka.net.

The bug fixes and feature enhancements


described in this book come, in no small part,
through the encouragement and feedback
provided by this stellar community.

Thank you all!


About the Author
Rockford Lhotka is the author of more than 17 books on developing software using the Microsoft
platform and technologies. He is a Microsoft Regional Director and a Microsoft MVP. Rockford
speaks at many conferences and user groups around the world. He is the Chief Technology Officer
at Magenic (www.magenic.com), a company that specializes in planning, designing, building and
maintaining your enterprise’s most mission critical systems.
Contents
Introduction........................................................................................................................................................... 1
Organization of the Book ..........................................................................................................................................1
Framework Code and Samples ..................................................................................................................................1

Chapter 1: Object Persistence ................................................................................................................................ 3


Architecture and Design Considerations ...................................................................................................................3
Separating Concerns ............................................................................................................................................4
Data Portal Models ..............................................................................................................................................5
Encapsulated Models ......................................................................................................................................5
Factory Models ................................................................................................................................................7
Data Portal Model Overview ...........................................................................................................................8
Encapsulated Invocation ...............................................................................................................................11
Factory Implementation ................................................................................................................................12
Factory Invocation .........................................................................................................................................12
Encapsulated Implementation ......................................................................................................................13
Persisting Non-CSLA .NET Objects ...........................................................................................................................14
Managing State and Metastate ..............................................................................................................................15
Object Relational Mapping ................................................................................................................................15
Managing State ..................................................................................................................................................16
Concurrency .......................................................................................................................................................16
Transactions .......................................................................................................................................................17
AutoCloneOnUpdate Feature ........................................................................................................................18
Managing Metastate ..........................................................................................................................................19
Data Access Technologies .......................................................................................................................................20
Accessing Relational Databases .........................................................................................................................21
Accessing Services ..............................................................................................................................................22
Accessing Isolated Storage .................................................................................................................................22
Accessing Other Data Sources ............................................................................................................................23
Accessing Multiple Data Sources .......................................................................................................................23
Persistence Operations ...........................................................................................................................................23
Create .................................................................................................................................................................24
Fetch...................................................................................................................................................................25
Update................................................................................................................................................................26
Saving Editable Root Objects .........................................................................................................................26
Results of Saving an Object ...........................................................................................................................28
ForceUpdate Option ......................................................................................................................................28
Delete .................................................................................................................................................................29
Execute ...............................................................................................................................................................30

Chapter 2: Data Portal ......................................................................................................................................... 32


Client-Side Data Portal Concepts ............................................................................................................................32
Calling the Client-Side Data Portal on the Server ...............................................................................................32

Using CSLA 4: Data Access Page i


Copyright © 2012 Marimer LLC
Forcing Code to Run Locally ...............................................................................................................................33
RunLocal Attribute ........................................................................................................................................33
ProxyMode Parameter ..................................................................................................................................33
Static Events .......................................................................................................................................................34
DataPortalInitInvoke Event ...........................................................................................................................34
DataPortalInvoke Event .................................................................................................................................34
DataPortalInvokeComplete Event .................................................................................................................35
Server-Side Data Portal Concepts ...........................................................................................................................35
Application Context ............................................................................................................................................35
User Principal and Identity ............................................................................................................................36
CSLA .NET Environment and Configuration ...................................................................................................38
LocalContext ..................................................................................................................................................39
ClientContext .................................................................................................................................................39
GlobalContext ................................................................................................................................................40
Authorizing Data Portal Requests ......................................................................................................................40
IAuthorizeDataPortal Interface .....................................................................................................................40
MobileFactory Attribute ................................................................................................................................42
Database Transactions .......................................................................................................................................43
Transactional Attribute .................................................................................................................................43
Manual Transactions .....................................................................................................................................44
TransactionScope Transactions .....................................................................................................................45
EnterpriseLibrary Transactions ......................................................................................................................46
Data Portal Exceptions .......................................................................................................................................46
DataPortalException Types ...........................................................................................................................47
Exception Inspector .......................................................................................................................................48
Encapsulation Models ........................................................................................................................................49
DataPortal_Create Method ...........................................................................................................................49
DataPortal_Fetch Method .............................................................................................................................51
DataPortal_Insert Method ............................................................................................................................52
DataPortal_Update Method ..........................................................................................................................53
DataPortal_DeleteSelf Method .....................................................................................................................53
DataPortal_Delete Method ...........................................................................................................................54
DataPortal_OnDataPortalInvoke Method .....................................................................................................55
DataPortal_OnDataPortalInvokeComplete Method .....................................................................................56
DataPortal_OnDataPortalException Method ................................................................................................56
Factory Models...................................................................................................................................................57
ObjectFactory Attribute ................................................................................................................................57
IObjectFactoryLoader Interface.....................................................................................................................58
ObjectFactory Class .......................................................................................................................................59
Create Method ..............................................................................................................................................61
Fetch Method ................................................................................................................................................62
Update Method .............................................................................................................................................63
Delete Method ..............................................................................................................................................65
Execute Method ............................................................................................................................................66
Invoke Method ..............................................................................................................................................66
InvokeComplete Method ..............................................................................................................................67
InvokeError Method ......................................................................................................................................67

Chapter 3: CSLA .NET Data Helpers ...................................................................................................................... 69


Csla.Data Namespace .............................................................................................................................................69
Data Object Managers .......................................................................................................................................69
ConnectionManager Class .............................................................................................................................71
Using CSLA 4: Data Access Page ii
Copyright © 2012 Marimer LLC
ObjectContextManager Class ........................................................................................................................73
TransactionManager Class ............................................................................................................................73
ContextManager Class...................................................................................................................................74
DataMapper Class ..............................................................................................................................................74
Map Method .................................................................................................................................................75
Non-Browsable Properties ............................................................................................................................76
Using an IgnoreList ........................................................................................................................................76
Mapping from an Object with a DataMap ....................................................................................................77
Value Coersion ..............................................................................................................................................77
ObjectAdapter Class ...........................................................................................................................................78
SafeDataReader Class.........................................................................................................................................79

Chapter 4: Data Access Implementation .............................................................................................................. 81


Implementing a Data Access Layer .........................................................................................................................81
Data Access Layer Interface Options ..................................................................................................................82
Data Reader and Methods ............................................................................................................................82
Data Transfer Objects and Methods .............................................................................................................83
Exceptions in .NET .........................................................................................................................................86
Exceptions in Silverlight and WP7 .................................................................................................................87
Dynamic Loading Options ..................................................................................................................................87
Mock Database Implementation ........................................................................................................................88
Creating the Mock Database .........................................................................................................................88
Using the Mock Database ..............................................................................................................................89

Chapter 5: Encapsulated Invocation Model.......................................................................................................... 91


Provider Pattern Implementation ...........................................................................................................................92
The DalFactory Implementation ........................................................................................................................93
Implementing the IDalManager Interface .........................................................................................................94
Implementing the IDisposable Interface .......................................................................................................95
Implementing a Data Reader DAL Interface ......................................................................................................96
Implementing a DTO-Based DAL Interface.........................................................................................................97
Using the ADO.NET Entity Framework ...............................................................................................................97
Editable Root Object Persistence ............................................................................................................................99
DataReader Interface .........................................................................................................................................99
Create Operation ...........................................................................................................................................99
Fetch Operation ..........................................................................................................................................101
Insert Operation ..........................................................................................................................................103
Update Operation .......................................................................................................................................105
Deferred Delete Operation .........................................................................................................................107
Immediate Delete Operation ......................................................................................................................108
DTO Interface ...................................................................................................................................................109
Create Operation .........................................................................................................................................110
Fetch Operation ..........................................................................................................................................110
Insert Operation ..........................................................................................................................................111
Update Operation .......................................................................................................................................112
Deferred Delete Operation .........................................................................................................................113
Immediate Delete Operation ......................................................................................................................114
Editable Root List Persistence ...............................................................................................................................114
Data Reader Interface ......................................................................................................................................114
Create Operation .........................................................................................................................................114
Child Create Techniques ..............................................................................................................................115

Using CSLA 4: Data Access Page iii


Copyright © 2012 Marimer LLC
Fetch Operation ..........................................................................................................................................120
Update Operation .......................................................................................................................................122
Immediate Delete Operation ......................................................................................................................124
DTO Interface ...................................................................................................................................................125
Create Operation .........................................................................................................................................126
Fetch Operation ..........................................................................................................................................126
Update Operation .......................................................................................................................................127
Immediate Delete Operation ......................................................................................................................128
Dynamic List and Object Persistence ....................................................................................................................129
Data Reader Interface ......................................................................................................................................129
Fetch Operation ..........................................................................................................................................130
Update Operation .......................................................................................................................................131
DTO Interface ...................................................................................................................................................132
Fetch Operation ..........................................................................................................................................133
Update Operation .......................................................................................................................................134
Editable Object Graph Persistence ........................................................................................................................134
Data Reader Interface ......................................................................................................................................135
Create Operation .........................................................................................................................................136
Creating New Child Objects .........................................................................................................................137
Creating New Grandchild Objects ...............................................................................................................138
Fetch Operation ..........................................................................................................................................138
Update Operation .......................................................................................................................................142
Delete Operation .........................................................................................................................................145
DTO Interface ...................................................................................................................................................150
Command Object Persistence ...............................................................................................................................151
Data Reader Interface ......................................................................................................................................151
Execute Operation .......................................................................................................................................152
DTO Interface ...................................................................................................................................................153
Execute Operation .......................................................................................................................................154
Unit of Work Object Persistence ...........................................................................................................................155
Retreiving Objects ............................................................................................................................................155
Updating Objects..............................................................................................................................................157
Read-Only List Persistence ....................................................................................................................................159
Data Reader Interface ......................................................................................................................................159
Fetch Operation ..........................................................................................................................................159
DTO Interface ...................................................................................................................................................161
Fetch Operation ..........................................................................................................................................161
Name-Value List Persistence .................................................................................................................................162
Data Reader Interface ......................................................................................................................................163
Fetch Operation ..........................................................................................................................................163
DTO Interface ...................................................................................................................................................164
Fetch Operation ..........................................................................................................................................165

Chapter 6: Factory Implementation ................................................................................................................... 166


Custom Factory Loader Implementation...............................................................................................................168
Editable Root Object Persistence ..........................................................................................................................169
Create Operation .............................................................................................................................................170
Fetch Operation ..........................................................................................................................................171
Update Operation .......................................................................................................................................174

Using CSLA 4: Data Access Page iv


Copyright © 2012 Marimer LLC
Immediate Delete Operation ......................................................................................................................177
Editable Root List Persistence ...............................................................................................................................178
Create Operation .............................................................................................................................................178
Child Create Techniques ..................................................................................................................................179
Creating the Child Locally ............................................................................................................................179
Creating the Child on the Server .................................................................................................................180
Fetch Operation ...............................................................................................................................................181
Update Operation ............................................................................................................................................183
Immediate Delete Operation ...........................................................................................................................185
Dynamic List and Object Persistence ....................................................................................................................186
Fetch Operation ...............................................................................................................................................186
Update Operation ............................................................................................................................................187
Editable Object Graph Persistence ........................................................................................................................188
Create Operation .............................................................................................................................................189
Creating New Child Objects .............................................................................................................................190
Creating New Grandchild Objects ....................................................................................................................190
Fetch Operation ...............................................................................................................................................191
Loading the Root Object ..............................................................................................................................191
Loading the Child Objects ............................................................................................................................191
Loading the Grandchild Objects ..................................................................................................................192
Update Operation ............................................................................................................................................193
Updating the Root Object ...........................................................................................................................194
Deleting the Child Objects ...........................................................................................................................194
Updating the Child Objects .........................................................................................................................196
Deleting the Grandchild Objects .................................................................................................................197
Updating the Grandchild Objects ................................................................................................................197
Immediate Delete Operation ...........................................................................................................................198
Command Object Persistence ...............................................................................................................................199
Execute Operation ...........................................................................................................................................199
Unit of Work Object Persistence ...........................................................................................................................200
Retrieving Objects ............................................................................................................................................200
Updating Objects..............................................................................................................................................201
Read-Only List Persistence ....................................................................................................................................201
Fetch Operation ...............................................................................................................................................202
Name-Value List Persistence .................................................................................................................................203
Fetch Operation ...............................................................................................................................................203

Conclusion ......................................................................................................................................................... 205

Using CSLA 4: Data Access Page v


Copyright © 2012 Marimer LLC
List of Tables
Table 1. Data access models supported by the data portal 9
Table 2. Primary metastate values related to persistence 19
Table 3. Data portal methods supporting the Create operation 24
Table 4. Data portal methods supporting the Fetch operation 25
Table 5. Metastate rules applied during the Update operation 26
Table 6. Data portal methods supporting the Update operation 26
Table 7. Methods used to save editable objects 27
Table 8. Members defined by the ISavable interface 27
Table 9. Data portal methods supporting the Delete operation 29
Table 10. Data portal methods that support the Execute operation 30
Table 11. ApplicationContext.User property source 36
Table 12. ExecutionLocation property values 38
Table 13. Members of the AuthorizeRequest class 41
Table 14. Properties available from DataPortalException 47
Table 15. Properties of WcfErrorInfo type 48
Table 16. Members of the DataPortalEventArgs type 55
Table 17. Default factory method names for data operations 57
Table 18. Members implemented by the ObjectFactory base class 60
Table 19. Csla.Data namespace types covered in Chapter 3 69
Table 20. Connection manager GetManager method overloads 72
Table 21. Default DataMapper mapping behaviors 76
Table 22. Methods on DataMap 77

Using CSLA 4: Data Access Page vi


Copyright © 2012 Marimer LLC
List of Figures
Figure 1. Five layer logical architecture ......................................................................................... 3
Figure 2. Five layer architecture in a 3-tier deployment ................................................................. 4
Figure 3. Areas of concern for object persistence........................................................................... 4
Figure 4. Encapsulated invocation data portal process flow......................................................... 11
Figure 5. Factory implementation data portal process flow ......................................................... 12
Figure 6. Factory invocation data portal process flow .................................................................. 13
Figure 7. Encapsulated implementation data portal process flow ................................................ 14
Figure 8. A 4-tier physical deployment ........................................................................................ 42
Figure 9. Nested connection manager objects .............................................................................. 71
Figure 10. Assemblies involved in implementing a pluggable DAL............................................ 91
Figure 11. DataAccess project contains DAL interface definitions and loader ............................ 92
Figure 12. DalFactory dynamically loading a provider. ............................................................... 93
Figure 13. Example SqlCe provider project. ................................................................................ 96
Figure 14. OrderEdit object graph. ............................................................................................. 135
Figure 15. Assemblies involved in loading an object factory DAL ........................................... 166
Figure 16. Concrete DAL assemblies reference business assemblies ........................................ 167
Figure 17. OrderEdit object graph. ............................................................................................. 188

Using CSLA 4: Data Access Page vii


Copyright © 2012 Marimer LLC
Introduction
Welcome to Using CSLA 4: Data Access.
This book will provide you with the information necessary to use the CSLA .NET framework to
implement persistence for your business objects. This includes the use of the data portal to enable
flexible 1-, 2-, 3-, and 4-tier deployments of your application, and your choice of four models for
implementing persistence.
This book is part of a multi-part book series consisting of several related ebooks. While each
ebook is separate, they are designed to work together to provide information about CSLA 4. This
book series will show you how to use the CSLA framework to build powerful and scalable
applications for Windows, Silverlight, and the web.
This book builds on the information provided in the Using CSLA 4: CSLA .NET Overview and CSLA
4: Creating Business Objects ebooks. It is assumed that you have an understanding of the content
from those ebooks.

Organization of the Book


This ebook is the third in a series of related ebooks that together comprise the Using CSLA 4 book.
Each ebook is separate, but they are designed to work together in a flexible manner so you can get
just the information you need for your application or project. All subsequent ebooks in the series
assume you have read the first three ebooks: Using CSLA 4: CSLA .NET Overview, Using CSLA 4:
Creating Business Objects, and Using CSLA 4: Data Access (this book).
This book covers two major topic areas: data access and the data portal.
The CSLA .NET framework is designed to be agnostic about the data access technology used by
any application. While the framework defines certain aspects of object persistence, it specifically
doesn’t require that you use any particular data access technology. This means you can choose
from any data access technology and any database or data storage technology available in the .NET
ecosystem.
Object persistence is managed through a CSLA .NET concept called the data portal. The data
portal manages the creation, retrieval, update, and deletion process for all business objects. By
using the data portal you gain a high level of code consistency, as well as the flexibility to switch
between 1-, 2-, 3-, and 4-tier physical deployments of your application with no impact on your
application’s code.
By the end of this book you will understand the four object persistence models supported by
CSLA .NET, and how to use and configure the data portal.

Framework Code and Samples


The CSLA .NET framework and related code samples are available from the download page at:
http://www.lhotka.net/cslanet/download.aspx
This ebook uses CSLA 4 version 4.1, and I may refer to samples available in the standard Samples
download for CSLA .NET.
Using CSLA 4: Data Access Page 1
Rev 1.0
Additionally, in the Support folder provided as part of the CSLA 4 installation you will find a
Templates folder that contains very basic sample code illustrating the structure of each business
object stereotype described in this ebook.
Any code samples unique to this ebook will be included as a separate download available from
http://download.lhotka.net
This is also where you will have downloaded this ebook.

Using CSLA 4: Data Access Page 2


Rev 1.0
Chapter 1:
Object Persistence
Object persistence is the process of retrieving and saving the state of an object or object graph into
a data storage mechanism. The most common data storage mechanism is a relational database, but
there are other examples, including XML files, flat text files, and the use of remote SOAP or REST
services.
Persisting objects involves not only the storage of the object’s state, but also the proper
management of the object’s metastate. As an object is retrieved, it becomes old so IsNew is false.
Only objects with an IsSelfDirty value of true should be saved during a save operation.

Architecture and Design Considerations


Recall from Using CSLA 4: CSLA .NET Overview that CSLA .NET is designed around the 5 layer logical
architecture shown in Figure 1.

Figure 1. Five layer logical architecture


Persistence involves fetching and saving the data into the Data Storage layer. This is handled by
the Data Access layer.
As shown in Figure 2, the Data Access layer is deployed to an application server in a 3-tier or 4-
tier physical deployment. The Interface and Interface Control layers are deployed to the client, and
the Business Logic layer is deployed to both the client and server.

Using CSLA 4: Data Access Page 3


Rev 1.0
Figure 2. Five layer architecture in a 3-tier deployment
This implies that there’s some mechanism that allows the client and server to communicate.
That mechanism is the data portal. You can think of the data portal as the technology that
orchestrates object persistence, along with enabling the concept of mobile objects and abstracting
any cross-tier communication between the client and application server.
Conceptually, the data portal sits between the Business Logic layer on the client and the
Business Logic layer on the application server.

Separating Concerns
When thinking about object persistence, there are three broad areas of functionality that should be
considered. Each area has its own concerns and responsibilities that should be kept as separate as
possible. Figure 3 illustrates these areas of concern.

Figure 3. Areas of concern for object persistence

Using CSLA 4: Data Access Page 4


Rev 1.0
The business object contains the state necessary to implement its behaviors as defined by the
user scenario or use case.
The data access layer (DAL) contains the behaviors that directly interact with the data store to
fetch or update data.
The purpose of the data access invocation concern may be less obvious. In a simplistic view, the
business object and DAL interact to persist the object’s state. But something needs to coordinate
the interaction between the business object and the DAL, and this is the purpose of the data access
invocation concern. I am separating out the idea that some code must coordinate or orchestrate
how the business object interacts with the DAL or visa versa.

Data Portal Models


The CSLA .NET data portal supports two models for data access invocation. Each model has two
variations with regard to where the DAL is implemented. I discussed these four models in Chapter 3
of the Using CSLA 4: CSLA .NET Overview ebook.

Encapsulated Models
Two of the four models encapsulate the data functionality within the business classes. The data
access code itself may be in an external data access component, or it may be implemented directly
within the business class.
Either way, the basic structure of a business class is consistent. This example shows the code
necessary to implement a Fetch operation:
[Serializable]
public class PersonEdit : BusinessBase<PersonEdit>
{
public static void GetPersonEdit(int id, EventHandler<DataPortalResult<PersonEdit>> callback)
{
DataPortal.BeginFetch<PersonEdit>(id, callback);
}

#if !SILVERLIGHT
public static PersonEdit GetPersonEdit(int id)
{
return DataPortal.Fetch<PersonEdit>(id);
}

private void DataPortal_Fetch(int id)


{
// invoke external DAL here (encapsulated invoke)
// or implement DAL code here (encapsulated implementation)
}
#endif
}

The asynchronous and synchronous factory methods invoke the client-side data portal to initiate
the Fetch operation. The client-side data portal uses convention and configuration to determine
how to communicate with the server-side data portal. Remember that the “server-side” data portal
will be running on the physical client machine in a 1- or 2-tier deployment.
The server-side data portal creates an instance of the business class and invokes the
DataPortal_Fetch method, passing the criteria value provided by the factory method into the
DataPortal_Fetch method.
Using CSLA 4: Data Access Page 5
Rev 1.0
You can implement DataPortal_Fetch to interact with an external data access component; a
model called encapsulated invocation. Or, you can implement the data access code directly in the
DataPortal_Fetch method; a model called encapsulated implementation.

Silverlight and WP7


The DataPortal_XYZ methods are slightly different when implemented on Silverlight or WP7. The
reason for this is that all server access from Silverlight is required to be asynchronous, and the most
common implementation of a DataPortal_XYZ method on Silverlight is to call a remote SOAP or
REST service.
If the remote service call is asynchronous, then the DataPortal_XYZ method must also be
asynchronous. This means that the method must accept a callback parameter so the calling code
can be notified when the asynchronous operation is complete.
The method must also be public because of limitations on dynamic method invocation and
reflection in Silverlight and WP7.
Here’s an example of DataPortal_Fetch for Silverlight or WP7:
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void DataPortal_Fetch(
int id, Csla.DataPortalClient.LocalProxy<PersonEdit>.CompletedHandler handler)
{
try
{
// invoke external DAL here (encapsulated invoke)
// or implement DAL code here (encapsulated implementation)
handler(this, null);
}
catch (Exception ex)
{
handler(null, ex);
}
}

Notice that the method is public, and that it accepts a CompletedHandler parameter that must
be invoked when the method is complete. It is also a void method, because all results are returned
through the callback handler.

It is critical that the callback parameter be invoked when the method is complete,
whether an exception occurs or not. If the callback parameter isn’t invoked, the data
portal won’t know that the method has completed. The application will be stuck
thinking the data access operation is still running.

If the code in the DataPortal_XYZ method does invoke an asynchronous service or other
asynchronous operation, the callback handler should not be invoked until the asynchronous
operation is complete.
I often use the EditorBrowsable attribute from the System.ComponentModel namespace to
“hide” the method from Intellisense. Ideally this method would be non-public because it should
never be called except by the data portal. Unfortunately, due to limitations on reflection and
dynamic method invocation in Silverlight and WP7, the method must be public. The
EditorBrowsable attribute helps minimize the impact by hiding the method from developers using
the business type.
Using CSLA 4: Data Access Page 6
Rev 1.0
Factory Models
Two of the four models require implementation of a factory object that manages the data access
interaction for the business type. The data access code itself may be in the factory class, or it may
be in an external data access component invoked by the code in the factory class.
Either way, the basic structure of the business and factory classes are consistent. This example
shows the code for a business class using a factory model:
[Serializable]
[ObjectFactory("MyApp.DataAccess.PersonFactory,MyApp.DataAccess")]
public class PersonEdit : BusinessBase<PersonEdit>
{
public static void GetPersonEdit(int id, EventHandler<DataPortalResult<PersonEdit>> callback)
{
DataPortal.BeginFetch<PersonEdit>(id, callback);
}

#if !SILVERLIGHT
public static PersonEdit GetPersonEdit(int id)
{
return DataPortal.Fetch<PersonEdit>(id);
}
#endif
}

The ObjectFactory attribute on the business class tells the data portal to create and use a
factory object to manage the data access interaction for this business type. The attribute requires
that a factory name be supplied. By default, this name is the assembly qualified name of the factory
type. You can create a custom factory loader that interpets this value in any way you choose.
The asynchronous and synchronous factory methods invoke the client-side data portal to initiate
the Fetch operation. The client-side data portal uses convention and configuration to determine
how to communicate with the server-side data portal. Remember that the “server-side” data portal
will be running on the physical client machine in a 1- or 2-tier deployment.
Notice that there’s no DataPortal_Fetch method in the business class. When using a factory
model, there are no DataPortal_XYZ methods in the business class. All data access related code is
in a separate factory class. The server-side data portal creates an instance of the factory class and
invokes a Fetch method on the factory object, passing the criteria value provided by business
class’s static factory method into the Fetch method.
This example shows a factory class that supports the Fetch operation for the PersonEdit
business class:
public class PersonFactory : ObjectFactory
{
public PersonEdit Fetch(int id)
{
var result = new PersonEdit();
// implement DAL code here (factory implementation)
// or invoke external DAL here (factory invoke)
MarkOld(result);
return result;
}
}

In a factory model, the factory is responsible for several steps, including the following:

Using CSLA 4: Data Access Page 7


Rev 1.0
 Creating the business object instance
 Invoking or implementing the data access code
 Managing the business object’s metastate
 Returning the business object as a result

Although there’s no requirement that a factory class inherit from the ObjectFactory base class,
this base class does provide protected methods that make it easier to implement a factory class.

Silverlight and WP7


As with the encapsulated models, if you implement an object factory that will run on Silverlight or
WP7 the methods must accept a callback parameter that is invoked when the method is complete.
Again, the reason for this is that the data access code will most likely invoke an asynchronous
SOAP or REST service, and so the object factory methods must also be asynchronous. Here’s an
example of a factory type for Silverlight or WP7:
public class PersonFactory : ObjectFactory
{
public void Fetch(
int id, Csla.DataPortalClient.LocalProxy<PersonEdit>.CompletedHandler handler)
{
try
{
var result = new PersonEdit();
// implement DAL code here (factory implementation)
// or invoke external DAL here (factory invoke)
MarkOld(result);
handler(result, null);
}
catch (Exception ex)
{
handler(null, ex);
}
}
}

The callback handler is invoked to tell the data portal when the method is complete, and that is
how the result is returned to the data portal.

It is critical that the callback handler be invoked whether an exception occurs or not.
If the callback handler isn’t invoked the data portal will not know that the method
has completed.

If the code does invoke an asynchronous service or behavior, the callback handler should be
invoked when the asynchronous operation is complete.

Data Portal Model Overview


At this point I will revisit all four models with a focus on the role of the data access invocation
concept and the impact of each model on the business object.
Throughout this discussion you should be aware that the client-side data portal functionality is
the same for all four models. The selection of model only affects the implementation of server-side
code.
Using CSLA 4: Data Access Page 8
Rev 1.0
Remember that when talking about the data portal, “server-side code” is a logical concept, and
the “server-side code” will run on the client machine in a 1- or 2-tier physical deployment. Please
refer to the Using CSLA 4: CSLA .NET Overview ebook for more details.
The four models are listed in Table 1.

Model Name Data portal DAL location Description Result


invokes
Encapsulated Business Separate The data portal creates Encapsulation preserved
Invocation object DAL the business object and
Metastate auto-managed
assembly invokes methods on that
object; the business object Clear DAL separation
then invokes the DAL to Medium complexity
persist its data
Factory Factory object In factory The data portal creates Encapsulation violated
Implementation class the factory object and
Metastate handled
invokes methods on that
manually
object; the factory object
then creates the business Clear DAL separation
object and implements the Medium complexity
DAL directly in the factory
class
Factory Factory object Separate The data portal creates Encapsulation violated
Invocation DAL the factory object and
Metastate handled
assembly invokes methods on that
manually
object; the factory object
then creates the business Clear DAL separation
object and invokes the High complexity
DAL to persist the data
Encapsulated Business In business The data portal creates Encapsulation preserved
Implementation object class the business object and
Metastate handled auto-
invokes methods on that
managed
object; the business object
implements the DAL No DAL separation
directly in the business Low complexity
class

Table 1. Data access models supported by the data portal


I’ve listed the items in Table 1 in order of my preference. The first two are the best options for
most applications. The third has more layers of abstraction than is necessary. The fourth is the
simplest, but doesn’t allow for a clearly separated Data Access layer.
I will discuss each model in more detail, but first I will expand on the results or outcomes you can
expect from each model. As you can see from the right-most column in Table 1, there are four
important outcomes or results you can expect depending on which data portal model you choose.

Using CSLA 4: Data Access Page 9


Rev 1.0
Encapsulation
Although it would be ideal if the business object had no knowledge of persistence at all, it is
important to consider the principal of encapsulation. This is an object-oriented programming
concept that says no object should directly interact with the private members of another object.
Not all persistence techniques preserve encapsulation. In fact, some ORM tools blatantly violate
this principle by having the tool directly get and set private field values in the business objects. The
reality is that sometimes it is worth violating the principle of encapsulation to achieve clean
separation of concerns between the business object and the other.
You can see from Table 1 that the two models where the data portal invokes the business object
almost automatically preserve encapsulation, whereas the use of factory objects typically means
encapsulation is violated. The reality isn’t quite that clear-cut though, because it is possible to
create the DAL to preserve or violate encapsulation in any of the models.
As I demonstrate how to implement each model later in this ebook, you will see how the direct
application of each model preserves or violates encapsulation as listed in Table 1.

Metastate Management
I’ll discuss managing state and metastate in detail later in this chapter. You should be aware that
the two object factory models do require that you manage all business objects’ metastates
manually, whereas the other two models allow the data portal to manage the metastate
automatically.
Automatic management of metastate helps reduce common bugs and results in simpler code.
Manual metastate management allows for broad flexibility in the DAL implementation. So the
choice is really one of simplicity vs flexibility.

Separation of the Data Access Layer


Separation of concerns is an important factor in the maintability of code.
Building a separate Data Access layer has been a recognized best practice for many years, if for
no other reason than to minimize the impact on the application from Microsoft’s continual changes
to their data access technologies. By abstracting any use of a data access technology to a separate
data access component it is possible to switch to new or different data access technologies over
time without substantial impact to the rest of your application code.
Another reason this is important is the idea of a “pluggable” DAL implementation where you can
have more than one implementation of the DAL and can just switch between them through
configuration. For example, you might have one DAL implementation that talks to your real SQL
Server database, and another implementation that uses mocked up in-memory data for testing. Or
you might have a SQL Server implementation, an Oracle implementation, and a MySQL
implementation.
Looking at Table 1 you can see that three of the four data portal models enable clean separation
of the Data Access layer. The last model is the simplest, in part because it embeds the data access
code directly in the business class. The cost of that simplicity is the lack of any separation of the
data access code from the rest of the code in your Business layer.

Using CSLA 4: Data Access Page 10


Rev 1.0
Implementation Complexity
Complex code is typically harder and more expensive to build and maintain than simpler code.
Sources of complexity include; sheer volume of code, complexity of algorithms or concepts, and
extraneous layers of abstraction.
Just having a separate DAL creates some complexity. It requires having at least one more project
in your solution, defining the interface between the DAL and the business object, and avoiding
circular loops in type and assembly references. However, this complexity is typically offset by the
clarity of code provided through separation of concerns.
Now that you have an understanding of the different results that will flow from each model, I’ll
discuss each model in more detail in this chapter. I’ll include a process diagram for each model. In
Chapter 2, I will provide an example implementation of each model.

Encapsulated Invocation
In this model the server-side data portal component creates an instance of the business class and
invokes a DataPortal_XYZ method on that object. The business object is responsible for invoking
the DAL.
Figure 4 illustrates the process flow for this model.

Figure 4. Encapsulated invocation data portal process flow


I recommend the encapsulated invocation model because it provides for clear separation of the
DAL, preserves encapsulation of the business object state, and also allows the data portal to
manage the object’s metastate.
This balance of simplicity and flexibility is usually ideal. The one potential drawback to this model
is that you must devise your own scheme to enable a pluggable DAL by implementing your own
Using CSLA 4: Data Access Page 11
Rev 1.0
layer of indirection. I’ll demonstrate one simple implementation of a pluggable DAL later in this
book.

Factory Implementation
With the factory implementation model, the server-side data portal component creates an instance
of a factory object based on the information provided by an ObjectFactory attribute on the
business class. This factory object is responsible for the following:

 Creating the business object


 Implementing the DAL functionality

Figure 5 illustrates the process flow for this model.

Figure 5. Factory implementation data portal process flow


Factory invocation is a model I often recommend, due to its balance of simplicity and flexibility.
Although this model requires that your factory objects create the business objects and manage
their metastate, the data portal’s factory object model automatically enables a pluggable DAL
model. The data portal allows you to implement a factory object loader class, where you can write
code to load the appropriate DAL implementation based on configuration.

Factory Invocation
In the factory invocation model, the server-side data portal component creates an instance of a
factory object based on the information provided by an ObjectFactory attribute on the business
class. This factory object is responsible for the following:

 Creating the business object


Using CSLA 4: Data Access Page 12
Rev 1.0
 Invoking the DAL
 Coordinating how data moves between the business object and DAL

Figure 6 illustrates the process flow for this model.

Figure 6. Factory invocation data portal process flow


I rarely recommend this model, as it involves extraneous layers of indirection. The data portal’s
factory object model already enables a pluggable DAL, so implementing your own pluggable DAL
model to be invoked from factory objects means you have two layers of indirection designed to do
the same thing. That’s just adding complexity with no value.

Encapsulated Implementation
In the encapsulated implementation model, the DAL functionality is implemented directly in the
DataPortal_XYZ methods in the business classes. This model involves the simplest code, but at the
expense of any flexibility or clear separation between the business code and data access code.
Figure 7 illustrates the process flow for this model.

Using CSLA 4: Data Access Page 13


Rev 1.0
Figure 7. Encapsulated implementation data portal process flow
Although this model might seem simple at first glance, the lack of separation of concerns will
typically make the application harder to maintain over time.
In the end, you need to choose the data portal model that best meets your requirements. As you
make your choice, you need to balance the value of encapsulation, separation of concerns,
automatic metastate management, and overall complexity.

Persisting Non-CSLA .NET Objects


Throughout this book and the rest of the Using CSLA 4 ebook series, I am focusing on how the data
portal is used to persist business domain objects created using the CSLA .NET base classes to
implement the stereotypes covered in the Using CSLA 4: Creating Business Objects ebook.
You should be aware that the data portal can be used to persist objects of any serializable type,
including types that don’t follow the CSLA .NET stereotypes. The stereotypes supported by CSLA
.NET are usually sufficient to implement most business applications. But if your application needs to
define its own stereotypes, they can be used with the data portal.
The data portal does include some functionality focused on the existing CSLA .NET base types,
including automatic management of metastate and some other features. But the basic capability of
the data portal to support mobile objects and object persistence is available to any serializable type.
I discuss what it means to be a serializable type in Chapter 1 of the Using CSLA 4: Creating
Business Objects ebook. To recap, a serializable type has either the Serializable or DataContract
attributes in .NET, and must have the Serializable attribute and implement the IMobileObject
interface on Silverlight and WP7.
In most cases, your applications will use the existing CSLA .NET types as discussed in this book,
but if you need to use the data portal to create, fetch, update, or delete other serializable objects
you can do so.
Using CSLA 4: Data Access Page 14
Rev 1.0
Managing State and Metastate
Object persistence involves retrieving and saving object data into a data storage mechanism like a
database. Since objects are often inter-related through parent-child relationships, object
persistence applies to entire object graphs, not only to single objects.
As I mentioned earlier in this chapter, object persistence requires proper management of the
metastate for each object in the object graph, along with management of object state. In most
cases it also requires interaction with database transactions to ensure that the database and the
objects in memory remain in a consistent and predictable state over time.

Object Relational Mapping


Good relational data design involves normalizing data and minimizing data duplication within the
data store. Good object design involves designing objects that meet the needs of each user
scenario, use case, or user story. If you do a good job with both relational data design and business
object design, you will end up with two very different models: one for data and one for behavior.
Perhaps the most common example of the mismatch between data and object design is that a
data entity will contain a lot of information. You might have dozens of columns of data in a
customer or product table. But only a small subset of those columns are required for most user
scenarios. For example, the select a product use case probably only requires a handful of fields from
the product table, even though the product table almost certainly has dozens of columns.
Well designed objects exist because they have a single responsibility or purpose to fulfill within
the context of one use case. Well designed database tables exist because they contain all data
relevant to a single data entity.
The difference between the shape of business objects and the shape of data tables must be
reconciled during the object persistence process. This reconciliation is often referred to as object-
relational mapping (ORM) because data elements are mapped between the object model and the
relational model.
There are many ORM tools on the market, but they rarely enable mapping of relational data into
true behavioral business domain objects. Most of them are designed to help you map relational
data from the database into object models that are directly derived from the shape of the database.
This is useful, because it can simplify the code required to get the data out of the database and into
memory, and out of database types and into .NET types. But you should understand that these tools
don’t provide a complete solution to map relational data into the kind of object-oriented business
objects you should be designing for your applications.
I have no problem using ORM tools, but I view them as a technology that should be isolated to
the Data Access layer in your application. No aspects or elements of your data access technology
should be used in code found in the Interface, Interface Control, or Business Logic layers. This
includes special attributes or interfaces required by an ORM tool that might otherwise “sneak into”
your business classes.

The goal should be complete isolation of data access technologies (including ORM
tools) within the Data Access layer so all other layers of the application are
independent and unaware of the data access technology in use.
Using CSLA 4: Data Access Page 15
Rev 1.0
Managing State
Well designed business objects exist because they have a responsibility or purpose within the
context of a use case or user scenario. Most objects require some data to implement the behaviors
necessary to fulfill that responsibility. This data is called the state of the object.

I view the behavior of an object as being the most important part of the object, and
any state contained in the object is only present to meet the needs of those
behaviors.

Most object state is persisted as the object is retrieved or saved. Some object state might be
calculated or derived from other state, or by interacting with other business objects; and that state
is usually not persisted.
Some application data exists completely in the database, at least from the perspective of any
specific user scenario. One example might be a user scenario where the user edits some customer
information. The objects represent behaviors around finding and selecting the customer to edit,
and then retrieving, editing, validating, and saving the customer data.
But at the Data Storage layer, there might be triggers or stored procedures that automatically
create audit log information to record which user retrieved and saved the customer data. This audit
information is probably critical application data, but may have no representation in the business
objects for this user scenario because that data has no relevance to the user.
You need to try to ensure that your business objects only contain the minimum state necessary
to implement the behaviors the object needs to fulfill its responsibility. That state is what will be
persisted by the Data Access layer as the object is retrieved or saved.
It is important to understand that persisting state is a bi-directional process. When you fetch an
object, that object’s state is loaded by the Data Access layer from the Data Storage layer. When you
save an object, that object’s state is inserted, updated, or deleted in the Data Storage layer. That
process will often affect the state of the object as well.
For example, when you insert a new row into a database, the database often creates a new
primary key and a new timestamp value for that row. Both of those values are usually part of the
object’s state. Similarly, when you update an existing row in a database, the database often creates
a new timestamp value for that row, and this timestamp value is part of the object’s state.
This means that even the operation of saving an object’s state will usually alter the object’s state
as part of the process.
As I discuss each persistence operation and how those operations are supported by the data
portal you will see this bi-directional requirement has on object persistence.

Concurrency
Concurrency is often necessary to protect data integrity in multi-user applications. There are three
basic types of concurrency:

1. Optimistic, last write wins

Using CSLA 4: Data Access Page 16


Rev 1.0
2. Optimistic, first write wins

3. Pessemistic

Pessemistic concurrency generally requires “locking” of data in the database so only one user
can interact with the data at any given time. Today’s highly distributed applications, and modern
data access technologies don’t generally support pessimistic concurrency, and so I won’t discuss it
here.
Optimistic concurrency doesn’t “lock” any data. Instead, it relies on the application to determine
whether changes to the database can be overwritten by other concurrent users of the application.
The default behavior of an application that doesn’t implement concurrency is optimistic, last
write wins. If multiple users edit the same data and then save their edits, each subsequent user’s
save will overwrite any previously saved values. This means that the edits made by the last user to
save are the only edits preserved in the database.
You can choose to implement optimistic, first write wins. In this case, the first user to save will
have their edits persisted in the database. All subsequent concurrent users will be unable to save,
typically getting an exception indicating that they are attempting to overwrite someone else’s
changes to the data.
The most common way to implement this type of concurrency is to use a timestamp column in
each table of the database. This timestamp value is updated any time a record is inserted or
updated into the database.
When the application retrieves data from the database table, it also retrieves the timestamp
value. Before saving the data the database ensures that the timestamp of the data in memory
matches the timestamp on the table. If the timestamp values match the database knows that the
data in the database hasn’t already been changed. On the other hand, if the timestamp values don’t
match, the database will raise an error to indicate a concurrency violation.
In the context of a CSLA .NET application, the timestamp value or values from the database must
be maintained as properties in the business object graph. These are usually private properties,
because they provide no value to the user interface or other business logic. These properties exist
for the purpose of storing the timestamp value between the time the data is retrieved from the
database and when an update operation is attempted to change the values in the database.

Transactions
Most database update operations are protected by a database transaction. Within .NET there are
four major transactional technologies:

 ADO.NET transactions
 Database-level transactions
 TransactionScope from the System.Transactions namespace
 Enterprise Services (COM+) distributed transactions

Using CSLA 4: Data Access Page 17


Rev 1.0
The data portal allows you to use any of these transaction models. These transaction models
apply only to the database, not to your business objects. Business objects exist in memory, and are
not automatically protected by any sort of transaction.
In the Using CSLA 4: Creating Business Objects ebook, I discussed the concepts of root and child
objects. In CSLA .NET object models, there is only one root object in an object graph. All other
objects in that graph are child objects. When you persist the object graph, this root object is
important because it also becomes the root of any database transaction.
The data portal understands the difference between root and child objects, and it provides the
ability to enlist in a transaction before the root object is persisted. That same transaction applies to
all child object data. If a database operation fails for any object in the object graph (and you are
using a transaction), all database operations for the entire object graph will be rolled back.

AutoCloneOnUpdate Feature
The challenge is that persistence is bi-directional. So as the state of each object in the graph is saved
into the database, that object was probably changed to reflect any database-generated key or
timestamp values. Although the database will roll back to a consistent state if there’s a failure, the
objects in memory could be left in an indeterminate state where they contain data that no longer
matches what’s in the database.
The data portal includes functionality to prevent this from being a problem: the
AutoCloneOnUpdate feature. Before the data portal invokes your Data Access layer code, it takes a
snapshot of the object graph. In the case of failure, the database transaction first rolles back all
changes to the database. Then, the data portal reverts the object graph to this snapshot. This
ensures that all objects in the graph are also in a known state.

Disabling AutoCloneOnUpdate
There is some overhead to taking this snapshot, and it is possible to disable this feature of the data
portal. You might disable this feature if you encounter performance issues due to the feature, and if
you are able to implement an alternative solution to the problem.
The most common alternative solution is to entirely discard the object graph and to reload it
from the database. This solution also incurs a great deal of overhead, and results in the user losing
any changes they’ve made to the state of the objects in the graph.
Another common alternative is to entirely discard the object graph and to throw an exception.
This solution avoids the overhead, but leaves the user with no object graph and typically just some
error dialog on their screen.
If you do want to disable the feature you need to add an entry to your app.config or
web.config file in the appSettings region:
<appSettings>
<add key="CslaAutoCloneOnUpdate" value="False"/>
</appSettings>

This will disable the feature for all objects in your application.
I will demonstrate the use of transactions later in this book as I walk through the various ways
you can implement a Data Access layer.
Using CSLA 4: Data Access Page 18
Rev 1.0
Managing Metastate
In the Using CSLA 4: Creating Business Objects ebook, I discussed the idea of object metastate, and
how CSLA .NET business objects maintain and use various metastate values such as:

 IsNew
 IsDirty
 IsSelfDirty
 IsDeleted
 IsValid
 IsSelfValid
 IsSavable
 IsBusy
 IsSelfBusy

As objects are retrieved and saved during the persistence process, these metastate values must
be correctly updated. The data portal can be used in two different modes, one of which will
automatically manage the metastate on your behalf, and the other of which you must manually
update the values.
The primary metastate values that must be maintained during object persistence are listed in
Table 2.

Value Description
IsNew This value should be true when there is reasonable expectation that the
primary identifier of the object doesn’t correspond to any row or element in
the data store; it should be false if there’s a reasonable expection that the
object corresponds to a row or element in the data store
IsSelfDirty This value should be true if there is a reasonable expectation that one or
more state values don’t match their corresponding values in the data store;
it will also be true if the IsDeleted metastate property has been set to true
IsDeleted This value is set to true to indicate that data corresponding to the object
should be deleted from the data store during an Update persistence
operation

Table 2. Primary metastate values related to persistence


These properties are managed through the use of protected methods defined in the
BusinessBase class.

The MarkNew method must be called as an object is created. This method results in IsNew and
IsSelfDirty being true, and IsDeleted being false.

The MarkNew method is also called after an object has been deleted during an update operation.
At first glance, this may seem strange, but once an object has been deleted it meets the definition
of a new object because the object’s state no longer corresponds to data in the data store.
Using CSLA 4: Data Access Page 19
Rev 1.0
The MarkOld method must be called after an object has been updated (inserted or deleted into
the data store). This method results in IsNew, IsSelfDirty, and IsDeleted being false.
The MarkDeleted method is called on a root object to mark that object for deletion. This sets the
IsDeleted property to true. The IsDeleted property of child objects is set to true by the parent
object, never directly on the child object. Typically, this occurs when a child object is removed from
a parent BusinessListBase object.
If you are implementing a parent object that directly contains a child object (without an
intervening collection), your parent object will use the DeleteChild method defined on the
IEditableBusinessObject interface in the Csla.Core namespace. The BusinessBase class
implements this interface, so all editable child objects can be cast to the IEditableBusinessObject
type.
Again, whether you need to manually worry about these details depends on which data portal
model you choose to utilize in your application. I will show you examples of each model later in this
book.

Data Access Technologies


One of the primary design goals for CSLA .NET and the data portal is to be database neutral, and
also data access technology neutral. When building a Business layer with CSLA .NET, you should be
able to use nearly any database and data access technology, or even combinations of several data
storage and data access technologies.
Examples of data storage technologies include:

 SQL Server
 SQL Azure
 Windows Azure Storage
 Oracle
 MySQL
 DB2
 SOAP services
 REST services
 XML files
 Delimited text files
 Isolated storage
 Mainframes or other legacy systems

If you can write .NET code to interact with your data store, you should be able to use
that technology to persist your business object state.

Using CSLA 4: Data Access Page 20


Rev 1.0
Most data storage technologies are only available to .NET code, and can’t be directly used from
Silverlight or WP7. If you are writing data access code that will run on a Silverlight or WP7 client
your options include:

 SOAP services
 REST services
 Isolated storage

If your Silverlight or WP7 application needs to access other data sources, you should either use
the data portal in a 3- or 4-tier deployment, or call remote SOAP or REST services that provide
access to the required data.

Accessing Relational Databases


When interacting with a relational database in .NET, you’ll typically use one of the standard .NET
data access technologies, including:

 Raw ADO.NET (connection, command, datareader)


 ADO.NET Entity Framework
 TableAdapter/DataTable/DataSet
 LINQ to SQL

You might also use third party ORM tools, data access tools, or abstractions over raw ADO.NET
such as the Enterprise Library’s Data Access Application Block (from Microsoft’s Patterns and
Practices group).
CSLA .NET doesn’t dictate which technology you use to interact with your relational databases.
My recommendation is to use either raw ADO.NET or the ADO.NET Entity Framework.
You should realize that raw ADO.NET is the basis for every other data access technology. Every
other data access technology is built on top of raw ADO.NET. If you are looking for the highest
performance, “closest to the metal” option then you should choose raw ADO.NET. Everything else is
just a layer of abstraction over this core technology.
Microsoft has made it clear that their current strategic data access technology choice is ADO.NET
Entity Framework (EF). This technology is an abstraction layer over raw ADO.NET that provides
object-relational mapping (ORM) features and may allow you to author simpler code for database
interaction than the code you’d write with raw ADO.NET.
The TableAdapter and DataSet technology has been part of .NET from the beginning, but it
hasn’t carried forward into newer platforms like Silverlight and WP7. Other newer technologies
such as WCF Data Services are built on top of EF and don’t work well with the DataSet. In general
my recommendation is to avoid building new code using the TableAdapter/DataSet model.
LINQ to SQL is a competitor to EF, and it also provides basic ORM functionality. As I mentioned
earlier, Microsoft has made it clear that their current strategic data access technology choice is EF.
For this reason, my recommendation is to avoid building new code using LINQ to SQL.

Using CSLA 4: Data Access Page 21


Rev 1.0
Accessing Services
There are several technologies available in .NET for accessing SOAP and REST services. These
include:

 Windows Communication Foundation (WCF)


 Web Services
 WebRequest and WebClient

In general, you should use WCF to call remote services. Microsoft has made it clear that their
strategic technology direction for service authoring and invocation is WCF.
Older .NET applications would add a web service reference to SOAP services, allowing Visual
Studio to generate a web service client proxy using the web services technology. Although you can
still use this technology, you can accomplish the same thing using the more modern WCF
technology by adding a service reference to your project.
There may be times when it is simpler to call some non-SOAP services manually through the
WebRequest or WebClient types in .NET. This is a lower level and less abstract technology than WCF
or web service client proxies, and can give you more control over how your code interacts with the
remote service.

Accessing Isolated Storage


The one data storage technology that is common across .NET, Silverlight, and WP7 is isolated
storage. This technology has been part of .NET since the beginning, and it provides an abstract API
for interacting with files on the local client or device.
Isolated storage is valuable because the developer has limited control over the files. The .NET
framework manages the file locations and file access, providing simple stream-based access to the
file contents. On Silverlight and WP7, the total amount of data an application can store in isolated
storage is restricted. The point of isolated storage is to provide a client-side storage location that
applications can use without any risk of compromising the integrity of the client.
Because the isolated storage API provides only stream-based access to the file contents, you are
left to invent any higher level abstraction for data storage. In many cases, developers choose to
store data in XML format, reading and writing the XML data into the isolated storage files.
It can be tempting to consider the use of object serialization to store application data in isolated
storage files. The BinaryFormatter, NetDataContractSerializer, and MobileFormatter are all
capable of converting an object graph into a byte stream that can be stored in a file, and then
convering the contents of that file back into objects in the future.

You should not use object serialization to persist object data in files.

You should resist this temptation. These serializers are all version sensitive. If you serialize an
object graph to a file, then update the application with new assemblies (including changing your
business types), you may be unable to deserialize the data from the file back into objects. At that
point, you’ve lost the data.
Using CSLA 4: Data Access Page 22
Rev 1.0
Instead, you should treat isolated storage files like any other data storage technology. Any data
should be persisted into these files through a formal data access layer.

Accessing Other Data Sources


There are many possible data sources beyond relational databases and services. Typically those
data sources have their own specialized data access technology or API that you must use when
interacting with those data sources.
The important thing to remember is that if you can write .NET code to interact with your data
source, you can encapsulate that code in a data access component and use it as a DAL to persist
your CSLA .NET business objects.

Accessing Multiple Data Sources


To this point I have been discussing how you can use different data sources and data access
technologies to implement your Data Access layer functionality. It is important to realize that the
Data Access layer is essentially composed of methods that interact with the database or other data
store.
There is absolutely no reason a DAL method is restricted to interacting with a single data store,
or to using a single data access technology. This means a DAL method might read data from a SQL
Server database and from a mainframe if that data is needed to populate the business object’s
state.
The one area of complexity you may encounter is with transactional updates. Not all data
sources support the concept of simple transactions, and even fewer support the concept of
distributed transactions. Most relational databases support distributed transactions through
Enterprise Services, but data sources such as XML or flat files have no transactional support. If your
DAL needs to update multiple data sources to persist an object’s state, you will need to determine
how (or if) transactional support can be provided based on the technologies being used.
At this point you should understand the flexibility available when using the data portal to
implement object persistence. I will now discuss the five persistence operations supported by the
data portal.

Persistence Operations
Data persistence is often described using the CRUD acronym, standing for:

 Create
 Read
 Update
 Delete

It should be clear how these translate to object persistence, in that objects must be created,
fetched (read), updated, and deleted.
Those operations address all the requirements of editable and read-only object stereotypes.
CSLA .NET also supports object stereotypes that represent pure action, such as the Command and
Using CSLA 4: Data Access Page 23
Rev 1.0
Unit of Work stereotypes. To support these stereotypes, the data portal also implements an
Execute operation.
As you read through the following discussion of each operation, remember that child objects are
always persisted as part of their top-level root object. Many data portal operations apply only to
root objects, and it is the responsibility of that root object to persist its child objects. Some data
portal operations exist to help root objects as they implement persistence for their child objects.

Create
The Create operation is used to create new instances of business types. It is important to formally
support the concept of object creation, because some objects must be initialized with template
data from the database as they are created.
For example, when creating a new CustomerEdit object for a specific sales person, the new
object might be initialized with the sales person’s information, including their id, region, and other
relevant information.
This information will often come from the database, and you can think of a Create operation as
being very much like a Fetch operation, except that the object is loaded with template data instead
of existing object data.
Sometimes you won’t need to initialize a new object with data, and the data portal supports this
requirement as well.
Table 3 lists the data portal methods that support this operation.

Method Description
Create Synchronously creates and initializes a new root object
BeginCreate Asynchronously creates and initializes a new root object
CreateChild Synchronously creates and initializes a new child object; only available when
using one of the encapsulated data portal models (see Table 1)

Table 3. Data portal methods supporting the Create operation


The Create and BeginCreate methods are found on the client-side DataPortal type. The data
portal routes the request to the server-side data portal component, and that component invokes
your business object or factory object depending on the data portal model you are using. Either
way, if creating the business object requires interaction with the database, the code is running on
the server and can interact with the DAL as necessary.
Here are examples of synchronous and asynchronous factory methods using the data portal to
create an object:
#if !SILVERLIGHT
public static PersonEdit NewPersonEdit()
{
return DataPortal.Create<PersonEdit>();
}
#endif

public static void NewPersonEdit(EventHandler<DataPortalResult<PersonEdit>> callback)


{
Using CSLA 4: Data Access Page 24
Rev 1.0
DataPortal.BeginCreate<PersonEdit>(callback);
}

Once the business object has been created and initialized, it is returned to the calling code for
use by the application.
The Create and BeginCreate methods accept zero or one criteria parameter that is used to
provide information to the server-side DAL code about how the object should be initialized. If you
need to pass multiple criteria values you need to create a type based on the Criteria object
stereotype as described in Using CSLA 4: Creating Business Objects.

Fetch
The Fetch operation is used to retrieve instances of business types that are populated with data
from the data store.
Table 4 lists the data portal methods that support this operation.

Method Description
Fetch Synchronously retrieves and loads a existing root object
BeginFetch Asynchronously retrieves and loads a existing root object
FetchChild Synchronously retrieves and loads a child object; only available when using
one of the encapsulated data portal models (see Table 1)

Table 4. Data portal methods supporting the Fetch operation


The Fetch and BeginFetch methods are found on the client-side DataPortal type. The data
portal routes the request to the server-side data portal component, and that component invokes
your business object or factory object depending on the data portal model you are using. The
server-side code can then interact with the DAL to read the appropriate data for the object.
Here are examples of synchronous and asynchronous factory methods using the data portal to
fetch an object based on an int id value:
#if !SILVERLIGHT
public static PersonEdit GetPersonEdit(int id)
{
return DataPortal.Fetch<PersonEdit>(id);
}
#endif

public static void GetPersonEdit(int id, EventHandler<DataPortalResult<PersonEdit>> callback)


{
DataPortal.BeginFetch<PersonEdit>(id, callback);
}

Once the business object has been loaded with data it is returned to the calling code for use by
the application.
The Fetch and BeginFetch methods accept zero or one criteria parameters that is used to
provide information to the server-side DAL code so it can find the appropriate data to use when
loading the business object’s state. If you need to pass multiple criteria values, you need to create a
type based on the Criteria object stereotype as described in Using CSLA 4: Creating Business
Objects.
Using CSLA 4: Data Access Page 25
Rev 1.0
Update
The Update operation is the most complex operation, because it can result in different actions
depending on the metastate values of the business objects in the object graph. These actions are:

 Insert
 Update
 Delete

When using one of the encapsulated data portal models (see Table 1), the Update operation
examines the metastate of the business object to determine which action to perform. If you are
using one of the factory data portal models, your factory object code is responsible for examining
the metastate and taking the correct action. Table 5 lists the rules that should be applied. Not all
metastate combinations are possible, so only valid combinations are listed.

IsNew IsDeleted IsDirty Action


n/a n/a false No action (object unchanged)
true false true Insert
true true true No action (no need to delete new object)
false false true Update
false true true Delete

Table 5. Metastate rules applied during the Update operation

Saving Editable Root Objects


Although the client-side DataPortal class does implement Update and BeginUpdate methods, these
methods are not typically invoked directly. Instead, editable objects implement Save and BeginSave
methods and you should call those methods to cause an Update operation.
When using one of the encapsulated data portal models you may use the UpdateChild method
of the DataPortal class to update child objects.
Table 6 lists the methods defined by the data portal for performing the Update operation.

Method Description
Update Synchronously inserts, updates, or deletes a root object
BeginUpdate Asynchronously inserts, updates, or deletes a root object
UpdateChild Synchronously inserts, updates, or deletes a child object; only available
when using one of the encapsulated data portal models (see Table 1)

Table 6. Data portal methods supporting the Update operation


Again, remember that you will not normally call Update or BeginUpdate in your code. Instead,
you should prefer to use the methods listed in Table 7, which are found on all editable root objects.

Using CSLA 4: Data Access Page 26


Rev 1.0
Method Description
Save Synchronously inserts, updates, or deletes a root object by invoking the data
portal
BeginSave Asynchronously inserts, updates, or deletes a root object by invoking the
data portal

Table 7. Methods used to save editable objects


The Save and BeginSave methods apply important business behaviors before invoking the data
portal. Specifically these methods perform the following checks:

 Ensure IsChild is false


 Ensure the object isn’t being edited (EditLevel is 0)
 Ensure IsValid is true
 Ensure IsBusy is false
 Ensure IsDirty is true

As you can see, these are rules that should be checked before an object is saved. This is why you
should prefer to use the Save and BeginSave methods instead of the Update and BeginUpdate
methods from the data portal.
The Save and BeginSave methods are virtual, so if you need to add extra rules or behaviors as
part of the save process you can override these methods.
The Csla.Core namespace also defines an ISavable interface that includes Save and BeginSave
methods. You can use this interface to implement polymorphic code that can save any editable root
object, regardless of whether it is a single object or a list. Table 8 lists the members defined by the
ISavable interface.

Method Description
Save Synchronously inserts, updates, or deletes a root object by invoking the data
portal
BeginSave Asynchronously inserts, updates, or deletes a root object by invoking the
data portal
Saved Event raised when an object has been saved

Table 8. Members defined by the ISavable interface


The methods defined by the ISavable interface invoke the Save and BeginSave methods
defined by the BusinessBase, BusinessListBase, and other base types that support editable root
objects. This means that you can call the methods on the interface, or directly on each business
object, and you’ll get the same resulting behavior.

Using CSLA 4: Data Access Page 27


Rev 1.0
Results of Saving an Object
When an editable object is saved, the result is a new instance of the editable object. It is critical that
the code calling Save or BeginSave update any references to the business object in order to use the
result of the save operation.

Failure to update references to use the object returned from Save or BeginSave is a
common cause of bugs in application code.

Here’s an example showing how to properly call the Save method on an editable object:
_person = _person.Save();

And here’s an example showing how to properly call the BeginSave method on an editable
object:
_person.BeginSave((o, e) =>
{
if (e.Error != null)
throw e.Error;
else
_person = (PersonEdit)e.NewObject;
});

In both cases, notice that the original _person field is updated to use the new object returned as
a result of the save operation. The code handling the asynchronous callback must also check for,
and rethrow or handle, any exceptions that occurred during the async operation.
Most applications will be using data binding to connect the business object to the UI, and that
data binding reference must also be updated. I’ll demonstrate how to update these references in
the UI technologies covered by subsequent books in this ebook series.
The important thing to understand is that all references to the original object must be updated
to use the new object returned from the save operation. Failure to update these references will
cause undesirable results in your application.

ForceUpdate Option
The Save method defined on all editable root objects, and by the ISavable interface, has an
overload that accepts a Boolean parameter named forceUpdate. This overload exists to support a
specific web-based scenario where a web application or service is designed to support a completely
stateless web server.
I will demonstrate the use of the forceUpdate parameter in the Using CSLA 4: ASP.NET MVC
ebook.
Normally, when you call the Save method on an object; the object’s state is inserted or updated
into the database depending on the value of the object’s IsNew property. If the forceUpdate
parameter is true, the data portal will ignore the IsNew property of the business object and will
always perform an update (instead of an insert) action. For example:
var person = PersonEdit.NewPersonEdit();
person.Id = id;
person.FirstName = firstName;
person.LastName = lastName;
person = person.Save(true);
Using CSLA 4: Data Access Page 28
Rev 1.0
The PersonEdit object created will be new (IsNew is true). The object is then loaded with data,
including the object’s Id property (representing its primary key in the database). When the Save
method is called, the forceUpdate parameter is passed as true, so the data portal operates as
though IsNew were false. Instead of an insert action, this results in an update action.
This behavior is necessary in the case where a web postback or service call comes into the web
server that contains all the data from an existing business object. If the server is completely
stateless, it must recreate that existing business object with the data provided in the postback or
service call. When an object is created like this, its IsNew property will be true, even though the
object already exists. The forceUpdate option allows the application to force the data portal to
perform an update instead of an insert action.
The Update operation is the most complex operation because the result is an insert, update, or
delete action. Additionally, editable root objects know how to “save themselves” through their Save
and BeginSave methods. These methods invoke the Update or BeginUpdate methods on the data
portal, so normal business code won’t ever call Update or BeginUpdate directly.

Delete
The Delete operation is used to delete data related to an editable root business object.
Table 9 lists the data portal methods that support this operation.

Method Description
Delete Synchronously deletes data corresponding to a root object
BeginDelete Asynchronously deletes data corresponding to a root object

Table 9. Data portal methods supporting the Delete operation


The Delete and BeginDelete methods are found on the client-side DataPortal type. The data
portal routes the request to the server-side data portal component, and that component invokes
your business object or factory object depending on the data portal model you are using. The
server-side code can then interact with the DAL to delete the appropriate data corresponding to the
object.
Here are examples of synchronous and asynchronous factory methods using the data portal to
delete data corresponding to an object based on an int id value:
#if !SILVERLIGHT
public static void DeletePersonEdit(int id)
{
DataPortal.Delete<PersonEdit>(id);
}
#endif

public static void DeletePersonEdit(int id, EventHandler<DataPortalResult<PersonEdit>> callback)


{
DataPortal.BeginDelete<PersonEdit>(id, callback);
}

Nothing is returned as a result of a Delete operation. The operation either works, or results in an
exception to indicate failure.

Using CSLA 4: Data Access Page 29


Rev 1.0
The Delete and BeginDelete methods accept one criteria parameter that is used to provide
information to the server-side DAL code about what data should be deleted. If you need to pass
multiple criteria values you need to create a type based on the Criteria object stereotype as
described in Using CSLA 4: Creating Business Objects.
This Delete operation only applies to editable root objects. Child object data is always deleted by
marking the child for deletion (so IsDeleted is true) and then saving the root object that contains
the child.
It is also possible to implement deferred deletion for an editable root object. This means the
MarkDeleted method is called on the root object, and then the root object is saved. As part of the
Update operation, the IsDeleted property is used to determine that a delete action should be
taken instead of an insert or update.

Execute
The Execute operation is used to execute arbitrary server-side code that is encapsulated within a
business object. Normally the Execute operation is applied to business objects that inherit from the
CommandBase class.
Table 10 lists the data portal methods that support this operation.

Method Description
Execute Synchronously executes server-side code associated with a command object
BeginExecute Asynchronously executes server-side code associated with a command
object

Table 10. Data portal methods that support the Execute operation
The Execute and BeginExecute methods are found on the client-side DataPortal type. The data
portal routes the request to the server-side data portal component, and that component invokes
your business object or factory object depending on the data portal model you are using. The
server-side code can then implement arbitrary behaviors that run on the server. That server-side
code might interact with the DAL, or any other resources available on the server.
Here are examples of synchronous and asynchronous command object factory methods using
the data portal:
#if !SILVERLIGHT
public static OrderShipper ShipOrder(int orderId)
{
var cmd = new OrderShipper(orderId);
return DataPortal.Execute<OrderShipper>(cmd);
}
#endif

public static void ShipOrder(int orderId, EventHandler<DataPortalResult<OrderShipper>> callback)


{
var cmd = new OrderShipper(orderId);
DataPortal.BeginExecute<OrderShipper>(cmd, callback);
}

Using CSLA 4: Data Access Page 30


Rev 1.0
Notice that the Execute and BeginExecute methods accept the command object as a parameter.
This is because the command object is a mobile object, and the data portal moves this object to the
server where it can be executed, or where the object is made available to the factory object.
Once the server-side execution is complete, the command object is moved back to the client so
any results or other state within the object become available to the application. The Execute
operation is very similar to the Update operation in that any references to the original command
object must be replaced with the object returned from the data portal. Because the data portal call
is usually encapsulated in factory methods as shown in this example, you usually don’t have to
worry about updating client-side references.
At this point, you should have a high level understanding of the five operations supported by the
data portal for object persistence. In Chapter 2, I will dig deeper into related functionality provided
by the data portal, and will demonstrate how to implement each of the four data portal models
discussed in Chapter 1.

Using CSLA 4: Data Access Page 31


Rev 1.0
Chapter 2:
Data Portal
In Chapter 1 I discussed the four data access models supported by the data portal (see Table 1). In
this chapter I will walk through an example implementation of each model:

 Encapsulated Data Access Invocation


 Object Factory Data Access Implementation
 Object Factory Data Access Invocation
 Encapsulated Data Access Implementation

Each model offers different benefits, but I am covering them in order from most to least
recommended, with a focus on the encapsulated invocation and factory implementation models.
See the discussion in Chapter 1 for more background information.
Before I provide examples of each of the data portal models, I will discuss some concepts that
are common to all four models. This includes; authorizing data portal requests, handling
transactions, and the basic structure of the DataPortal_XYZ methods and factory methods.

Client-Side Data Portal Concepts


The client-side data portal is invoked any time a business object is created, retrieved, saved, or
deleted. Chapter 5 will provide details on how to configure the data portal, but there are some
code-level concepts as well.

Calling the Client-Side Data Portal on the Server


Most of my examples show the client-side data portal being called by static factory methods in a
business class. And most examples show these static factory methods being called by Presentation
layer code running on the client workstation or the web server.
It is important to understand that these factory methods can also be called by code running on
the application server. The data portal enables a concept called location independence, which
means that you can call the “client-side” data portal on the client or application server and your
code will work as expected. Code that calls the client-side data portal works independent of the
physical location where the calling code is running.
When client-side data portal methods are invoked by code running on a client workstation or
web server, the data portal uses convention and configuration to determine how to communicate
with the server-side data portal. In 3- and 4-tier deployments, the result is a network call to the
application server where the server-side data portal is installed.
When client-side data portal methods are invoked by code running on the application server, the
data portal understands that it is already running on the server. For this reason, it makes no effort
to go across the network. Instead, it directly invokes the server-side data portal that is already
running in the same process and AppDomain.

Using CSLA 4: Data Access Page 32


Rev 1.0
The result is that you should be able to use the static factory, Save, and BeginSave methods on
business objects in your code regardless of whether these methods are being called on the client or
server.

Forcing Code to Run Locally


The client-side data portal normally uses convention and configuration (discussed in Chapter 5) to
determine whether to run the server-side data portal on the client workstation or on an application
server. It is possible for you to override the use of configuration to force the data portal to run code
locally for a specific business type and data portal operation.
The most common scenario is where a business object is being created, but the Create operation
doesn’t need access to any server resources such as the database. It is quite common for a Create
operation to initialize some business objects with hard-coded or calculated default values. This type
of code can usually run on the client or on the server. Since the code can run anywhere, there’s no
reason to incur the overhead of communicating with an application server, and it would be better
to have the entire Create operation run locally.
I’ve discussed code running on the client and on the application server. Some code can only run
on the server, such as code that interacts with the database or other server-side resources. Other
code can run on either the client or the server.
Code that runs locally is code that runs in the same process and AppDomain as the calling code,
without going across a network. This is true even if the calling code is on the client, and the data
portal is configured to run in a 3- or 4-tier deployment.
The way you force code to run locally is different in .NET and Silverlight. Code in .NET uses a
RunLocal attribute, and code in Silverlight and WP7 uses a ProxyMode parameter on the data portal
method call.

RunLocal Attribute
In .NET, the decision to run data access invocation code locally is made when implementing the
data access invocation method: the DataPortal_XYZ method or the ObjectFactory method.
For example, the following DataPortal_Create method will run locally:
[RunLocal]
protected override void DataPortal_Create()
{
using (BypassPropertyChecks)
{
Id = -1;
}
base.DataPortal_Create();
}

This method initializes the business object’s Id property with a hard-coded value.There’s no
reason for this method to run on an application server. The RunLocal attribute tells the data portal
that this method should run locally.

ProxyMode Parameter
In Silverlight and WP7, the decision to run data access invocation code locally is made in the static
factory method of the business class. Most Silverlight applications involve a 3- or 4-tier deployment,
Using CSLA 4: Data Access Page 33
Rev 1.0
where the data access invocation methods exist only on the server, not on the client. If CSLA .NET
required the use of a RunLocal attribute on Silverlight, you would be required to deploy the data
access code to the client, and that is undesirable.
The client-side data portal methods for Silverlight and WP7 accept an optional ProxyMode
parameter that can be used to force the data portal to run code locally. For example, the following
factory method forces the object creation to run locally:
public static void NewPersonEdit(EventHandler<DataPortalResult<PersonEdit>> callback)
{
DataPortal.BeginCreate<PersonEdit>(callback, DataPortal.ProxyModes.LocalOnly);
}

Like the BeginCreate method, all the Silverlight data portal methods have an overload that
accepts a ProxyMode parameter. If this value is LocalOnly, then the data portal will run the “server-
side” code locally on the client workstation or device.

Static Events
The client-side data portal defines a set of events that are raised on each data portal invocation.
These events can be used to detect when a data portal method call starts, when the call is
underway, and when the call is complete.
These events are static, and so it is important to use them carefully to avoid memory leaks.
Remember that setting up an event handler creates a reference from the event source to the
handler. When an event source is a static event, that reference will never go away unless the
event handler is explicitly unhooked from the event.

DataPortalInitInvoke Event
The DataPortalInitInvoke event is raised by the client-side data portal at the very beginning of
each data portal method call.
You can handle this event to perform any initialization of the ClientContext or GlobalContext
dictionaries in Csla.ApplicationContext. The data portal passes these dictionaries to the
application server on each data portal call, and this event is raised before those dictionaries are
serialized by the data portal.

DataPortalInvoke Event
The DataPortalInvoke event is raised by the client-side data portal immediately before the server-
side data portal is invoked.
You can handle this event to be notified when each server-side call is being made. The event
arguments contain information about the data portal method call, including the data portal
operation being performed and either the business object type or the business object itself.
The primary purpose for this event is to implement logging and instrumentation for the
application. For example, you might write code in the event handler to record a Windows event for
the data portal call so the Windows Event Viewer can be used to monitor the number of times the
data portal calls the server.

Using CSLA 4: Data Access Page 34


Rev 1.0
DataPortalInvokeComplete Event
The DataPortalInvokeComplete event is raised by the client-side data portal immediately after
each server-side data portal call completes.
You can handle this event to be notified when each server-side call completes. The event
arguments include information about the data portal method call, including the data portal
operation being performed and either the business object type or the business object itself.
The primary purpose for this event is to implement logging and instrumentation for the
application. For example, you might write code in the event handler to record a Windows event for
the data portal call so the Windows Event Viewer can be used to monitor the number of times the
data portal calls the server.
At this point you should understand that the client-side data portal uses convention and
configuration to determine how to call the server-side data portal, and that the configuration can
be overridden for specific data portal method calls. Additionally, you should be aware of the static
events raised by the client-side data portal. I’ll now move on to discuss some basic concepts
surrounding the server-side data portal.

Server-Side Data Portal Concepts


The server-side data portal is responsible for orchestrating the data access invocation process that
runs on the server. As always, “server-side” is a logical concept and this code will run on the client
workstation or web server in a 1- or 2-tier deployment.
The server-side data portal supports several areas of functionality, including:

 Setup of application context


 Optional impersonation of the client user identity
 Authorization of each data portal request
 Optional enlistment of each data portal call into a TransactionScope or Enterprise Services
transaction
 Rewriting server-side exceptions before they are returned to the client
 Selection of an encapsulation or factory data portal model

I’ll discuss each of these concepts.

Application Context
CSLA .NET includes an ApplicationContext type in the Csla namespace. The ApplicationContext
type is used to provide global access to various application context values, including:

 The current user principal and identity


 CSLA .NET configuration values
 Context dictionary available on the current machine and thread (LocalContext)

Using CSLA 4: Data Access Page 35


Rev 1.0
 Context dictionary available on the client and copied to the server on each data portal call
(ClientContext)
 Context dictionary available on the client and server, and copied to and from the server on
each data portal call (GlobalContext)

The ApplicationContext type is available to application code in any logical layer, and it often
contains properties or values that are useful to the Interface Control, Business, and Data Access
layers.

User Principal and Identity


The .NET framework provides access to the current user’s principal and identity information
through the current thread:
System.Security.Principal.IPrincipal user = System.Threading.Thread.CurrentPrincipal;

Although this is generally reliable, you will find that WPF sets this value to null in many cases,
rendering the user’s identity unavailable.
Code running in ASP.NET can also access this value through the current HttpContext object:
System.Security.Principal.IPrincipal user = HttpContext.Current.User;

In fact, the only reliable way to access the user’s principal in ASP.NET is through the current
HttpContext object.

The Silverlight and WP7 runtimes define the IPrincipal interface, but don’t provide any global
location to store or access the value. There’s no real concept of a “current user” built into Silverlight
or WP7.
The purpose of the User property on the Csla.ApplicationContext type is to provide a
consistent way for you to write code that uses the current user’s principal and identity information.
Table 11 lists where the User property gets its value depending on the runtime environment.

Runtime Csla.ApplicationContext.User Source


.NET (excluding WPF and ASP.NET) System.Threading.Thread.CurrentPrincipal
WPF application The value is stored by ApplicationContext in a static field so
it is consistent across all application threads; value originates from
System.Threading.Thread.CurrentPrincipal
ASP.NET HttpContext.Current.User
Silverlight Value is maintained by ApplicationContext
WP7 Value is maintained by ApplicationContext

Table 11. ApplicationContext.User property source


It is important to understand that applications deployed in n-tier scenarios will use more than
one of these runtimes. For example, a Silverlight client will often interact with application server
code hosted in ASP.NET.

Using CSLA 4: Data Access Page 36


Rev 1.0
You should avoid using any .NET or ASP.NET specific techniques to access the user’s
principal, and should favor the use of Csla.ApplicationContext.User .

I will discuss user authentication in the Using CSLA 4: Data Portal Configuration ebook, but it is
important to understand that you have two basic choices for authentication: Windows Active
Directory and custom authentication.

Windows Impersonation
If you are using Windows Active Directory authentication you are relying on the Windows operation
system to authenticate the user and to manage the user’s principal and identity. This includes
impersonation when making data portal calls from the client to the server.
I’ll discuss how to configure the data portal for Windows impersonation in Chapter 5 and in the
Using CSLA 4: Data Portal Configuration ebook. When using Windows impersonation, the data
portal doesn’t copy the client-side user principal to the server. There is no need, because the
Windows operating system and network stack do that work.

Custom Impersonation
The default data portal behavior is to assume you are using custom authentication. This means your
application is not relying on the Windows operating system to authenticate the user. Instead, the
application has authenticated the user through the ASP.NET MembershipProvider model, with
ASP.NET forms authentication, or with custom code.
The result is that the user’s principal object is a serialiable implementation of the IPrincipal
interface from the System.Security.Principal namespace. I’ll discuss this and related concepts in
detail in the Using CSLA 4: Data Portal Configuration ebook.
When using custom authentication the server-side data portal will copy the client-side principal
object to the server with each data portal call. This is done to provide a consistent experience
where your authorization rules run against the same user identity on the client and server.

Manual Impersonation
Sometimes the principal object can be quite large. Custom principal and identity objects may
contain many roles (in a List<string>), or a lot of user profile information. If these objects contain
a lot of data, the process of serializing them to the server with each data portal call can become a
performance issue.
If you encounter this issue when using custom authentication you can implement manual
impersonation. In this approach you recreate the user’s principal and identity objects from the
database or other data store on each data portal request. There’s a performance cost to recreating
these objects on each request, but sometimes this cost is lower than the cost of transferring the
data over the network with each request.
I’ll discuss the specific implementation of this approach in the Using CSLA 4: Data Portal
Configuration ebook. At a high level it involves the following steps:

1. Configure the data portal for Windows authentication (thereby preventing it from serializing
the principal to the server on each call)
Using CSLA 4: Data Access Page 37
Rev 1.0
2. Put the username or other user id value into the ClientContext dictionary of
Csla.ApplicationContext so it becomes available to the server

3. Implement a custom IAuthorizeDataPortal provider and recreate the user’s principal and
identity objects in the Authorize method

4. Set Csla.ApplicationContext.User to the recreated principal object

5. Configure the server-side data portal to use this custom IAuthorizeDataPortal


implementation

In my experience, most applications don’t need to take this approach, but if your principal or
identity objects contain large amounts of data this technique can be valuable.

CSLA .NET Environment and Configuration


The ApplicationContext type has numerous properties that expose CSLA .NET environment and
configuration values. These values are not serialized from client to server by the data portal, but are
available in both locations based on the state of the environment and the configuration settings
you’ve created on client and server.
There are two values of particular interest when discussing the data portal: the
ExecutionLocation and LogicalExecutionLocation properties.

ExecutionLocation Property
The ExecutionLocation property indicates the physical location where the code is currently
executing: Silverlight, Client, or Server. These locations are listed in Table 12.

Value Description
Silverlight Indicates the code is running on a Silverlight or WP7 client workstation or device
Client Indicates the code is running on a Windows client workstation, or on the web
server in an ASP.NET Web Forms or MVC application
Server Indicates the code is running on an application server when the data portal is
configured for a 3- or 4-tier deployment

Table 12. ExecutionLocation property values


You can get this property value in your code and use it to determine where your code is running.
This can be valuable for some scenarios where you implement business rules that should act
differently when running on the client or application server.
For example, you might implement a business rule that should be asynchronous when running in
Silverlight, and should be synchronous in all other environments. To do this, you can set the rule’s
IsAsync property based on the ExecutionLocation value.

LogicalExecutionLocation Property
The LogicalExecutionLocation property indicates the logical execution location for the code.
Several times in this book I’ve mentioned that “server-side” code will run on the client workstation
Using CSLA 4: Data Access Page 38
Rev 1.0
or web server when the application is deployed in a 1- or 2-tier scenario. In that case, the
ExecutionLocation property will always return Silverlight or Client, but the
LogicalExecutionLocation will return Client or Server depending in the logical location of the
code.
For example, in a WPF application deployed in a 2-tier scenario all the application’s code will run
on the client workstation. The ExecutionLocation property will always return Client, even when
“server-side” code is running.
In that same example, the LogicalExecutionLocation property will return Client or Server
depending on whether the current code is logically “client-side” or “server-side”.

LocalContext
The ApplicationContext type has a LocalContext property. This property is a dictionary of values
available to the application.
The LocalContext dictionary is maintained on a per-thread basis for all code outside ASP.NET,
and is maintained in the current HttpContext inside ASP.NET. This means that the values in
LocalContext are global to the application, but isolated to the current thread or HttpContext.

CSLA .NET uses the LocalContext dictionary to store certain short-term values that should be
available within a specific thread or HttpContext, and you can use LocalContext to store your own
values as well.
For code running on a smart client (WPF or Silverlight for example), LocalContext is a place to
store values that should be global to all code on the client. The dictionary remains in memory
throughout the life of the application.
For code running on a web or application server, LocalContext only exists for the duration of
the current server request. As each request ends, the dictionary is removed from memory.

ClientContext
The ApplicationContext type has a ClientContext property. This property is a dictionary of values
that is maintained by client-side code, but is also made available to server-side code. The data
portal copies the ClientContext dictionary from the client to the server with every data portal
request.
Like the LocalContext value, ClientContext is maintained on the current thread or
HttpContext. Also, it is maintained in memory for the entire life of the application on a smart client
(WPF or WP7 for example), and is lost at the end of each server request when running in a server
environment such as ASP.NET.

Be very careful what you put into ClientContext, because all values and objects in
ClientContext are serialized from the client to the server on every data portal
request. Putting large amounts of data in ClientContext can cause performance
problems.

CSLA .NET does not store any values in ClientContext, and the data portal has optimizations to
minimize overhead when making server requests if ClientContext is entirely unused.
Using CSLA 4: Data Access Page 39
Rev 1.0
The ClientContext dictionary is a good location to store small application configuration and
context values that should be available to code on the client and server. For example, some
applications are used by many divisions or departments within an organization. As the application
starts up the current corporate department may be loaded into ClientContext so it is available to
all application code on client and server. This value may be used by business and authorization rules
or other aspects of the application.

GlobalContext
The ApplicationContext type has a GlobalContext property. This property is a dictionary of values
that is maintained by code on both the client and server. The data portal serializes GlobalContext
from the client to the server, and then back to the client, on every data portal request.
As with the other context dictionaries, this one is maintained on the current thread or
HttpContext, is available for the life of a smart client application, and is lost at the end of each
server request when running in a server environment such as ASP.NET.

Be extremely careful when putting values into GlobalContext. These values are
serialized from client to server and back to the client on every data portal request.
Putting values in GlobalContext can cause performance problems.

CSLA .NET does not store any values in GlobalContext, and the data portal has optimizations to
minimize overhead when making server requests if GlobalContext is entirely unused.
The GlobalContext dictionary is a good location to put limited debugging or trace information
during development and testing. I recommend avoiding its use in most production settings to avoid
possible performance problems.

Authorizing Data Portal Requests


Any time the server-side data portal is invoked by the client-side data portal there is an opportunity
to authorize the request from the client. Additionally, when deploying a Silverlight or WP7
application in a 4-tier model, there’s an opportunity to validate each client request on the web
server before the data portal call is relayed to the application server.

IAuthorizeDataPortal Interface
Every time the server-side data portal is invoked it invokes an authorizer that implements the
IAuthorizeDataPortal interface from the Csla.Server namespace. The default implementation
allows all data portal calls to succeed.
You can create your own implementation of the IAuthorizeDataPortal interface to create more
restrictive authorization for the data portal. The interface requires that the class implement an
Authorize method:
protected class NullAuthorizer : IAuthorizeDataPortal
{
public void Authorize(AuthorizeRequest clientRequest)
{
// implement authorization here and
// throw exception to deny call
}
}
Using CSLA 4: Data Access Page 40
Rev 1.0
This method is invoked immediately after the client request has been deserialized. The order of
events for each data portal request is as follows:

1. Client request arrives at server-side host

2. The User property of ApplicationContext is set (if using Windows impersonation)

3. Client request data is deserialized into objects (except for Silverlight and WP7 clients)

4. Client request is routed to server-side data portal

5. Client request data is deserialized into objects (Silverlight and WP7 clients only)

6. The ClientContext and GlobalContext values are loaded into the server-side
ApplicationContext type

7. The User property of ApplicationContext is set (if using custom impersonation)

8. The Authorize method of the IAuthorizeDataPortal handler is invoked

9. Subsequent data portal processing occurs

As you can see, when the Authorize method is invoked the data portal has deserialized the
client request into objects, the ApplicationContext dictionaries are loaded, and the current user
principal has been set to an appropriate value.
This means the code you write in the Authorize method can make use of all context and user
identity information, as well as the information provided through the AuthorizeRequest
parameter. Table 13 lists the values provided through that parameter.

Member Description
ObjectType Gets the type of business object affected by the client request
RequestObject Gets a reference to the criteria or business object passed from the client to the
server
Operation Gets a DataPortalOperations value indicating the data portal operation
requested by the client; one of: Create, Fetch, Update, Delete, Execute

Table 13. Members of the AuthorizeRequest class


Not only can you read information from ApplicationContext, but you can alter values as well.
For example, you might set global configuration values into LocalContext, or you might get a
username value from ClientContent and use it to recreate the user’s principal object to set the
User property.

However, the primary reason for implementing this interface is to determine whether to allow
each data portal request to be processed by the server. If you do not want a request to be
processed your Authorize method implementation should throw an exception. This exception will
be returned to the caller to indicate the reason the request was not processed by the server.

Using CSLA 4: Data Access Page 41


Rev 1.0
If your Authorize method implementation doesn’t throw an exception the data portal request
will be processed by the server.

MobileFactory Attribute
When building a Silverlight or WP7 application you may choose to use a 4-tier deployment as shown
in Figure 8.

Figure 8. A 4-tier physical deployment


In this diagram, the Business layer is deployed to the client workstation or device, the web
server, and the application server.
The reason for having two servers (web and application) is security. The web server is a public-
facing server, without authorization to interact with the database server. In fact, there’s usually an
internal firewall between the web server and the rest of the organization’s network.
Requests from the client go to the web server, and the web server relays them through the
internal firewall to the application server. The application server is running inside the organization’s
secure network, and so it has access to the database server. This means that the Data Access layer
runs on the application server.
The data portal has components running on the web and application servers. The default
behavior of the data portal on the web server is to relay all client requests to the application server,
but you can choose to implement mobile factory objects that run on the web server to screen or
otherwise process client requests.
The reason for this feature is to allow you to implement an extra layer of security for situations
where you want to use the data portal to build a Silverlight or WP7 client, but where you don’t
completely trust the client-side code. The mobile factory object has an opportunity to interact with
the business objects on the web server, before they are passed through the internal firewall to the
application server. You can use this opportunity to validate the client request, or do something as

Using CSLA 4: Data Access Page 42


Rev 1.0
simple as forcing all business rules defined in the objects to be re-run before allowing the request to
proceed.
Implementing a mobile factory is similar to implementing a data factory. A business class
indicates that it should be processed by a mobile factory through the MobileFactory attribute.
Here’s an example of a business class with an attached mobile factory type:
[Serializable]
[Csla.Server.MobileFactory("MyApp.Security.PersonFactory,MyApp.Security")]
public class PersonEdit : BusinessBase<PersonEdit>
{
}

The MobileFactory attribute accepts a string parameter that is used to identify the type of the
mobile factory object that should run on the web server. By default, this parameter is interpreted as
the assembly qualified name of the mobile factory class. Nevertheless, you can implement a mobile
factory loader that interprets the value any way you choose.
A mobile factory class must implement public methods that are invoked by the data portal:
Create, Fetch, Update, and Delete. Only methods appropriate to the business object stereotype
are required. For example, a read-only business object would only require a Fetch method in the
factory class. Here’s an example of a mobile factory class that implements a Fetch method:
public class PersonFactory
{
public PersonEdit Fetch(int id)
{
// verify that this operation should be allowed here
return DataPortal.Fetch<PersonEdit>(id);
}
}

A mobile factory class is implemented exactly like a data factory class, but its purpose is
different. Instead of implementing or invoking data access code, a mobile factory verifies that the
requested operation should be allowed, or invokes the business rules on objects being updated.
At this point, you should understand how data portal requests come into the server and are
authorized. You’ve also seen how the data portal copies certain bits of client-side data to the server
to provide location transparency for the application’s code.
I’ll now move on to discuss the next step in the server-side data portal processing: optionally
enlisting the operation in a transaction.

Database Transactions
The server-side data portal invokes your DataPortal_XYZ or object factory methods to perform
Create, Fetch, Update, or Delete operations. By default, these methods are invoked without any
pre-existing transactional context, but you can use the Transactional attribute to tell the data
portal to enlist in a transaction before invoking these methods.

Transactional Attribute
The Transactional attribute is in the Csla namespace, and it is applied to the DataPortal_XYZ
methods of a root object, or to the methods in an object factory. If this method is applied to any
other methods it will have no affect on those methods or the data portal.

Using CSLA 4: Data Access Page 43


Rev 1.0
The purpose of the Transactional attribute is to tell the data portal to enlist in a transaction
before invoking the method to which the attribute has been applied. When using the attribute you
can specify that transactions are one of:

 Manual
 TransactionScope
 EnterpriseServices

These values are defined in an enum named TransactionalTypes.


The default behavior is to not enlist in a transaction. This is the same as using the Transactional
attribute with a parameter of Manual.
I’ll discuss each transactional model in turn.

Manual Transactions
The data portal defaults to using Manual transactions. In this case the code you write in the
DataPortal_XYZ or object factory method is responsible for enlisting in its own transaction using
whatever technology you choose.
The most common scenario is to use ADO.NET transaction objects such as a SqlTransaction
from the System.Data.SqlClient namespace. For example:
protected override void DataPortal_Insert()
{
using (var cn = new SqlConnection())
{
cn.Open();
using (var tr = cn.BeginTransaction())
{
// invoke access layer here
tr.Commit();
}
}
}

This code explicitly creates a SqlTransaction object using the BeginTransaction method of the
SqlConnection object. And the transaction is explicitly committed once the data access code is
complete.
Any exception encountered during the data access process will prevent the Commit method from
being called and the transaction will automatically roll back. Additionally, the data portal expects
that any failure during data access will result in an exception, so there’s no effort to catch any
exceptions in this code.
In Chapter 3 I will discuss some helper types in the Csla.Data namespace that make it easier to
implement manual transactions for object graphs that contain parent-child relationships.
You can use any transactional technology you choose when implementing manual transactions.
This includes ADO.NET transactions as shown in this example, TransactionScope transactions, or
database-level transactions.

Using CSLA 4: Data Access Page 44


Rev 1.0
TransactionScope Transactions
The most common technology for implementing transactions when using a SQL Server database is
to use a TransactionScope object from the System.Transactions namespace. You can create your
own TransactionScope object when using manual transactions, but the data portal offers a simpler
way to enlist your data access code in a TransactionScope transaction through the Transactional
attribute.
For example:
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_Insert()
{
// invoke access layer here
}

The TransactionScope parameter passed to the Transactional attribute tells the data portal to
enlist in a TransactionScope before invoking this DataPortal_Insert method. The same idea
applies to methods in an object factory class. For example:
[Transactional(TransactionalTypes.TransactionScope)]
public PersonEdit Update(PersonEdit obj)
{
// implement data access here
return obj;
}

In both models the idea is the same: by the time your code is invoked the data portal has already
created a TransactionScope object so your code is running in a transactional context.
Notice that this code is much simpler. Any interaction with the database is automatically
protected by a transaction. If no exception is thrown during the data access process the transaction
will automatically commit when your method is complete.
Any exception will cause the data portal to roll back the transaction and perform normal failure
processing, including returning the exception to the client-side code.
The TransactionScope created by the data portal uses default values for all settings, including
the isolation level and timeout value. This means the transaction is Required, has an isolation level
of Serializable, and has a one minute timeout. If you need different values from the defaults, you
will need to use manual transactions and create your own TransactionScope object.
It is also important to understand that the TransactionScope object will automatically use the
Microsoft Distributed Transaction Coordinator (DTC) if more than one database connection is
opened during the data access processing. It doesn’t matter if these connections are open at the
same time, or one after another. If more than one connection is opened the DTC is enlisted.
The reason this is important is that the DTC incurs substantial performance overhead.
Additionally, the DTC is not enabled on most client workstations by default. If the data access code
is running on a client workstation, the code will throw an exception when it fails to locate the DTC.
Most parent-child object models will open more than one connection during data access and so
this is a common issue. In Chapter 3 I will discuss several helper types in the Csla.Data namespace
that are designed to simplify the process of reusing a single database connection for all data access
actions across an entire object graph.

Using CSLA 4: Data Access Page 45


Rev 1.0
EnterpriseLibrary Transactions
Although the TransactionScope and Manual transactional models solve most transaction
requirements, there are some application scenarios where a two-phase distributed transaction is
required and a TransactionScope won’t work.
The most common scenario is when the database used by the application isn’t supported by the
TransactionScope object. This includes Oracle, DB2, older versions of SQL Server, and many other
non-Microsoft databases.
Fortunately, the older Enterprise Services technology does provide support for many of these
databases, including several versions of Oracle, DB2, and older versions of SQL Server. The
Transactional attribute can be used to enlist your code in an Enterprise Services transaction. For
example:
[Transactional(TransactionalTypes.EnterpriseServices)]
protected override void DataPortal_Insert()
{
// invoke access layer here
}

Or with an object factory:


[Transactional(TransactionalTypes.EnterpriseServices)]
public PersonEdit Update(PersonEdit obj)
{
// implement data access here
return obj;
}

As with the TransactionScope option, the data portal enlists the code in a transaction before
invoking your method. If the data access code completes without throwing an exception, the
transaction is automatically commited. If an exception is thrown, the transaction is rolled back.
Because Enterprise Services transactions always use the DTC, they always incur the performance
penalty associated with a distributed transaction. On the other hand, these transactions protect
access to multiple databases, and support more types of database than the TransactionScope
object provides.
Transactions are an important part of any data access model, and the data portal provides
simplicity through TransactionScope and EnterpriseServices, or flexibility through Manual
transactions.

Data Portal Exceptions


When an exception is thrown by code in the DataPortal_XYZ, or object factory methods, it is
returned to the client, along with other details about the exception. CSLA .NET provides some
functionality that makes this process richer and more flexible than normal, including:

 Preserving detailed information about the original exception


 Preserving information about the state of the business object at the time of the exception
 Allowing the exception to be altered before it is returned from the server

I’ll discuss these concepts in more detail.


Using CSLA 4: Data Access Page 46
Rev 1.0
DataPortalException Types
Normally, a lot of detail is lost when exception data is serialized so it can flow across the network.
To avoid this loss of detail, CSLA .NET wraps all server-side exceptions in a special exception object
that preserves the information. On the client, another special exception type is used to provide
richer information about the exception to the calling code.

Server-side DataPortalException Class


All exceptions thrown on the server are wrapped in a DataPortalException object (from the
Csla.Server namespace) before being returned to the client. This DataPortalException type
includes functionality that preserves the full stack trace and the business object as it was at the
time of the exception, and returns that information to the client.
You won’t normally see this server-side type, because it exists purely for the purpose of
serializing detailed information from client to server.
On the client, the application will see a DataPortalException object designed to provide
exception information to the client with as much detail about what occurred on the server as
possible. This client-side DataPortalException type is different on .NET and Silverlight.

Client-side DataPortalException Class (.NET)


Once a server-side exception has been returned to a .NET client, the data portal creates a
DataPortalException object from the Csla namespace and populates this exception with all the
server-side information. The data portal then throws this client-side DataPortalException so it can
be caught by the code that called the data portal originally.
This means that all exceptions that originated on the server appear on the client as
DataPortalException objects. Any code calling the data portal should expect to catch and handle
DataPortalException objects.

The data portal may throw other exceptions as well. Specifically, if the data portal was unable to
reach the server due to network errors or similar issues, you should expect to catch exceptions
specific to the network technology you are using. The most common source of these exceptions will
be WCF (System.ServiceModel) or other components from the System.Net namespace.
The reason the data portal throws exceptions of type DataPortalException, is that the
exception contains useful information about the original exception that would otherwise be lost or
unavailable. Table 14 lists the properties available from the DataPortalException type (beyond
those normally available from the base Exception type).

Property Description
BusinessException Gets the original server-side exception that was thrown, bypassing all
intermediate exceptions that may have been inserted by the data portal
BusinessObject Gets a reference to the business object as it was on the server at the time of the
exception
StackTrace Gets the full stack trace for the exception, including the client-side and server-side
stack traces merged into one unified stack trace

Table 14. Properties available from DataPortalException


Using CSLA 4: Data Access Page 47
Rev 1.0
In most cases, the code that catches and handles a DataPortalException will use the
BusinessException property to determine the type and detail about the original exception.

The consolidated stack trace property is valuable for debugging, because it includes the entire
history of the exception from the point that it was thrown on the server, through any intermediate
steps on the server and client, right up to where the exception was caught on the client.
The BusinessObject property can also be useful for debugging, because it provides a reference
to the business object as it was at the time of the exception. In many cases, this business object will
be in an indeterminate state, because its properties and metastate will have been partially altered
during the data access process, but the changes were never completed due to the exception.

Client-side DataPortalException Class (Silverlight/WP7)


Once a server-side exception has been returned to a Silverlight or WP7 client, the data portal
creates a DataPortalException object from the Csla namespace and populates this exception with
all the server-side information. The data portal then throws this client-side DataPortalException
so it can be caught by the code that called the data portal originally.
Exception objects aren’t serializable in Silverlight or WP7, so the original server-side exceptions
aren’t available on the client. The Silverlight data portal does copy as much of the server-side
exception information as possible into a WcfErrorInfo object that is available to client-side code
through the ErrorInfo property of the DataPortalException object.
The WcfErrorInfo type implements properties that contain most of the information from the
original exception. Table 15 lists these properties.

Property Description
ExceptionTypeName Type name of the original exception object
Message Message text from the exception
Source Source property value from the exception
StackTrace Stack trace text derived from the exception
TargetSiteName TargetSiteName value from the exception
InnerError WcfErrorInfo object containing the exception information from the
InnerException property of the original exception

Table 15. Properties of WcfErrorInfo type


Client-side code can use the information available from the ErrorInfo property to implement
appropriate exception handling based on the server-side exception.

Exception Inspector
When an exception is thrown by code in the DataPortal_XYZ or object factory method, it is
returned to the client. Before the data portal serializes the exception on the server, you can
“rewrite” the exception. This can be useful in cases where you want to globally change one
exception type into another before the exception is returned to the client.

Using CSLA 4: Data Access Page 48


Rev 1.0
The most common scenario where you need to rewrite exceptions is when you have a pluggable
Data Access layer, with options to talk to different types of database; SQL Server and Oracle for
example. Each type of database will throw different exceptions when records aren’t found, or other
database errors occur. SQL Server will throw SQL exceptions and Oracle will throw Oracle
exceptions. This means that for any given logical type of error, different exceptions will be thrown.
Unless this issue is overcome, the client code that catches and handles the exceptions must
handle every type of exception from every possible type of database. A better alternative is often to
“rewrite” those exceptions into a common type. For example, the SQL and Oracle “record not
found” exception types could both be rewritten into a custom MyAppRecordNotFound exception
type.
To rewrite server-side exceptions, you need to create a class that implements the
CslaDataPortalExceptionInspector interface from the Csla.Server namespace, and then
configure the data portal to use this inspector type.
For example, here’s an inspector that changes every exception into the base Exception type:
public class Inspector : IDataPortalExceptionInspector
{
public void InspectException(
Type objectType, object businessObject, object criteria, string methodName, Exception ex)
{
throw new Exception("From inspector", ex);
}
}

Notice that the original exception is included as the InnerException value of the new exception.
This avoids losing any detail about the exception, while still rewriting the top-level exception that is
returned to the client.
In the web.config file on the server (or app.config for a 1- or 2-tier deployment) you need to
tell the data portal to use this inspector by supplying an assembly-qualified type name:
<appSettings>
<add key="CslaDataPortalExceptionInspector"
value="Library.Inspector,Library"/>
</appSettings>

The assembly containing this type must be deployed to the machine that is running the “server-
side” data portal components.

Encapsulation Models
When using the data portal with one of the encapsulation models the data portal calls methods on
the root business object, and those methods are responsible for invoking or implementing the data
access code.

DataPortal_Create Method
The DataPortal_Create method is invoked by the data portal when a new root obect is being
created. The data portal creates a new instance of the root business type, the object’s MarkNew
method is invoked, and then the DataPortal_Create method is invoked to initialize the object with
appropriate data.

Using CSLA 4: Data Access Page 49


Rev 1.0
The BusinessBase, BusinessListBase, and BusinessBindingListBase types implement a
default DataPortal_Create method. For objects that require no custom initialization, you don’t
need to implement your own DataPortal_Create method.
The default implementation in the BusinessBase class calls BusinessRules.CheckRules to run
all business rules defined by the business type. This ensures that properties with default values that
violate business rules are marked as being invalid as the object is created.
The default method accepts no parameters in .NET, and accepts an async callback handler in
Silverlight and WP7. The default method is virtual, so you can override the default behavior.
In some cases you may pass a criteria value to the Create or BeginCreate method of the data
portal. When you do that, your DataPortal_Create method must accept a parameter of the same
type. For example, consider this factory method:
public static PersonEdit NewPersonEdit(int regionId)
{
return DataPortal.Create<PersonEdit>(regionId);
}

That Create method is provided with an int parameter, and so the data portal will invoke an
overload of the DataPortal_Create method that accepts an int parameter:
private void DataPortal_Create(int regionId)
{
using (BypassPropertyChecks)
{
// initialize object here
}
base.DataPortal_Create();
}

The data portal follows normal .NET rules for invoking overloaded methods. If a
DataPortal_Create method can’t be found with a parameter type that matches the parameter
from the Create or BeginCreate method an exception is thrown.
In this example I show how to call the base implementation. This is a good practice if you want
the default behavior of running the business rules for the object after the object’s data has been
initialized.
Also notice that the object initialization occurs within a using block for the object’s
BypassPropertyChecks property. This ensures that business and authorization rules aren’t run as
properties are set with new values.
Here’s an example of a Silverlight implementation of the DataPortal_Create method:
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void DataPortal_Create(
int id, Csla.DataPortalClient.LocalProxy<PersonEdit>.CompletedHandler handler)
{
try
{
// invoke external DAL here (encapsulated invoke)
// or implement DAL code here (encapsulated implementation)
handler(this, null);
}
catch (Exception ex)
{
handler(null, ex);

Using CSLA 4: Data Access Page 50


Rev 1.0
}
}

The assumption is that a DataPortal_XYZ method running on the Silverlight or WP7 client will
invoke a remote SOAP or REST service. Because all server interactions must be async on Silverlight,
the code inside this DataPortal_Create method will be async. Given those assumptions, the
DataPortal_Create method accepts a callback handler parameter that must be invoked when the
method is complete. That is true whether there’s an exception or not, so the implementation or
invocation code is wrapped in a try..catch block.
The EditorBrowsable attribute blocks this method from appearing in Intellisense. The method
must be public due to limitations on reflection and dynamic method invocation in Silverlight, but
the method should never be called directly. Hiding it from Intellisense is a good practice because it
reduces the chance that a developer will accidentally think they should be able to call this method.

DataPortal_Fetch Method
The DataPortal_Fetch method is invoked by the data portal when the Fetch or BeginFetch data
portal method is invoked. The data portal creates an instance of the root business type, calls the
object’s MarkOld method, and then calls the DataPortal_Fetch method. This method is responsible
for invoking or implementing the data access code necessary to load the object with existing data
from the data store.
You must implement a DataPortal_Fetch method that accepts the same criteria parameter type
as the criteria value provided to the Fetch or BeginFetch method. On Silverlight and WP7 the
DataPortal_Fetch must also accept an async callback parameter.

For example, consider the following factory method:


public static PersonEdit GetPersonEdit(int id)
{
return DataPortal.Fetch<PersonEdit>(id);
}

It will cause the data portal to invoke the following DataPortal_Fetch method:
private void DataPortal_Fetch(int id)
{
// get data from DAL
using (BypassPropertyChecks)
{
// load object properties
}
}

The data portal follows normal .NET rules for invoking overloaded methods. If a
DataPortal_Fetch method can’t be found with a parameter type that matches the parameter from
the Fetch or BeginFetch method an exception is thrown.
Also notice that the object initialization occurs within a using block for the object’s
BypassPropertyChecks property. This ensures that business and authorization rules aren’t run, as
properties are set with new values. If you set properties without this step, the object will be marked
as having changes even though it was just fetched, and that will result in unexpected behaviors
within the object and most user interfaces.
Here’s an example of a Silverlight implementation of the DataPortal_Fetch method:
Using CSLA 4: Data Access Page 51
Rev 1.0
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void DataPortal_Fetch(
int id, Csla.DataPortalClient.LocalProxy<PersonEdit>.CompletedHandler handler)
{
try
{
// invoke external DAL here (encapsulated invoke)
// or implement DAL code here (encapsulated implementation)
handler(this, null);
}
catch (Exception ex)
{
handler(null, ex);
}
}

As with the DataPortal_Create method, this DataPortal_Fetch method accepts a callback


handler parameter that must be invoked when the method is complete. That is true whether
there’s an exception or not. Also notice the same use of the EditorBrowsable attribute to help hide
the method, even though the method must be public in scope.

DataPortal_Insert Method
The DataPortal_Insert method is invoked by the data portal when an editable root object is saved
using its Save or BeginSave method. This only occurs if the object’s IsNew property is true and its
IsDeleted property is false. After the DataPortal_Insert method completes, the data portal will
call the object’s MarkOld method.
On .NET the DataPortal_Insert method accepts no parameters. On Silverlight and WP7 the
method must define and invoke an async callback handler parameter. Here’s an example of a .NET
implementation:
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_Insert()
{
using (BypassPropertyChecks)
{
// invoke external DAL here (encapsulated invoke)
// or implement DAL code here (encapsulated implementation)
}
}

And here’s an example of a Silverlight implementation:


[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void DataPortal_Insert(
Csla.DataPortalClient.LocalProxy<PersonEdit>.CompletedHandler handler)
{
try
{
// invoke external DAL here (encapsulated invoke)
// or implement DAL code here (encapsulated implementation)
handler(this, null);
}
catch (Exception ex)
{
handler(null, ex);
}
}

As with the DataPortal_Fetch method, this DataPortal_Insert method accepts a callback


handler parameter that must be invoked when the method is complete. That is true whether
Using CSLA 4: Data Access Page 52
Rev 1.0
there’s an exception or not. Also notice the same use of the EditorBrowsable attribute to help hide
the method, even though the method must be public in scope.

DataPortal_Update Method
The DataPortal_Update method is invoked by the data portal when an editable root object is saved
using its Save or BeginSave method. This only occurs if the object’s IsNew property is false and its
IsDeleted property is false. After the DataPortal_Update method completes, the data portal will
call the object’s MarkOld method.
On .NET the DataPortal_Update method accepts no parameters. On Silverlight and WP7 the
method must define and invoke an async callback handler parameter. Here’s an example of a .NET
implementation:
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_Update()
{
using (BypassPropertyChecks)
{
// invoke external DAL here (encapsulated invoke)
// or implement DAL code here (encapsulated implementation)
}
}

And here’s an example of a Silverlight implementation:


[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void DataPortal_Update(
Csla.DataPortalClient.LocalProxy<PersonEdit>.CompletedHandler handler)
{
try
{
// invoke external DAL here (encapsulated invoke)
// or implement DAL code here (encapsulated implementation)
handler(this, null);
}
catch (Exception ex)
{
handler(null, ex);
}
}

As with the DataPortal_Create method, this DataPortal_Update method accepts a callback


handler parameter that must be invoked when the method is complete. That is true whether
there’s an exception or not. Notice the same use of the EditorBrowsable attribute to help hide the
method, even though the method must be public in scope.

DataPortal_DeleteSelf Method
The DataPortal_DeleteSelf method is invoked by the data portal when an editable root object is
saved using its Save or BeginSave method. This only occurs if the object’s IsNew property is false
and its IsDeleted property is true.
After the DataPortal_DeleteSelf method completes, the data portal will call the object’s
MarkNew method. This may seem strange, but once the object’s data has been deleted there is a
reasonable expectation that the object does not correspond to any existing data in the database.
That is the definition of a new object, so it makes sense that IsNew and IsDirty should now be
true.
Using CSLA 4: Data Access Page 53
Rev 1.0
On .NET the DataPortal_DeleteSelf method accepts no parameters. On Silverlight and WP7
the method must define and invoke an async callback handler parameter. Here’s an example of a
.NET implementation:
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_DeleteSelf()
{
using (BypassPropertyChecks)
{
// invoke external DAL here (encapsulated invoke)
// or implement DAL code here (encapsulated implementation)
}
}

And here’s an example of a Silverlight implementation:


[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void DataPortal_DeleteSelf(
Csla.DataPortalClient.LocalProxy<PersonEdit>.CompletedHandler handler)
{
try
{
// invoke external DAL here (encapsulated invoke)
// or implement DAL code here (encapsulated implementation)
handler(this, null);
}
catch (Exception ex)
{
handler(null, ex);
}
}

As with the DataPortal_Create method, this DataPortal_DeleteSelf method accepts a


callback handler parameter that must be invoked when the method is complete. That is true
whether there’s an exception or not. Also notice the same use of the EditorBrowsable attribute to
help hide the method, even though the method must be public in scope.

DataPortal_Delete Method
The DataPortal_Delete method is invoked by the data portal when the Delete or BeginDelete
data portal method is invoked. The data portal creates an instance of the root business type and
then calls the DataPortal_Delete method. This method is responsible for invoking or implementing
the data access code necessary to remove the object’s data from the data store.
You must implement a DataPortal_Delete method that accepts the same criteria parameter
type as the criteria value provided to the Delete or BeginDelete method. On Silverlight and WP7
the DataPortal_Delete must also accept an async callback parameter.
For example, consider the following factory method:
public static void DeletePersonEdit(int id)
{
return DataPortal.Delete<PersonEdit>(id);
}

It will cause the data portal to invoke the following DataPortal_Delete method:
private void DataPortal_Delete(int id)
{
// invoke external DAL here (encapsulated invoke)
// or implement DAL code here (encapsulated implementation)
}
Using CSLA 4: Data Access Page 54
Rev 1.0
The data portal follows normal .NET rules for invoking overloaded methods. If a
DataPortal_Delete method can’t be found with a parameter type that matches the parameter
from the Delete or BeginDelete method an exception is thrown.
Here’s an example of a Silverlight implementation of the DataPortal_Delete method:
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void DataPortal_Delete(
int id, Csla.DataPortalClient.LocalProxy<PersonEdit>.CompletedHandler handler)
{
try
{
// invoke external DAL here (encapsulated invoke)
// or implement DAL code here (encapsulated implementation)
handler(this, null);
}
catch (Exception ex)
{
handler(null, ex);
}
}

As with the DataPortal_Create method, this DataPortal_Delete method accepts a callback


handler parameter that must be invoked when the method is complete. That is true whether
there’s an exception or not. Also notice the same use of the EditorBrowsable attribute to help hide
the method, even though the method must be public in scope.

DataPortal_OnDataPortalInvoke Method
The DataPortal_OnDataPortalInvoke method is called by the server-side data portal before the
appropriate DataPortal_XYZ method is invoked. You can think of this as a pre-processing method
where you can run code before every data portal invocation.
The standard base classes for object stereotypes all contain a virtual implementation of this
method that you can override if you want to implement pre-processing behaviors. The most
common reason for overriding this method is to implement logging or tracing code for
instrumentation or diagnostics in your application.
This method is synchronous on both .NET and Silverlight, and looks like this:
protected override void DataPortal_OnDataPortalInvoke(DataPortalEventArgs e)
{
// implement your behavior here
base.DataPortal_OnDataPortalInvoke(e);
}

The DataPortalEventArgs parameter provides useful information about the current data portal
request. The members of this type are listed in Table 16.

Member Description
Operation A DataPortalOperations value indicating the type of data portal operation
being performed (Create, Fetch, Update, Delete, or Execute)
ObjectType The type of the business object being processed by the data portal
Exception Any exception that occurred during the DataPortal_XYZ method

Table 16. Members of the DataPortalEventArgs type


Using CSLA 4: Data Access Page 55
Rev 1.0
During the DataPortal_OnDataPortalInvoke method only the Operation property has any
meaning.
This DataPortalEventArgs type is used for post-process exception handling, and that’s where
the Exception property has value. It is also provided to comparable methods in object factories,
and that’s where the ObjectType property has value.

DataPortal_OnDataPortalInvokeComplete Method
The DataPortal_OnDataPortalInvokeComplete method is invoked by the server-side data portal
after a DataPortal_XYZ method has successfully completed. You can think of this method as a post-
processing method where you can write code that should run after every successful data portal
operation.
This method is synchronous on both .NET and Silverlight and looks like this:
protected override void DataPortal_OnDataPortalInvokeComplete(DataPortalEventArgs e)
{
// implement your behavior here
base.DataPortal_OnDataPortalInvokeComplete(e);
}

The primary purpose for overriding this method is to implement instrumentation or diagnostic
code for your application.
As with the previous method, this one accepts a DataPortalEventArgs parameter that contains
an Operation property indicating the reason for the current data portal request.

DataPortal_OnDataPortalException Method
The DataPortal_OnDataPortalException method is invoked by the server-side data portal after a
DataPortal_XYZ method has thrown an exception. You can think of this method as a post-
processing exception handler where you can write code that should run after every unsuccessful
data portal operation.
This method is synchronous on both .NET and Silverlight and looks like this:
protected override void Child_OnDataPortalException(DataPortalEventArgs e, Exception ex)
{
// implement your behavior here
base.Child_OnDataPortalException(e, ex);
}

The primary purpose for overriding this method is to implement instrumentation or diagnostic
code for your application.
As with the previous two methods, this one accepts a DataPortalEventArgs parameter that
contains Operation and Exception properties you can use in your code.
Remember that you can also rewrite the exception before it is returned to the client by providing
your own IDataPortalExceptionInspector implementation. I discussed this earlier in the chapter.
You should understand that the DataPortal_OnDataPortalException method is invoked before
any custom IDataPortalExceptionInspector implementation.

Using CSLA 4: Data Access Page 56


Rev 1.0
At this point you should understand how the data portal interacts with DataPortal_XYZ methods
in the encapsulated invocation and encapsulated implementation models. I will now discuss the
alternative models where the data portal invokes methods in object factories.

Factory Models
When using the data portal with one of the factory models, the data portal calls methods on a
factory object that is associated with a business type. The methods implemented in the factory class
are responsible for implementing or invoking the data access code.

ObjectFactory Attribute
The data portal must be provided with information about the factory type associated with each
business type. This is done through the ObjectFactory attribute. For example:
[Csla.Server.ObjectFactory("DataAccess.Mock.PersonDal,DataAccess.Mock")]
[Serializable]
public class PersonEdit : BusinessBase<PersonEdit>

The ObjectFactory attribute is applied to a root business class. It requires a string parameter
that provides the name of the factory type. By default this string contains the assembly qualified
name of the type.
You can override that behavior by implementing your own custom factory type loader that
interprets the string value in any way you choose. This means that any time you use a factory
model you automatically have the ability to create a pluggable data access layer.
When the server-side data portal detects the ObjectFactory attribute on a root business type, it
will create an instance of the factory type and then invoke data operation methods on that factory
object.
By default, the names of the data operation methods are those listed in Table 17.

Name Description
Create Implements the create operation
Fetch Implements the Fetch operation
Update Implements the update operation (insert, update, and delete actions)
Delete Implements the delete operation
Execute Implements the execute operation
Invoke Implements any pre-processing behaviors
InvokeComplete Implements any post-processing behaviors
InvokeException Implements any post-processing exception behaviors

Table 17. Default factory method names for data operations


Normally a factory class will implement some or all of these methods.
You can override the names of the primary operation methods by providing alternate method
names to the ObjectFactory attribute. For example:
Using CSLA 4: Data Access Page 57
Rev 1.0
[Csla.Server.ObjectFactory("DataAccess.Mock.PersonDal,DataAccess.Mock",
"CreatePerson","FetchPerson", "UpdatePerson", "DeletePerson")]

In that case the data portal will invoke methods on the factory object based on the alternate
method names you’ve provided.

IObjectFactoryLoader Interface
As I discussed earlier, the ObjectFactory attribute requires a string parameter that provides the
name of the factory type associated with the root business type. By default this value is interpreted
as the assembly qualified type name of the factory class.
The interpretation of the parameter value is handled by an object called an object factory loader.
You can provide your own object factory loader to interpret the parameter value in any way you
choose. This is done by implementing the IObjectFactoryLoader interface and then configuring
the server-side data portal to use your factory loader instead of the default implementation.
Here’s an example of a factory loader that emulates the default behavior:
public class FactoryLoader : Csla.Server.IObjectFactoryLoader
{
public object GetFactory(string factoryName)
{
return Activator.CreateInstance(GetFactoryType(factoryName));
}

public Type GetFactoryType(string factoryName)


{
return Type.GetType(factoryName);
}
}

The interface requires that the factory loader implement a GetFactoryType method that returns
a Type object based on the factoryName parameter provided to the ObjectFactory attribute. You
can interpret the parameter value in any way you choose. For example, you might do one of the
following:

 Use Type.GetType to treat the value as an assembly qualified type name


 Rewrite the value to alter the type name, then use Type.GetType to get the type
 Look up the value in a config file that maps values to type names, then use Type.GetType to
get the type

The factory loader must also implement a GetFactory method that returns an instance of the
factory type. The simplest implementation is the one shown above, where the .NET Activator type
is used to create an instance of the type. You may also perform any initialization of the factory
object in this method.
Here’s an example of a factory loader that creates a type name by combining a configuration
value with the factoryName parameter:
public class FactoryLoader : Csla.Server.IObjectFactoryLoader
{
public string Assembly { get; set; }

public FactoryLoader()
{

Using CSLA 4: Data Access Page 58


Rev 1.0
Assembly = ConfigurationManager.AppSettings["ObjectFactoryAssembly"];
}

public object GetFactory(string factoryName)


{
return Activator.CreateInstance(GetFactoryType(factoryName));
}

public Type GetFactoryType(string factoryName)


{
var typeName = string.Format("{0}.{1},{0}", Assembly, factoryName);
var factoryType = Type.GetType(typeName);
if (factoryType == null)
throw new ArgumentException(string.Format("Can not find type '{0}'", typeName));
return factoryType;
}
}

As the factory loader is created it retrieves an ObjectFactoryAssembly value from the


web.config or app.config file. That value is then combined with the factoryName parameter in the
GetFactoryType method to create an assembly qualified type name that can be provided to the
Type.GetType method.

The ObjectFactory attribute should now provide only the name of the factory class, not the
assembly. For example:
[Csla.Server.ObjectFactory("PersonDal")]

The config file will contain entries to tell the data portal to use this custom factory loader, and
for the ObjectFactoryAssembly value:
<appSettings>
<add key="ObjectFactoryAssembly" value="DataAccess.Mock"/>
<add key="CslaObjectFactoryLoader" value="DataAccess.FactoryLoader,DataAccess"/>
</appSettings>

The CslaObjectFactoryLoader config value provides the data portal with the assembly qualified
type name of the custom factory loader implementation. That factory loader then reads the
ObjectFactoryAssembly config value to get the assembly and namespace that should be used to
create the assembly qualified type names of each factory class.

ObjectFactory Class
An object factory class is nothing more than a class that implements public methods for the
required data operations. For example:
public PersonList Fetch()
{
var result = new PersonList();
// implement DAL code here (factory implementation)
// or invoke external DAL here (factory invoke)
// load result with data
return result;
}

Like most Fetch and Create methods, this example method creates an instance of the business
type and returns it as a result.
The challenge with implementing this Fetch method is that the factory object needs to have
some way of manipulating the state and metastate of the business object. The PersonList type is a

Using CSLA 4: Data Access Page 59


Rev 1.0
read-only list, so the code in the Fetch method must somehow set the collection’s IsReadOnly
property to false, then true, and it must load the list with PersonInfo objects.
If the result were an editable object, this code would also need to somehow call the MarkOld
method on the result to properly set its metastate.
In short, factory objects must break encapsulation to manipulate the non-public state and
metastate of the business objects being persisted by the factory.
CSLA .NET includes the ObjectFactory base class in the Csla.Server namespace to help break
encapsulation without forcing every factory method to use reflection, or every business class to
implement alternate interfaces for use by factory objects.
Table 18 lists the protected members available from the ObjectFactory class.

Member Description
LoadProperty Loads a property value without invoking authorization or business rules
ReadProperty Reads a property value without invoking authorization rules
MarkAsChild Invokes MarkAsChild on the target object (editable object only)
MarkNew Invokes MarkNew on the target object (editable object only)
MarkOld Invokes MarkOld on the target object (editable object only)
BypassPropertyChecks Gets the BypassPropertyChecks object from the target object (editable
object only)
CheckRules Invokes the CheckRules method on the target object’s BusinessRules
object (editable object only)
FieldExists Gets a value indicating whether a managed backing value already exists for
the target property
GetDeletedList Gets the DeletedList collection from a BusinessListBase or
BusinessBindingListBase object
SetIsReadOnly Sets the IsReadOnly property on a ReadOnlyListBase,
ReadOnlyBindingListBase, or NameValueListBase object

Table 18. Members implemented by the ObjectFactory base class


The protected members of the ObjectFactory class make it possible to implement factory
methods that manipulate the state and metastate of business objects, breaking encapsulation in a
relatively abstract and maintainable manner. Most factory classes will inherit from ObjectFactory
to gain these behaviors. For example:
public class PersonDal : Csla.Server.ObjectFactory
{
public PersonList Fetch()
{
var result = new PersonList();
// implement DAL code here (factory implementation)
// or invoke external DAL here (factory invoke)
SetIsReadOnly(result, false);
// load result with data
SetIsReadOnly(result, true);

Using CSLA 4: Data Access Page 60


Rev 1.0
return result;
}
}

At this point you should understand how factory objects are created by the data portal, and how
you can use the ObjectFactory base class to implement factory types. I’ll now discuss each data
operation method you may implement in factory types.

Create Method
The Create method is invoked by the data portal when a new root obect is being created. The data
portal creates a new instance of the factory type and then the Create method is invoked.
The Create method is responsible for the following:

1. Creating the business object graph

2. Initializing the business object graph with data

3. Setting the business object graph metastate

4. Optionally executing business rules for each new object

5. Returning the root business object

Notice that I’m using the phrase “business object graph”, because the Create method may
create one object, or an entire object graph with a root object.
Here’s an example of a synchronous Create method on .NET:
public PersonEdit Create()
{
var result = new PersonEdit();
// implement DAL code here (factory implementation)
// or invoke external DAL here (factory invoke)
MarkNew(result);
CheckRules(result);
return result;
}

You can see how this method performs each step, starting with creating an instance of the
business object and ending with returning that object as a result.
Because this Create method doesn’t accept a parameter, it corresponds to this data portal
Create method call:
public static PersonEdit NewPersonEdit()
{
return DataPortal.Create<PersonEdit>();
}

The data portal uses standard .NET method overloading rules. If the data portal’s Create or
BeginCreate method is passed a criteria value, the data portal will invoke a Create method in the
factory object that accepts a parameter of that type. This is the same behavior I described earlier
for the DataPortal_XYZ methods.

Using CSLA 4: Data Access Page 61


Rev 1.0
When factory classes are implemented to run on Silverlight and WP7 the methods are
asynchronous and so they must accept a callback handler parameter. For example:
public void Create(
Csla.DataPortalClient.LocalProxy<PersonEdit>.CompletedHandler handler)
{
try
{
var result = new PersonList();
// implement DAL code here (factory implementation)
// or invoke external DAL here (factory invoke)
MarkNew(result);
CheckRules(result);
handler(result, null);
}
catch (Exception ex)
{
handler(null, ex);
}
}

This Create method is not invoked asynchronously by the data portal, but the data portal
assumes the code inside this method will be asynchronous. When using a local data portal
configuration on a Silverlight client, the assumption is that the factory method will invoke a remote
SOAP or REST service. Because all server calls must be asynchronous on Silverlight, the
implementation of any factory method is assumed to contain asynchronous code.
The important thing to understand is that the Create method you implement in a factory class is
entirely responsible for creating, initializing, and returning the requested business object or object
graph. This includes initializing the new object’s state and metastate.

Fetch Method
The Fetch method is invoked by the data portal when an existing root obect is being retrieved. The
data portal creates a new instance of the factory type and then the Fetch method is invoked.
The Fetch method is responsible for the following:

1. Creating the business object graph

2. Loading the business object graph with existing data

3. Setting the business object graph metastate

4. Returning the root business object

The process is very similar to the Create method, except the Fetch method loads the object or
object graph with existing data. Here’s an example of a synchronous Fetch method on .NET:
public PersonEdit Fetch(int id)
{
var result = new PersonEdit();
// implement DAL code here (factory implementation)
// or invoke external DAL here (factory invoke)
MarkOld(result);
return result;
}

Using CSLA 4: Data Access Page 62


Rev 1.0
Most Fetch methods will accept a criteria parameter. In this example, the value is of type int,
and so it corresponds to a Fetch or BeginFetch data portal call like this:
public static PersonEdit GetPersonEdit(int id)
{
return DataPortal.Fetch<PersonEdit>(id);
}

The data portal uses standard .NET method overloading rules. If the data portal’s Fetch or
BeginFetch method is passed a criteria value, the data portal will invoke a Fetch method in the
factory object that accepts a parameter of that type. This is the same behavior I described earlier
for the DataPortal_XYZ methods.
When factory classes are implemented to run on Silverlight and WP7 the methods are
asynchronous and so they must accept a callback handler parameter. For example:
public void Fetch(
Csla.DataPortalClient.LocalProxy<PersonEdit>.CompletedHandler handler)
{
try
{
var result = new PersonList();
// implement DAL code here (factory implementation)
// or invoke external DAL here (factory invoke)
MarkOld(result);
handler(result, null);
}
catch (Exception ex)
{
handler(null, ex);
}
}

As with the Create method, it is important to understand that the Fetch method you implement
in a factory class is entirely responsible for creating, loading, and returning the requested business
object or object graph. This includes initializing the new object’s state and metastate.

Update Method
The Update method is invoked by the data portal when an editable root object is saved. This
method handles the insert, update, and delete actions, and so it is the most complex of the factory
methods.
The Update method accepts the root business object as a parameter, and returns the root
business object as a result. In most cases the same object is returned as a result, but it is possible
for an Update method to entirely reload or recreate the object graph if appropriate.
Here’s an example of a synchronous Update method on .NET:
public PersonEdit Update(PersonEdit obj)
{
if (obj.IsDeleted)
{
if (!obj.IsNew)
using (BypassPropertyChecks(obj))
{
// implement DAL code here (factory implementation)
// or invoke external DAL here (factory invoke)
}
MarkNew(obj);
}
Using CSLA 4: Data Access Page 63
Rev 1.0
else if (obj.IsNew)
{
using (BypassPropertyChecks(obj))
{
// implement DAL code here (factory implementation)
// or invoke external DAL here (factory invoke)
}
MarkOld(obj);
}
else
{
using (BypassPropertyChecks(obj))
{
// implement DAL code here (factory implementation)
// or invoke external DAL here (factory invoke)
}
MarkOld(obj);
}
return obj;
}

Notice how the implementation uses the root object’s metastate to determine if the object is
marked for deletion, or is new. If IsDeleted is true, the object’s data is deleted. If IsNew is true,
the object’s data is inserted. Otherwise, the object’s data is updated.
In each case, the object’s metastate is updated appropriately. For example, once an object’s data
has been deleted, the object is marked as new by calling the MarkNew method from the
ObjectFactory base class.

If the root object contains child objects, the Update method is responsible for inserting,
updating, or deleting those objects as well. I typically use private methods in the factory class to
implement those actions for each type of object in an object graph.
The same requirements apply to an asynchronous Update method on Silverlight or WP7:
public void Update(
PersonEdit obj, Csla.DataPortalClient.LocalProxy<PersonEdit>.CompletedHandler handler)
{
try
{
if (obj.IsDeleted)
{
if (!obj.IsNew)
using (BypassPropertyChecks(obj))
{
// implement DAL code here (factory implementation)
// or invoke external DAL here (factory invoke)
}
MarkNew(obj);
}
else if (obj.IsNew)
{
using (BypassPropertyChecks(obj))
{
// implement DAL code here (factory implementation)
// or invoke external DAL here (factory invoke)
}
MarkOld(obj);
}
else
{
using (BypassPropertyChecks(obj))
{
// implement DAL code here (factory implementation)

Using CSLA 4: Data Access Page 64


Rev 1.0
// or invoke external DAL here (factory invoke)
}
MarkOld(obj);
}
handler(obj, null);
}
catch (Exception ex)
{
handler(null, ex);
}
}

This Update method is not invoked asynchronously by the data portal, but the data portal
assumes the code inside this method will be asynchronous. When using a local data portal
configuration on a Silverlight client, the assumption is that the factory method will invoke a remote
SOAP or REST service. Because all server calls must be asynchronous on Silverlight, the
implementation of any factory method is assumed to contain asynchronous code.

Delete Method
The Delete method is invoked by the data portal when an immediate delete operation is required.
Like the Create and Fetch methods, the Delete method can accept a criteria parameter to identify
the data to be deleted.
Here’s an example of a synchronous Delete method on .NET:
public void Delete(int id)
{
// implement DAL code here (factory implementation)
// or invoke external DAL here (factory invoke)
}

This method is invoked by the data portal in response to a Delete or BeginDelete method call
like this:
public static void DeletePersonEdit(int id)
{
DataPortal.Delete<PersonEdit>(id);
}

Notice how the parameter type of the data portal Delete call matches the parameter accepted
by the Delete method in the factory class.
Here’s an example of an asynchronous Delete method on Silverlight:
public void Delete(
int id, Csla.DataPortalClient.LocalProxy<PersonEdit>.CompletedHandler handler)
{
try
{
// implement DAL code here (factory implementation)
// or invoke external DAL here (factory invoke)
handler(null, null);
}
catch (Exception ex)
{
handler(null, ex);
}
}

The callback handler parameter is required so the Delete method can tell the data portal when
the operation is complete.
Using CSLA 4: Data Access Page 65
Rev 1.0
Execute Method
The Execute method is invoked by the data portal when a command object is executed. The data
portal passes the root business object to the Execute method, and expects the root object to be
returned as a result.
Here’s an example of a synchronous Execute method on .NET:
public OrderShipper Execute(OrderShipper obj)
{
// implement DAL code here (factory implementation)
// or invoke external DAL here (factory invoke)
return obj;
}

The Execute method can interact with the properties of the command object, and will often
implement or invoke data access code to perform the requested action. As with all command
objects, it is important to realize that a command doesn’t always correspond to a direct data access
operation. The code in this Execute method can interact with any server-side resources, other
business objects, and the database.
Here’s an example of an asynchronous Execute method on Silverlight or WP7:
public void Execute(
OrderShipper obj, Csla.DataPortalClient.LocalProxy<OrderShipper>.CompletedHandler handler)
{
try
{
// implement DAL code here (factory implementation)
// or invoke external DAL here (factory invoke)
handler(obj, null);
}
catch (Exception ex)
{
handler(null, ex);
}
}

As with the other asynchronous factory methods, the assumption is that the code inside this
method will invoke remote SOAP or REST services, or will execute code on a background thread.
While the Execute method isn’t invoked asynchronously by the data portal, the data portal expects
that the method will implement asynchronous behaviors.
At this point, you should understand the factory methods that implement the Create, Fetch,
Update, Delete, and Execute data portal operations. The data portal also invokes methods for pre-
and post-processing of data portal operations.

Invoke Method
A factory class on .NET can implement an Invoke method. This method is invoked by the server-side
data portal before any method implementating a data portal operation. You can think of the Invoke
method as being a place to implement pre-processing code that should run before any data
operation.
This feature doesn’t exist on Silverlight or WP7, and any Invoke method you implement in a
client-side factory class won’t be invoked by the data portal.

Using CSLA 4: Data Access Page 66


Rev 1.0
The most common reason for implementing this method is for logging, instrumentation, or
diagostics. This method is invoked after the data portal request has been deserialized, and the data
portal has set up the current user principal object and ApplicationContext context dictionaries.
Here’s an example of the Invoke method:
public void Invoke(Csla.Server.DataPortalContext context)
{
// implement pre-processing here
}

You can implement appropriate pre-processing code in this method.

InvokeComplete Method
A factory class on .NET can implement an InvokeComplete method. This method is invoked by the
server-side data portal after every successful data portal operation. You can think of the
InvokeComplete method as being a place to implement post-processing code that should run after
any data operation.
This feature doesn’t exist on Silverlight or WP7, and any InvokeComplete method you implement
in a client-side factory class won’t be invoked by the data portal.
The most common reason for implementing this method is for logging, instrumentation, or
diagostics. This method is invoked after the data portal operation is complete, and before results
are serialized back to the client.
Here’s an example of the InvokeComplete method:
public void InvokeComplete(Csla.Server.DataPortalContext context)
{
// implement post-processing here
}

You can implement appropriate post-processing code in this method.

InvokeError Method
A factory class on .NET can implement an InvokeError method. This method is invoked by the
server-side data portal after any data portal operation that throws an exception.
This feature doesn’t exist on Silverlight or WP7, and any InvokeError method you implement in
a client-side factory class won’t be invoked by the data portal.
The most common reason for implementing this method is for logging, instrumentation, or
diagostics. This method is invoked after the data portal operation is complete, when the operation
has thrown an exception.
Here’s an example of the InvokeError method:
public void InvokeError(Exception ex)
{
// implement exception handling here
}

The Exception object is passed to the method as a parameter, so you can log or record the
exception information.

Using CSLA 4: Data Access Page 67


Rev 1.0
This method is invoked before any custom IDataPortalExceptionInspector implementation is
executed, so the Exception parameter passed to the InvokeError method is the original exception
before any rewriting has occurred.
In this chapter I have discussed the encapsulation and factory data portal models, along with
several important data portal features you can use in your applications. In the next chapter I will
discuss some helper types in the Csla.Data namespace. Then, in Chapter 4, I will walk through
some specific examples showing how to invoke or implement data access code.

Using CSLA 4: Data Access Page 68


Rev 1.0
Chapter 3:
CSLA .NET Data Helpers
There are many ways to implement data access code, but there are several common issues that
must be addressed by most Data Access layer implementations. On .NET, the Csla.Data namespace
contains helper types you might find useful when implementing data access code.
These types are strictly optional, and there is no requirement that you use them in your
applications. However, they can be useful to solve some common problems.

Csla.Data Namespace
Table 19 provides a summary of the types from the Csla.Data namespace I will discuss in this
chapter.

Type Description
ConnectionManager Enables reuse of a single IDbConnection database connection object
ObjectContextManager Enables reuse of a single ADO.NET Entity Framework context object
TransactionManager Enables reuse of a single IDbConnection database connection object
and associated IDbTransaction ADO.NET transaction object
ContextManager Enables reuse of a single LINQ to SQL context object
DataMapper Copies property and field values from one object to another using
dynamic property or field invocation
ObjectAdapter Converts data from an object into a DataSet or DataTable
SafeDataReader Provides an IDataReader data reader implementation that
automatically replaces all null data values with empty or zero
equivalents

Table 19. Csla.Data namespace types covered in Chapter 3

Data Object Managers


The ConnectionManager, ObjectContextManager, TransactionManager, and ContextManager types
are all designed to address a specific issue with database transactions. Each class solves the same
problem for ADO.NET connections, Entity Framework contexts, and LINQ to SQL contexts.
The problem is that the TransactionScope object from the System.Transactions namespace
has a serious limitation. When more than one database connection is opened within the scope of a
TransactionScope object, the TransactionScope object will attempt to elevate the transaction to a
distributed transaction. Distributed transactions are managed by the Microsoft Distributed
Transaction Coordinator (DTC).
Using a TransactionScope object to apply a transaction to data operations on a single database
connection is easy and fast. As long as the database is supported by TransactionScope, and only
one database connection is opened, everything works great.
Using CSLA 4: Data Access Page 69
Rev 1.0
But if a second database connection is opened, the DTC comes into play. This has two negative
impacts: a noticeable performance cost is incurred, and by default the DTC isn’t enabled on client
computers. In a 1- or 2-tier physical deployment the data access code is typically running on the
client workstation, and an exception will be thrown because the DTC isn’t enabled. But even in
cases where the data access code is running on a computer where the DTC is enabled, the
performance impact of a distributed transaction is usually noticeable.
Unfortunately, it is very common to open multiple connections to a database. If an object graph
has a root object that contains a collection of child objects, it is very likely that each object will open
a connection to the database to insert, update, or delete the object’s data. Most developers don’t
think twice about opening database connections, because .NET implements database connection
pooling, so the same connection is reused and performance is good.
Even with database connection pooling causing the same connection to be reused, the
TransactionScope object sees each use of the connection as a separate event and so it thinks the
application is opening more than one connection.
To avoid accidental use of the DTC, it is important for applications to reuse the same open
database connection object. This means that the root object should open the connection, and that
same open connection should be used by all child objects in the object graph.
This can get even more complex because one root object can interact with other root objects,
and in that case multiple root objects should reuse the same open connection.
The connection manager types discussed in this chapter solve this problem by enabling a
consistent coding pattern for use in all root and child objects. If your code always follows the same
pattern, you’ll automatically reuse the same open connection and avoid having the
TransactionScope object use the DTC.

The basic coding pattern is best illustrated with an example:


using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
SqlCeConnection connection = ctx.Connection;
// use the connection variable to interact with the database

// persist all objects before exiting the using block


}

This example uses the ConnectionManager type to get access to an open SqlCeConnection
object. If no database connection already existed, one is created and opened. But if a database
connection was already open, that open connection is reused.
Looking at this code, you can’t tell if the GetManager method created and opened a connection,
or just returned access to an already open connection. That is the point of this coding pattern; to
abstract this behavior out of your code and into the framework.
The most important part of this coding pattern is that the data access code for every object
performs all object persistence within the using block for the manager object. That must include
any method calls to persist child objects, or other root objects.
A connection manager object detects when the any data access code enters the first using
block, and it creates and opens the appropriate database connection, object context, or other
managed data object. That connection object is held open until that first using block exits.
Using CSLA 4: Data Access Page 70
Rev 1.0
This is illustrated in Figure 9, where you can see how multiple levels of using blocks are nested
within the top-level using block created by the first object.

Figure 9. Nested connection manager objects


Any using blocks nested inside another using block will reuse the already-open connection. This
is true even if those subsequent using blocks are in other root or child objects.
The various connection manager objects are designed to manage different types of data
connection object, but they all follow this same coding pattern. I’ll discuss each manager object in
turn.

ConnectionManager Class
The ConnectionManager class is designed to enable the reuse of standard ADO.NET connection
objects. There are two requirements on the connection class:

1. The connection class must implement IDbConnection from the System.Data namespace

2. The connection class must implement a public constructor that accepts the database
connection string as a parameter

All standard database connection objects meet these requirements, including SqlConnection for
SQL Server databases and SqlCeConnection for SQL Server Compact Edition databases.
Here is an example of a typical using block with a ConnectionManager type:
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
// interact with database using ctx.Connection
}

The GetManager method has several overloads with parameters as described in Table 20.

Using CSLA 4: Data Access Page 71


Rev 1.0
Parameter name Description
database The database parameter is the name of the database entry in the
web.config or app.config database configuration list: the
connectionStrings element
isDatabaseName If isDatabaseName is false, then the database parameter is the
database connection string; if isDatabaseName is true, then the
database parameter is the name of the database entry in the config
file; isDatabaseName defaults to true
label An optional label for the connection; every label has its own open
connection

Table 20. Connection manager GetManager method overloads


By default the database parameter is the name of the database entry in connectionStrings
element of the application’s web.config or app.config file. The GetManager method will retrieve
the connection string from the config file to open the database connection.
You can use the isDatabaseName parameter to tell GetManager that you are providing the
connection string directly. If this value is false then GetManager will use the database parameter
value as the connection string when it opens the database connection.
It is also possible to have more than one open database connection at the same time by using
the label parameter. Each label value has its own open database connection, so the following
code will have two open connections:
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
// interact with database using ctx.Connection
using (var ctx2 = ConnectionManager<SqlCeConnection>.GetManager("LocalDb", "MyLabel"))
{
// interact with database using ctx.Connection or ctx2.Connection
}
}

The first GetManager method call opens or reuses the connection associated with the default
label. The second GetManager method call opens or reuses the connection associated with the
MyLabel label.

Remember that if you open multiple database connections while inside a


TransactionScope you will make the TransactionScope object use the DTC to
manage the transaction.

The ConnectionManager type doesn’t alter the way database connection objects work. It simply
provides a way to reuse an already-open connection. This means that any code you use that
interacts with the connection object must follow the normal rules for that type of connection
object.

Using CSLA 4: Data Access Page 72


Rev 1.0
ObjectContextManager Class
The ObjectContextManager type is designed to enable the reuse of an ADO.NET Entity Framework
(EF) context object. An EF context object contains an open database connection, along with
managing the state of entity objects associated with the context.
When using EF to build data access code, you will need to reuse the same open context object to
avoid opening multiple database connections, and to ensure that EF is able to consistently persist
all related entity objects.
Here’s an example of using the ObjectContextManager type:
using (var ctx = ObjectContextManager<LocalDbContext>.GetManager("LocalDb"))
{
// ctx.ObjectContext is the EF context object
}

The GetManager has the same overloads as for the ConnectionManager type, as described in
Table 20.
The ObjectContextManager type doesn’t alter the way EF context objects work. It provides a
way to reuse an existing context object and its already-open database connection. Any standard EF
context object can be used with the ObjectContextManager type.

TransactionManager Class
The TransactionManager type is designed to enable the reuse of an ADO.NET transaction object.
This type should be used with Manual data portal transactions, where you are creating and using
your own database transaction through ADO.NET.
The TransactionManager type works with any transaction type that implements the
IDbTransaction interface from the System.Data namespace. This includes all transaction types
from standard ADO.NET database implementations, including those for SQL Server and other major
databases.
Here’s an example of using the TransactionManager type:
using (var ctx = TransactionManager<SqlCeConnection, SqlCeTransaction>.GetManager("LocalDb"))
{
// access the transaction with ctx.Transaction
// interact with database using ctx.Connection
}

The GetManager method opens or reuses an existing database connection and transaction
object.
If the outermost using block exits without an exception, the transaction is committed and the
database connection is closed.
If the outermost using block exits due to an unhandled exception, the transaction is rolled back
and the database connection is closed.
The GetManager method accepts the same parameters as with the ConnectionManager type, as
described in Table 20.
Within the using block, you can access the database connection through the manager’s
Connection property.
Using CSLA 4: Data Access Page 73
Rev 1.0
You can also access the transaction object through the manager’s Transaction object.
Remember that the TransactionManager type will automatically call the Commit and Rollback
metods on the transaction object. You should not invoke those methods manually.

ContextManager Class
The ContextManager type is designed to enable the reuse of LINQ to SQL context object. A LINQ to
SQL context object contains an open database connection, along with managing the state of data
objects associated with the context.
When using LINQ to SQL to build data access code, you will need to reuse the same open context
object to avoid opening multiple database connections, and to ensure that LINQ to SQL is able to
consistently persist all related data objects.
Here’s an example of using the ContextManager type:
using (var ctx = ContextManager<LocalDbContext>.GetManager("LocalDb"))
{
// ctx.Context is the LINQ to SQL context object
}

The GetManager has the same overloads as for the ConnectionManager type, as described in
Table 20.
The ContextManager type doesn’t alter the way LINQ to SQL context objects work. It simply
provides a way to reuse an existing context object and its already-open database connection. Any
standard LINQ to SQL context object can be used with the ContextManager type.
At this point, you should understand the value of the connection and context manager types,
and how they enable the abstract reuse of already-open database connections within your data
access code.

DataMapper Class
When Web Forms data binding needs to insert or update data, it provides the data elements to the
ASP.NET data source control in the form of a dictionary object of name/value pairs. The
CslaDataSource control from the Csla.Web assembly and namespace provides this dictionary
object to the UI code as an event argument.
This means that in a typical Web Forms application that uses the CslaDataSource, the UI code
must copy the values from the dictionary to the business object’s properties. The name is the name
of the property to be updated, and the value is the value to be placed into the property of the
business object. Copying the values isn’t hard—the code looks something like this:
cust.FirstName = e.Values["FirstName"].ToString();
cust.LastName = e.Values["LastName"].ToString();
cust.City = e.Values["City"].ToString();

Code implementing a service in WCF or the older asmx technology has a similar scenario, where
the values passed to the service as part of the XML or JSON message are translated into a set of
data objects. The data values from those objects must be copied into the business object’s
properties. Again, the code isn’t difficult to write:

Using CSLA 4: Data Access Page 74


Rev 1.0
cust.FirstName = message.FirstName;
cust.LastName = message.LastName;
cust.City = message.City;

Unfortunately, this is tedious code to write and debug; and if your object has a lot of properties,
this can add up to a lot of lines of code. An alternative is to use reflection or the dynamic setting of
property values to automate the process of copying the values.
The DataMapper class uses reflection and dynamic property setting technology to help automate
these data mapping operations; from either a collection implementing IDictionary or an object
with public properties.

The use of DataMapper is entirely optional, and is a trade-off between


maintainability and performance. Code that directly copies values is almost always
faster than using DataMapper. But that manual code is verbose, and can be hard to
maintain over time. You need to decide whether performance or maintainability is
more important for each web page and service implementation.

In any case, it is possible or even likely that some properties can’t be mapped. Business objects
often have read-only properties, and obviously it isn’t possible to set those values. Yet the
IDictionary or DTO may have a value for that property. It is up to the business developer to deal
on a case-by-case basis with properties that can’t be automatically mapped.
The DataMapper class will accept a list of property names to be ignored. Properties matching
those names simply won’t be mapped during the process. Additionally, DataMapper will accept a
Boolean flag that can be used to suppress exceptions during the mapping process. This can be used
simply to ignore any failures.
An alternative is to provide DataMapper with a DataMap object that explicitly describes the source
and target properties for the mapping.

Map Method
The most basic use of the DataMapper class involves the Map method. This method maps data values
from a source object to a target object. It does not loop over collections or traverse object graphs.
The Map method copies property values from one object to another.
DataMapper.Map(source, target);

The source parameter may be one of:

 object
 IDictionary

The target parameter may be one of:

 object
 Dictionary<string, object>

Using CSLA 4: Data Access Page 75


Rev 1.0
Mapping Description
object, object Properties from the source are mapped to properties of exactly the
same name and type on the target
IDictionary, object Elements from the dictionary are mapped to properties of the target
object, where the target property names exactly match the key names
in the dictionary
object, Dictionary Properties from the source are mapped to entries of the target, using
the source property names as keys in the dictionary

Table 21 describes how each mapping occurs by default (without the use of an explicit DataMap
object).

Mapping Description
object, object Properties from the source are mapped to properties of exactly the
same name and type on the target
IDictionary, object Elements from the dictionary are mapped to properties of the target
object, where the target property names exactly match the key names
in the dictionary
object, Dictionary Properties from the source are mapped to entries of the target, using
the source property names as keys in the dictionary

Table 21. Default DataMapper mapping behaviors


It is important to understand that the property and dictionary key names must match. The
default mapping behavior assumes these values match between the source and target. If they do
not match, you must create an explicit DataMap object to control the mapping process.
Another consideration is that the properties on a source or target of type object must be public
in scope. Again, you can use a DataMap object to change this behavior and get or set non-public
property or field values.

Non-Browsable Properties
The System.ComponentModel namespace includes a Browsable attribute. This attribute is used by
.NET to indicate properties that are not available for data binding.
The Map method is a sort of “data binding”, in that it binds data values from one object to
another. Because of this, any source object properties that are decorated with the
Browsable(false) attribute are ignored during the mapping process. This includes the metastate
properties on editable business objects such as IsNew and IsDeleted.

Using an IgnoreList
The Map method has numerous overloads to support the mappings listed in Table 21. It is also
possible to provide an ignore list parameter that tells the Map method to ignore certain properties
from the source object.

Using CSLA 4: Data Access Page 76


Rev 1.0
The ignoreList parameter is a params array of type string, and it allows you to provide a
comma-separate list of property names to ignore:
DataMapper.Map(source, target, "Id", "TotalSales");

During the mapping process, properties in this list are simply ignored, whereas all other property
values are copied. You can use this feature to avoid trying to map values into a read-only property,
or getting values the user isn’t authorized to read.

Mapping from an Object with a DataMap


You can also create a DataMap to describe the mapping of properties or fields from one object to
another. This DataMap can be passed to the DataMapper object’s Map method, and in that case the
DataMap is used to determine the source and target properties or fields.
A DataMap is created using code like this:
var map = new DataMap(typeof(CustomerData), typeof(CustomerEdit));
map.AddPropertyMapping("SourceName", "TargetName");

The DataMap constructor requires that the types of the source and target objects be provided.
This is required, because reflection is used behind the scenes to get PropertyInfo or FieldInfo
objects for each property or field you specify. X lists the methods used to load a DataMap with
mappings.

Method Description
AddPropertyMapping Sets up a mapping from one property to another property
AddFieldMapping Sets up a mapping from one field to another field (even if the fields are
non-public)
AddFieldToPropertyMapping Sets up a mapping from a field to a property
AddPropertyToFieldMapping Sets up a mapping from a property to a field

Table 22. Methods on DataMap


These methods give you the flexibility to map most values from one object to another in a very
flexible manner.

Reflection against public members is much faster than against non-public


members. If you set up a DataMap that copies to or from non-public properties or
fields you should do careful performance testing to ensure you are comfortable with
the results.

The Map method works the same as described earlier, except that it uses the information in the
DataMap object to determine the source and target properties or fields. Because you are specifying
the map explicitly, no ignoreList parameter is used.

Value Coersion
In cases where the source and target property or field types don’t match, the Map method will
attempt to coerce the source value into the target type. The coercion used is aggressive, and will
Using CSLA 4: Data Access Page 77
Rev 1.0
attempt to use every technique available in .NET to cast or convert the source value to the target
type.
The value coercion is implemented by the CoerceValue method from the Csla.Utilities class.
The CoerceValue method is public, and can be used by your code directly if you find it of value.
This method uses a number of techniques in an attempt to coerce a value to the new type,
including:

 If the value is already the right type do nothing


 If the target type is Nullable<T> then try to convert to T
 If the target type is an enum then try to parse the value
 If the target type is a SmartDate then try to cast the value
 If the target type is a primitive type, or decimal and the value is an empty string, set the
value to 0
 If nothing has worked yet, call Convert.ChangeType() to convert the type
 If ChangeType() fails, see if there’s a TypeConverter for the target type and if so use the
TypeConverter
 If nothing has worked yet, throw an exception

It is important to understand that this coercion process is automatically invoked by the Map
method when the source and target property or field types don’t match. You may find that values
from a source object successfully map to the target in cases where a simple cast would fail, and that
is because this coercion process is more aggressive than a simple cast operation.
The DataMapper type can be useful in simplifying or reducing repetitive code for mapping data
from one object to another. It is designed to support Web Forms and service development, but you
can use it any time data must be mapped from one object to another.

ObjectAdapter Class
The ObjectAdapter class is similar to the DataMapper class, in that it is designed to map data from
business objects into a DataSet or DataTable object.
The ObjectAdapter class implements a Fill method. This method works much like the Fill
method from a standard ADO.NET TableAdapter object. The Fill method copies property values
from a business object into a DataTable or DataSet:
adapter.Fill(dataset, source);
adapter.Fill(dataset, "TableName", source);
adapter.Fill(datatable, source);

If the source object is a single object, then one row of data is added to the DataTable or
DataSet. If the source object is a collection, then one row of data is added to the DataTable or
DataSet for each item in the collection.

Things are slightly more complex if the business object graph has several levels of object. For
example, an OrderEdit object containing a child collection of LineItemEdit objects will require two

Using CSLA 4: Data Access Page 78


Rev 1.0
calls to the Fill method: one to copy the OrderEdit object, and a second to copy the collection of
child objects.
The property names of the source object are used as column names in the target DataTable. If
the target DataTable is missing columns for any properties, those columns are automatically added.
This means you can write code like the following:
var datatable = new System.Data.DataTable();
adapter.Fill(datatable, source);

Because the target DataTable object is empty, the Fill method will automatically add all
necessary column definitions before copying the source object’s properties into the DataTable.
You can use the ObjectAdapter class to convert business objects into DataTable or DataSet
objects when the application requirements need one of these older ADO.NET data types.

SafeDataReader Class
One of the basic ADO.NET data types is the data reader. All data reader objects implement the
IDataReader interface from the System.Data namespace, and every ADO.NET provider
implementation includes a data reader.
One of the most common issues application developers face when reading data from a database
is that some database columns allow null data values that have no meaning to the application.
When those null data values are read from the database they must be converted into some
meaningful non-null value for use by the application.
There are two major reasons for using null data values in a database:

1. Optional foreign key references

2. Values that have yet to be entered

The second reason, values that have yet to be entered, only has meaning if the business cares
about the difference between an empty value and a value that has never been entered. For a
numeric type this means that there is a business difference between a zero and a value that hasn’t
been entered at all.
This is a valid concern, because in some applications there is a big difference between a zero
entered by a user, and a value that hasn’t been entered. For most applications, this sort of
distinction has no meaning.
In my experience, a lot of databases allow null values in columns where no null values should be
allowed. I am sure there are many reasons why this occurs, but the end result is that many
application developers are left reading data from the database and having to convert null data
values into a meaningful equivalent, such as 0, false, string.Empty, etc.
The SafeDataReader class is a data reader implementation that wraps any other IDataReader
and automatically removes all null data values that come from the database. The goal of
SafeDataReader is to simplify data access code that uses a data reader, so the data access code
never has to worry about getting a null data value.

Using CSLA 4: Data Access Page 79


Rev 1.0
If your application does need null data values you should not use SafeDataReader.

Here’s an example of using the SafeDataReader type:


using (var dr = new SafeDataReader(cm.ExecuteReader()))
{
dr.Read();
using (BypassPropertyChecks(result))
{
LoadProperty(result, PersonEdit.IdProperty, dr.GetInt32("Id"));
result.FirstName = dr.GetString("FirstName");
result.LastName = dr.GetString("LastName");
}
}

The ExecuteReader method is called on the command object (cm), and the result of that method
is wrapped in a new SafeDataReader object. The SafeDataReader class can wrap any IDataReader
type, and since all data readers implement this interface, it can wrap any data reader object.
The resulting SafeDataReader object is used exactly like a normal data reader, except that any
null data values are automatically converted into the non-null default value for the data type. For
example, a null string value is converted to string.Empty, and a null numeric value is converted to
0.

One other nice feature of SafeDataReader is that it allows the direct use of the column name
instead of its ordinal position value. In the code above, you can see how the GetString method
directly accepts the column name instead of the numeric column position. Assuming the FirstName
column is column number 1, the following three lines of code are equivalent:
result.FirstName = dr.GetString("FirstName");
result.FirstName = dr.GetString(dr.GetOrdinal("FirstName"));
result.FirstName = dr.GetString(1);

You should consider using SafeDataReader if your application doesn’t have a business
requirement to differentiate between empty data values and values never entered by a user.
At this point I have discussed the utility types available in the Csla.Data namespace. In Chapter
4 I will discuss how to create data access layers in the encapsulated invoke and factory
implementation models.

Using CSLA 4: Data Access Page 80


Rev 1.0
Chapter 4:
Data Access Implementation
In Chapter 1 I discussed the four models the data portal supports for data access:

1. Encapsulated invocation

2. Factory implementation

3. Factory invocation

4. Encapsulated implementation

The two models I recommend for most applications are encapsulated invocation and factory
implementation, so these are the models I will cover in detail.
Encapsulated invocation allows the data portal to manage the metastate of the business objects,
while enabling clean separation of the data access implementation.
Factory implementation enables clean separation of the data access implementation, along with
enabling a high degree of flexibility in how your data access code manipulates the state and
metastate of the business objects.
The other two models are variations on the same concepts, but each has drawbacks. Factory
invocation adds a redundant layer of indirection that usually introduces more complexity and
overhead than can be justified for an application. Encapsulated implementation is the simplest of all
the models, but doesn’t enable separation of the data access implementation from the business
classes and so it is also the least flexible.
In this chapter I will discuss some options for implementing an external Data Access layer that
can be invoked by a DataPortal_XYZ method or factory object method.
In Chapters 5 and 6 I will then move on to demonstrate how to implement data access for a set
of business objects using the two data portal models I generally recommend: encapsulated
invocation and factory implementation. The other two data portal models are variations on these
concepts, so once you understand the two models I’ll demonstrate in this ebook you should be able
to implement the other models if necessary.

Implementing a Data Access Layer


There are many ways to implement an external Data Access layer (DAL) for an application, and it is
impractical for me to cover every possibility in this chapter. At the same time, it is important to
understand the high level concepts you should think about when designing any data access
component.
The data access component will be invoked by your DataPortal_XZY methods or your factory
object methods. Remember from Figure 3 in Chapter 1 that there are three areas of concern around
object persistence:

Using CSLA 4: Data Access Page 81


Rev 1.0
1. Business Object

2. Data Access Invocation

3. Data Access (DAL)

When the DAL is external, the data access invocation code is responsible for invoking the DAL to
get, save, or delete data. This invocation code might be in your DataPortal_XYZ methods, or it
might be in your factory object methods. Either way, the DAL must expose some formal interface
that can be invoked.
External DAL components are usually loaded dynamically at runtime. This allows the DAL
components to be swapped for other components, resulting in a “pluggable DAL”. I recommend at
least implementing your real DAL and a “mock” DAL that provides hard-coded data values for
testing of the application. You can also use a pluggable DAL to allow an application to work against
multiple types of database, such as SQL Server, Oracle, and DB2.
It is also the case that some code must interact with the private state and metastate of the
business object to get and set the object’s properties and metastate. As I’ve already discussed, this
can be done in a way that preserves encapsulation by using the DataPortal_XYZ methods, or it can
be done by breaking encapsulation with factory objects and the ObjectFactory base class.
I’ll cover all these concepts, starting with options for the DAL interface.

Data Access Layer Interface Options


The first step in creating a pluggable DAL is to define the interface that will be implemented by
every concrete DAL implementation. This interface defines how the DAL returns data from the
database, and how it defines Insert, Update, and Delete operations.
There are many ways to implement a DAL, and therefore the interface to the DAL. But there are
two types of DAL interface that are quite common:

1. Data reader and methods

2. Data transfer object (DTO) and methods

I’ll discuss each of these options.

Data Reader and Methods


The low-level ADO.NET data types, such as a data reader, are widely available and usually provide
the highest performance for data access. Because performance is often a critical requirement for
applications and data access, the direct use of ADO.NET types is beneficial.
A data reader based DAL usually consists of one class for each type of data entity, and each DAL
class defines methods to fetch, insert, update, and delete that type of data entity. It is also common
for a DAL class to implement methods that can fetch a single entity or a list of entities.

Using CSLA 4: Data Access Page 82


Rev 1.0
There are no hard-and-fast rules about how data methods are organized into
classes. The ideas I am suggesting here have worked well for me, but you should
understand that there are many alternatives available.

Here’s an example interface for a person entity:


public interface IPersonDal
{
IDataReader Fetch();
IDataReader Fetch(int id);
int Insert(string firstName, string lastName);
void Update(int id, string firstName, string lastName);
void Delete(int id);
}

The methods that Fetch data return their results through an IDataReader object. This is the
interface defined by ADO.NET for all data reader objects, so these Fetch methods could be getting
the data from SQL Server, Oracle, or any other data source with support for ADO.NET.
The Insert method defines parameters for every data value that is required in the database.
The method also returns an int value. That value is the new primary key value generated by the
database during the insert operation.
The Update method defines parameters for every data value necessary to perform the update
operation in the database.
The Delete method requires the primary key value for the data entity so it can implement the
delete operation.
I will demonstrate implementations of this interface later in the chapter as I discuss the
EncapsulatedInvoke sample application.

There are several advantages to this type of interface:

 It is database neutral and will work with any database that supports ADO.NET
 Performance is usually high because the DAL can use direct ADO.NET concepts
 The interface is strongly-typed and that helps make the code more readable and
maintainable

Some business objects contain or interact with data from multiple tables or data entities. In that
case, the data access invocation code will call methods on multiple DAL objects.

Data Transfer Objects and Methods


The data transfer object (DTO) design pattern is commonly used to define interfaces for
components that accept and return data. A data transfer object is an object composed of public
read-write properties and no other behaviors. A DTO is a container for strongly typed data.
Here’s an example of a DTO that contains person data:
public class PersonDto
{
public int Id { get; set; }
public string FirstName { get; set; }

Using CSLA 4: Data Access Page 83


Rev 1.0
public string LastName { get; set; }
}

Every instance of PersonDto is composed of public read-write properties that provide strongly
typed access to the data.
Objects designed this way are for data transfer because they are easily serialized into XML, JSON,
or other formats. And XML, JSON, and other formatted data can be easily deserialized into a DTO.
This is because reflection or dynamic property invocation can be used to get and set every property
value.
This is entirely unlike a typical business domain object, where some properties are read-only,
and most properties have authorization and business rules that may prevent property values from
being read or set by a serialization component.
Here’s an example of a data access interface that uses DTOs:
public interface IPersonDal
{
List<PersonDto> Fetch();
PersonDto Fetch(int id);
void Insert(PersonDto data);
void Update(PersonDto data);
void Delete(int id);
}

Notice that the methods are similar to the data reader example, and include support for reading,
inserting, updating, and deleting data. Instead of using a data reader, this interface uses the DTO
type or a list of the DTO type.
I will demonstrate implementations of this interface later in the chapter as I discuss the
EncapsulatedInvokeDto sample application.

This type of interface is more abstract than the data reader approach, because it completely
avoids the use of any ADO.NET data types. There is nothing in this interface that requires the
concrete DAL implementations to use ADO.NET. If you are building a concrete DAL that doesn’t use
a database, the DTO approach is often a better solution than using a data reader. Examples of non-
database DAL implementations include:

 Calling a REST or SOAP service


 Storing data in a file on disk (text, XML, etc.)
 Interacting with an Excel spreadsheet file, or similar complex data files
 Calling a mainframe or minicomputer through a custom API

You can use the DTO approach when building a concrete DAL that does use a database too. The
result is that the DTO approach can work with nearly any DAL you can imagine, while the data
reader approach is generally more useful for DAL implementations that work against a database
supported by ADO.NET.
The primary advantage of the DTO approach is the higher level of abstraction. The primary
drawback to the DTO approach is that it requires more code, and usually, more overhead.

Using CSLA 4: Data Access Page 84


Rev 1.0
You must define every DTO class, often duplicating the properties defined in the business classes
and possibly in the data entity types from ADO.NET EF or other data technologies. Although the
code in a DTO is trivial code, it does take time to create and maintain.
There’s also some extra overhead when compared to the data reader approach. Data must be
read from the database (often using a data reader), and loaded into the DTO objects. The DTO
objects are then returned from the DAL, and the data is loaded into the properties of the business
objects. When compared to the direct use of a data reader, this involves an extra step to copy the
data in memory from the DTO to the business object.

Including Metastate in the DTO


There is one alternative to the DTO-based IPersonDal interface discussed in the previous section.
That interface defined separate Insert and Update methods, with the assumption that the DTO
contained only entity state data, and no metastate data.
It is possible to include metastate in the DTO implementations. For example:
public class PersonDto
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public bool IsNew { get; set; }
public bool IsDeleted { get; set; }
}

If these values are included in the DTO, then the interface doesn’t need separate Insert and
Update methods, and even the Delete method can be eliminated:
public interface IPersonDal
{
List<PersonDto> Fetch();
PersonDto Fetch(int id);
void Update(PersonDto data);
}

The reason the Insert and Delete methods are no longer required is that the implementation of
the Update method can now use the IsNew and IsDeleted properties from the DTO to determine
what kind of action is required:
public void Update(PersonDto data)
{
if (data.IsDeleted)
{
if (!data.IsNew)
{
// delete data
}
data.Id = -1; // reset primary key value
}
else if (data.IsNew)
{
// insert data
// set data.Id to database-generated value
}
else
{
// update data
}
}

Using CSLA 4: Data Access Page 85


Rev 1.0
Whether the DAL interface has explicit methods, or the metastate is embedded in the DTO, you
can see how the concept of saving or updating an entity results in the appropriate Insert, Update, or
Delete operation.

Exceptions in .NET
The data portal is designed with the idea that when a data operation fails the result is an exception.
One thing you should consider when building pluggable DAL components, is that exceptions are
part of the interface.
If an insert operation occurs because of a duplicate key or other data integrity violation, the
ADO.NET provider for the database will throw an exception. The exception thrown by SQL Server
will be different from that for Oracle or other database providers.
At some level in your application, your code will need to catch and handle this exception. Many
exceptions flow back to the client, possibly to the Interface Control layer. Ideally, the code in that
layer won’t need to catch every possible type of exception from every database your application
might use.
To avoid that problem, you may choose to define your own exception types for each possible
failure condition. In your concrete DAL implementations, you can then handle any exceptions
specific to each database provider and rethrow your custom exception type. This helps ensure that
only your custom exceptions flow up to higher layers in the application.
Here’s an example exception class for the .NET platform:
[Serializable]
public class DataNotFoundException : Exception
{
public DataNotFoundException(string message, Exception innerException)
: base(message, innerException)
{ }

protected DataNotFoundException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base(info, context)
{ }

[SecurityPermission(
SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.SerializationFormatter)]
[SecurityPermission(
SecurityAction.Demand, Flags = SecurityPermissionFlag.SerializationFormatter)]
public override void GetObjectData(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
{
base.GetObjectData(info, context);
}
}

Exception classes must be serializable.


Making an exception class serializable requires a little more coding that for most classes,
because the Exception base class explicitly implements the ISerializable interface. At a
minimum, this means that you must implement a special constructor like the one shown in the
example.

Using CSLA 4: Data Access Page 86


Rev 1.0
If your custom exception type includes any extra fields beyond those defined by the Exception
base class, you must also implement custom deserialization code in that constructor, and custom
serialization code in the GetObjectData method.
While a complete discussion on creating custom exception types is outside the scope of this
book, this example code demonstrates the minimum requirements for any exception class.

Exceptions in Silverlight and WP7


As I discussed earlier in this book, exceptions are not serializable in Silverlight or WP7, and .NET
server-side exceptions are not directly returned to a Silverlight client application through the data
portal.
When an exception occurs on the server, the Silverlight data portal throws a
DataPortalException on the client. This DataPortalException object includes an ErrorInfo
property that contains a copy of the server-side exception information.
The Silverlight data portal converts all server-side exceptions into a WcfErrorInfo object for
return to the client. The WcfErrorInfo type is similar to the .NET Exception type, providing the
property values listed in blah.
The data portal uses the original exception object graph to create a WcfErrorInfo object graph
that contains as much of the original information as possible. This information is then returned to
the client application so it is available through the ErrorInfo property of the client-side
DataPortalException object.

As a result, any custom exceptions you create and use in your DAL implementation will not be
directly returned to a Silverlight client, but the data contained within the exception will be available
to client-side code.

Dynamic Loading Options


One reason for implementing a separate Data Access layer is to enable the concept of a “pluggable
DAL”, where different DAL implementations can be loaded at runtime based on configuration or
other information.
This implies that your application has some way to dynamically load the correct DAL
implementation at runtime. There are many different ways to accomplish this goal, including the
use of inversion of control, dependency injection, and provider patterns. You can also use the
Managed Extensibility Framework (MEF) technology built into .NET in the
System.ComponentModel.Composition namespace.

For example, the data portal uses a provider pattern to dynamically load the appropriate object
factory types by default. As I discussed earlier in this book, the factory loader component
dynamically loads the correct type for each object factory, and creates instances of the factory
objects as needed.
You can also choose to implement your own provider pattern, or you might use an inversion of
control (IoC) framework and container to dynamically load your DAL types. Examples of IoC
frameworks include the Unity framework from Microsoft Patterns and Practices, and the open
source Castle Winsor project.

Using CSLA 4: Data Access Page 87


Rev 1.0
A complete discussion of IoC, dependency injection, MEF, and similar technologies is outside the
scope of this book. You can find a lot of information about these design patterns, frameworks, and
technologies on MSDN and from many other books and web sites.
I will demonstrate the implementation of a simple provider pattern in the EncapsulatedInvoke
and EncapsulatedInvokeDto samples. I will demonstrate how the dynamic loading of object factory
types work when I discuss the FactoryImplementation sample.
Before I do that I’ll demonstrate an implementation of the provider pattern and discuss how I
typically implement a mock in-memory “database”.

Mock Database Implementation


One of the primary reasons for creating a pluggable DAL is to make it easier to create a “mock
database” for testing purposes. Having a mock database is useful in two ways.

1. It allows for easier testing of your business objects

2. It ensures that your pluggable DAL is really pluggable

When testing business objects, you need to be able to load each object graph with known values
so you can perform tests against those values. Although it is possible to re-initialize a real SQL
database before each test run, it is far easier to use a mock database that automatically initializes
each time it is used. Additionally, you can avoid much of the configuration complexity that often
comes with using a physical database, because the mock database is usually an in-memory
construct.
Using a mock database also ensures that you create at least two DAL implementations. This
makes it harder to make accidental implementation choices that prevent the DAL from being
pluggable.
When building a pluggable DAL, it is extremely easy to take implementation shortcuts or make
other mistakes that eventually prevent the application from swapping from one DAL
implementation to another. The only guaranteed way to prevent such mistakes is to create at least
two DAL implementations from the start of the project. Creating a DAL for your real database and
for your mock database achieves this goal.

Creating the Mock Database


I typically create a mock database using a simple static class, where each property of the class
represents a table. For example:
public static class MockDb
{
public static List<PersonData> Persons { get; private set; }
public static List<CategoryData> Categories { get; private set; }
public static List<SkillData> Skills { get; private set; }
public static List<OrderData> Orders { get; private set; }
public static List<OrderLineItemData> OrderLineItems { get; private set; }
public static List<OrderLineItemPersonData> OrderLinePersons { get; private set; }
}

Each “table” is a List<T> where T is a simple entity type containing public read-write properties
that represent each column of data. For example:
Using CSLA 4: Data Access Page 88
Rev 1.0
public class CategoryData
{
public int Id { get; set; }
public string Category { get; set; }
}

Finally, it is necessary to load the mock database with known data values. This initialization
process should be consistent every time to enable business object tests to be written against these
known values. You can hard-code the values, or load them from a file, or some other source.
I typically load the values in the static constructor of the class containing the “table
definitions”. For example, here’s the code that loads the Categories table:
static MockDb()
{
Categories = new List<CategoryData>
{
new CategoryData { Id = 0, Category = "Misc" },
new CategoryData { Id = 1, Category = "Employee" },
new CategoryData { Id = 2, Category = "Vendor" },
new CategoryData { Id = 3, Category = "Customer" }
};

This creates the list object, and populates it with a set of new entity objects containing hard-
coded values for testing.

Using the Mock Database


Once the mock database has been defined, and is initialized in its static constructor, it can be
accessed using LINQ to Objects.
For example, the following query retrieves a specific row from the Persons table based on the Id
property:
var result = MockDb.MockDb.Persons.Where(r => r.Id == id).First();

In this example, I’m using the First method, and that will result in an exception if the row is not
found. You may also choose to implement fetch actions so they don’t immediately throw a “key not
found” exception, in which case you would use the FirstOrDefault method.

The behavior of each mock DAL action should exactly match the behavior of the real
DAL action.

If the real DAL throws exceptions when the row isn’t found, the mock DAL should also throw an
exception. If the real DAL doesn’t throw an exception, then the mock DAL shouldn’t throw an
exception either.
An insert action is simply a matter of creating a new entity object, populating it with values, and
adding it to the table. For example:
var newId = MockDb.MockDb.Persons.Max(r => r.Id) + 1;
var item = new MockDb.PersonData { Id = newId, FirstName = firstName, LastName = lastName };
MockDb.MockDb.Persons.Add(item);

To implement an update action, the existing row must be found, and the existing values
updated. For example:

Using CSLA 4: Data Access Page 89


Rev 1.0
var item = MockDb.MockDb.Persons.Where(r => r.Id == id).First();
item.FirstName = firstName;
item.LastName = lastName;

Finally, the delete action finds the existing row and removes it from the list:
var item = MockDb.MockDb.Persons.Where(r => r.Id == id).FirstOrDefault();
if (item != null)
MockDb.MockDb.Persons.Remove(item);

The examples I’m showing here demonstrate how to get, insert, update, and delete data in an in-
memory mock database. You will use similar code to create the mock DAL implementations that use
the mock database.
In the next chapter, I will move on to discuss the implementation of the encapsulated invoke and
factory implementation data access models.

Using CSLA 4: Data Access Page 90


Rev 1.0
Chapter 5:
Encapsulated Invocation Model
In the encapsulated invocation model, the data portal is responsible for creating instances of the
business objects, and invoking DataPortal_XYZ or Child_XYZ methods in each business object.
Those methods implement the data access invocation concept, meaning that they contain the code
that invokes the Data Access layer.
The data access code is implemented in separate assemblies. To support a pluggable DAL, there
is typically one central assembly that contains the interface definitions and common data types
used by all concrete DAL implementations.
Figure 10 illustrates the assemblies typically involved in implementing a pluggable DAL.

Figure 10. Assemblies involved in implementing a pluggable DAL


The arrows represent references. You can see how the DAL interface assembly is referenced by
all other assemblies. This is necessary because this is the assembly that defines the interface
implemented by each concrete DAL, and used by the data access invocation code.
The data access invocation code is in the business library and is implemented in the
DataPortal_XYZ and Child_XYZ methods in the business classes.

Each concrete DAL project implements the interfaces defined in the DAL interface assembly. One
concrete DAL might interact with SQL Server, another with Oracle, and still another might use hard-
coded mock data for testing purposes. Because they all implement the same interfaces, each
concrete DAL is interchangeable with the others, and can be dynamically loaded at runtime.
The DAL interface assembly often contains the provider pattern or IoC implementation
necessary to dynamically load the appropriate concrete DAL assembly at runtime. This is usually
done based on configuration values in the application’s web.config or app.config file.
In the EncapsulatedInvoke and EncapsulatedInvokeDto sample applications, I am using a
provider pattern that uses an entry in the application’s config file to determine which DAL
implementation to load at runtime. Both samples include a database implementation that uses a
SQL Server Compact Edition (SqlCe) implementation using direct ADO.NET data access. They also
include an implementation using the ADO.NET Entity Framework to interact with a SQL Server
Using CSLA 4: Data Access Page 91
Rev 1.0
Express database. And they include a mock DAL implementation that operates against simple hard-
coded values in memory.
I will walk through the entire persistence process, including implementation of the Create, Fetch,
Update, Delete, and Execute operations. Before I do that, I’ll discuss the DAL provider
implementation in more detail.

Provider Pattern Implementation


As I discussed earlier, there are several design patterns you can use to implement a pluggable DAL
model. In the EncapsulatedInvoke and EncapsulatedInvokeDto samples I am using a provider
pattern, so each DAL implementation is a provider, and there’s one coordination point that is
responsible for loading the correct provider based on configuration.
Each of the sample solutions includes a DataAccess project.

Figure 11. DataAccess project contains DAL interface definitions and loader
This project contains the interface definitions and DTO implementations used by the concrete
DAL implementations. The project also contains the code that dynamically loads the concrete DAL
provider based on the application’s configuration.
When a DataPortal_XYZ method needs to interact with the data store, it asks the DalFactory
class (from the DataAccess project) to return an object that knows how to create concrete
implementations of the required DAL types. That DAL type “manager” object can then be used to
get objects that provide a specific implementation of each DAL action.
Figure 12 illustrates how the DataPortal_XYZ method uses the DalFactory to get a DalManager.
The DalManager then provides the DataPortal_XYZ method with a reference to a PersonDal object
that is a concrete implementation of the IPersonDal interface.

Using CSLA 4: Data Access Page 92


Rev 1.0
Figure 12. DalFactory dynamically loading a provider.
In the example from Figure 12, if a PersonEdit object needs to retrieve data for a specific
person, it needs an implementation of the IPersonDal type:
var dalManager = DataAccess.DalFactory.GetManager();
var dal = dalManager.GetProvider<DataAccess.IPersonDal>();

The first step is to call the GetManager method on the DalFactory class to get an object that
knows how to return the appropriate implementations of each DAL interface type defined in the
DataAccess assembly. Remember from Figure 10 that the business library and each DAL provider
reference the DataAccess assembly. That assembly provides the definitions for all DAL types used
by the rest of the code.

The DalFactory Implementation


The DalFactory class in the DataAccess project is responsible for dynamically loading the
appropriate DAL provider assembly based on the current application configuration. This work is
done in a static method named GetManager:
public static class DalFactory
{
private static Type _dalType;

public static IDalManager GetManager()


{
if (_dalType == null)
{
var dalTypeName = ConfigurationManager.AppSettings["DalManagerType"];
if (!string.IsNullOrEmpty(dalTypeName))
_dalType = Type.GetType(dalTypeName);
else
throw new NullReferenceException("DalManagerType");
if (_dalType == null)
throw new ArgumentException(string.Format("Type {0} could not be found", dalTypeName));
}
return (IDalManager)Activator.CreateInstance(_dalType);
}
}

Using CSLA 4: Data Access Page 93


Rev 1.0
The GetManager method uses the .NET configuration system to get a DalManagerType value from
the app.config or web.config file. That value is the full type name of the class that implements the
IDalManager interface in the assembly containing the DAL provider implementation.

Here’s an example of the configuration:


<appSettings>
<add key="DalManagerType" value="DataAccess.Mock.DalManager,DataAccess.Mock"/>
<!--<add key="DalManagerType" value="DataAccess.SqlCe.DalManager,DataAccess.SqlCe"/>-->
<!--<add key="DalManagerType" value="DataAccess.SqlEf.DalManager,DataAccess.SqlEf"/>-->
</appSettings>

The GetManager method uses the GetType method of the Type class from .NET to create a Type
object based on that full type name. That Type object is cached so this work only occurs once per
execution of the application.
The value of the _dalType field is then used to create an instance of the IDalManager
implementation each time the GetManager method is called.

Implementing the IDalManager Interface


Each concrete DAL provider assembly must have one class that implements the IDalManager
interface:
public interface IDalManager : IDisposable
{
T GetProvider<T>() where T: class;
}

This DAL manager object is responsible for returning DAL provider objects that implement each
of the interfaces defined in the DataAccess assembly.
There are several ways you might implement the GetProvider method, including hard coding
the results in a big switch statement. In my sample applications I chose to use reflection to get the
type name of the interface, and to then dynamically rewrite that type name so “IPersonDal”
becomes “MyProvider.PersonDal”:
private static string _typeMask = typeof(DalManager).FullName.Replace("DalManager", @"{0}");

public T GetProvider<T>() where T : class


{
var typeName = string.Format(_typeMask, typeof(T).Name.Substring(1));
var type = Type.GetType(typeName);
if (type != null)
return Activator.CreateInstance(type) as T;
else
throw new NotImplementedException(typeName);
}

The _typeMask field gets the full type name of the current type: MyProvider.DalManager. The
“DalManager” class name is replaced with {0} to create a string format mask: “MyProvider.{0}”.
In the GetProvider<T> method, the type name of T is retrieved. This will be a value such as
IPersonDal or ICategoryDal. The “I” prefix is removed, and the resulting value is then applied to
the _typeMask value to get a resulting value such as “MyProvider.PersonDal”.

Using CSLA 4: Data Access Page 94


Rev 1.0
The GetType method from the Type class is then used to dynamically load the Type object for the
required type name, and the CreateInstance method of the Activator class is used to create an
instance of the type. That new object is returned as the result of the method.
The constraint with this approach is that each class that implements an interface must be named
the same as the interface, just without the “I” prefix.

Implementing the IDisposable Interface


Notice that the IDalManager interface derives from the .NET IDisposable interface. This means
that all the DAL manager objects implemented by DAL providers will be disposable objects.
The reason for this is that any object that contains a disposable object must be disposable too. I
am assuming that some DAL implementations will use ADO.NET database connection objects, and
they are always disposable.
For example, the DataAccess.SqlCe provider interacts with a SQL Server Compact Edition
database, and so uses a SqlCeConnection object. That connection object is opened and disposed by
the DalManager class in the SqlCe provider:
public ConnectionManager<SqlCeConnection> ConnectionManager { get; private set; }

public DalManager()
{
ConnectionManager = ConnectionManager<SqlCeConnection>.GetManager("LocalDb");
}

public void Dispose()


{
ConnectionManager.Dispose();
ConnectionManager = null;
}

This implementation uses the ConnectionManager class from Csla.Data to ensure any already-
open connection is automatically reused. I discussed the ConnectionManager type in Chapter 3.
When the DalManager object is disposed, it disposes the ConnectionManager object it contains.
And the ConnectionManager object disposes the SqlCeConnection object it contains when there
are no more users of that connection.
Similarly, the DataAccess.SqlEf provider implements the same behavior, but using an
ObjectContextManager object:
public ObjectContextManager<SqlDbEntities> ConnectionManager { get; private set; }

public DalManager()
{
ConnectionManager = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities");
}

public void Dispose()


{
ConnectionManager.Dispose();
ConnectionManager = null;
}

Again, to ensure that the database connection is held open and reused by all data access code,
the DalManager object creates an ObjectContextManager in its constructor, and disposes that
object when the DalManager object is disposed.
Using CSLA 4: Data Access Page 95
Rev 1.0
Implementing a Data Reader DAL Interface
Each DAL provider assembly contains classes that implement every DAL interface defined in the
DataAccess assembly. Figure 13 is an example of a project that implements a concrete provider of
the interfaces defined in Figure 11.

Figure 13. Example SqlCe provider project.


Notice the DalManager class that implements the IDalManager interface. And notice that each
DAL interface defined in the DataAccess assembly has a corresponding class in this provider project.
For example, the CategoryDal class implements the ICategoryDal interface:
public class CategoryDal : ICategoryDal
{
public System.Data.IDataReader Fetch()
{
}

public int Insert(string name)


{
}

public void Update(int id, string name)


{
}

public void Delete(int id)


{
}
}

Every DAL provider will provide an implementation of ICategoryDal. The specific code in each
provider may be very different, but they are interchangeable as long as they all implement the
same interface and provide consistent behaviors.
“Consistent behaviors” means that each implemention throws exceptions and returns results in
a consistent manner. If one Fetch method implementation throws an exception when no data is
found, then all Fetch method implementations must throw an exception when no data is found. If
one Delete method implementation silently fails if there’s no data to delete, then all Delete
method implementations must silently fail in that situation.

Using CSLA 4: Data Access Page 96


Rev 1.0
Implementing a DTO-Based DAL Interface
The same concepts apply to a DTO-based DAL interface. The DataAccess assembly defines the DAL
interface types and data transfer object (DTO) types used by the business classes and by each DAL
provider implementation.
This means that each DAL provider project must provide implementations of each DAL interface
defined in the DataAccess assembly, as shown earlier in Figure 13.
The DalManager class implements the IDalManager interface in the same way I discussed earlier.
Even though DTOs are used to pass values between the DataPortal_XYZ methods and the DAL
provider code, the DalManager is a disposable object, because I assume it is maintaining an open
connection to the database during the data access process.
Each DAL interface defined by the DataAccess assembly is implemented in every DAL provider
implementation. For example, the CategoryDal class implements the ICategoryDal interface:
public class CategoryDal : ICategoryDal
{
public List<CategoryDto> Fetch()
{
}

public void Insert(CategoryDto data)


{
}

public void Update(CategoryDto data)


{
}

public void Delete(int id)


{
}
}

Notice how the Fetch method returns a List<CategoryDto> instead of an IDataReader, and
how the Insert and Update methods accept a CategoryDto object instead of a list of parameters. In
some ways this DAL interface is cleaner than with the data reader example, but it does require the
implementation of a DTO type for every data entity.
As with the data reader based DAL, it is important that every DAL provider provide consistent
behaviors in terms of returning data or throwing exceptions. Even though the Mock, SqlEf, and
SqlCe implementations are very different, they all provide the same behaviors when invoked.

Using the ADO.NET Entity Framework


The EncapsulatedInvoke and EncapsulatedInvokeDto solutions include projects named
DataAccess.SqlEf. This project implements a DAL provider using the ADO.NET Entity Framework
(EF) to interact with a SQL Server Express database.
It is important to understand that every DAL provider must conform to the same interface.
This means the DataAccess.SqlEf implementation in the EncapsulatedInvoke solution uses EF
to interact with the database, but it still implements all DAL methods according to the interfaces
defined in the DataAccess project. The results of each EF query are wrapped in an IDataReader so
the results meet the requirements of the interface.
Using CSLA 4: Data Access Page 97
Rev 1.0
For example, here’s a Fetch method from that provider:
public System.Data.IDataReader Fetch()
{
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var data = from r in ctx.ObjectContext.CategoryTables
select r;
return new ListDataReader<CategoryTable>(data);
}
}

The database access is handled by EF using a standard object context, and the results from the
EF query are used to populate a ListDataReader object. You can find the ListDataReader class in
the SqlEf project.
Similarly, the SqlEf provider implementation in the EncapsulatedInvokeDto solution must
conform to the DTO-based interface defined by the interfaces in that solution’s DataAccess project.
Here’s an example of a Fetch method in this implementation:
public List<CategoryDto> Fetch()
{
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var data = from r in ctx.ObjectContext.CategoryTables
select new CategoryDto { Id = r.Id, Category = r.Category };
return data.ToList();
}
}

The EF query is very similar, but instead of wrapping a list of entity objects in an IDataReader,
this implementation puts the data from the query into a list of the DTO types defined in the
DataAccess project.

It is possible to define a DAL interface that is based on EF entity types. If you do this, all your DAL
implementations will be required to conform to that interface. This can be challenging, since the
default behavior of the EF model designer tooling will create different entity types each time you
generate an entity model from a database.
For example, if you have two identical databases, one in SQL Server and another in Oracle, you’ll
end up (by default) with two similar entity models, each with different entity types. This means they
can’t conform to the same common type scheme and therefore can’t be pluggable DAL
implementations.
You can use model-first concepts supported by EF, where you manually create a model and then
map it to each database. And future versions of EF are planned to support something called code-
first design, where you manually create .NET classes to contain the data, and then map each of
those class types to tables in the database.
The model-first and code-first options require more manual effort, but do enable the idea of
multiple DAL implementations that conform to an interface defined by common entity types. In
both of these scenarios, your common model or entity types will be located in a shared assembly
that is referenced by all individual DAL provider implementations.
The provider model I just discussed will be used as I discuss how to implement persistence using
the encapsulated invoke model with data reader and DTO style provider interfaces. I’ll now
Using CSLA 4: Data Access Page 98
Rev 1.0
demonstrate persistence for each business object stereotype, starting with the editable root
stereotype.

Editable Root Object Persistence


The PersonEdit business class is an implementation of an editable root stereotype. You can find
this type in the Library.Net projects in the EncapsulatedInvoke and EncapsulatedInvokeDto
solutions.
I am starting with the editable root stereotype, because this stereotype covers the primary data
access actions (create, fetch, insert, update, and delete). Most of the other stereotypes are
variations on these concepts, or are subsets of these actions.
The EncapsulatedInvoke solution is an implementation of the encapsulated invoke data access
model that uses an IDataReader interface approach. The EncapsulatedInvokeDto solution provides
the same functionality and architecture, but it uses a DTO-based interface to the DAL.

DataReader Interface
The DataAccess project in the EncapsulatedInvoke solution includes the IPersonDal interface:
public interface IPersonDal
{
IDataReader Fetch();
IDataReader Fetch(int id);
int Insert(string firstName, string lastName);
void Update(int id, string firstName, string lastName);
void Delete(int id);
}

This interface defines the data access operations for the person data entity. This DAL interface is
used to persist the PersonEdit editable root object, and the PersonList read-only list object (which
I’ll discuss later in this chapter).
The DataAccess.Mock, DataAccess.SqlCe, and DataAccess.SqlEf projects contain PersonDal
classes. Each class implements this IPersonDal interface in a different way, but with consistent
behaviors.
Each data access action includes data access invocation and data access implementation.
Because these samples are following the encapsulated invoke model, the data access invocation is
in DataPortal_XYZ or Child_XYZ methods contained in each business class. The data access
implementation is located in the Mock, SqlEf, and SqlCe DAL provider projects.

Create Operation
The create action starts with the NewPersonEdit factory methods in the PersonEdit class:
#if SILVERLIGHT
public static void NewPersonEdit(EventHandler<DataPortalResult<PersonEdit>> callback)
{
DataPortal.BeginCreate<PersonEdit>(callback, DataPortal.ProxyModes.LocalOnly);
}
#else
public static void NewPersonEdit(EventHandler<DataPortalResult<PersonEdit>> callback)
{
DataPortal.BeginCreate<PersonEdit>(callback);
}
Using CSLA 4: Data Access Page 99
Rev 1.0
public static PersonEdit NewPersonEdit()
{
return DataPortal.Create<PersonEdit>();
}
#endif

These methods invoke the client-side data portal to create and initialize a new instance of the
business class. The asynchronous method is slightly different between Silverlight and .NET, and the
synchronous method is only available on .NET.
The client-side data portal invokes the server-side data portal based on the client configuration.
The result is that the DataPortal_Create method in the PersonEdit class is invoked. In this
example I’m showing the Silverlight and .NET implementations of the method:
#if SILVERLIGHT
public override void DataPortal_Create(
Csla.DataPortalClient.LocalProxy<PersonEdit>.CompletedHandler handler)
{
using (BypassPropertyChecks)
{
Id = -1;
}
base.DataPortal_Create(handler);
}
#else
[RunLocal]
protected override void DataPortal_Create()
{
using (BypassPropertyChecks)
{
Id = -1;
}
base.DataPortal_Create();
}
#endif

In both implementations, this method initializes the new object with default values. The base
implementation of DataPortal_Create is then invoked. This base implementation runs all business
rules associated with the object and its properties. Usually this is desirable, because required fields
are marked as invalid, ensuring that an empty object can’t be saved with invalid data.
The NewPersonEdit factory method for Silverlight sets the data portal’s proxy mode to
LocalOnly, and that prevents the data portal from attempting to make a cross-network call to run
the DataPortal_Create method. This is good, because this DataPortal_Create method doesn’t
interact with the database or DAL, so the code can run on the client or server. It is more efficient to
have the code run on the client.
In the .NET implementation, notice the use of the RunLocal attribute. Again, because this
method doesn’t interact with the database or DAL, this code can run on the client or server. The
RunLocal attribute prevents the .NET data portal from attempting to make a cross-network call to
run this method.
If your DataPortal_Create method does interact with the DAL to load default values for the new
object, you should not use the LocalOnly proxy mode in Silverlight or the RunLocal attribute in
.NET. That will allow the data portal to make the appropriate cross-network call so the
DataPortal_Create method runs on an application server (in a 3- or 4-tier deployment) where it
can access the database.
Using CSLA 4: Data Access Page 100
Rev 1.0
In any case, the data portal automatically ensures that this new object’s metastate is set
correctly, so IsNew is true, IsDirty is true, and IsValid is true or false depending on the
business rules defined for the object.

Fetch Operation
The fetch action starts with the GetPersonEdit factory methods in the PersonEdit class:
public static void GetPersonEdit(int id, EventHandler<DataPortalResult<PersonEdit>> callback)
{
DataPortal.BeginFetch<PersonEdit>(id, callback);
}

#if !SILVERLIGHT
public static PersonEdit GetPersonEdit(int id)
{
return DataPortal.Fetch<PersonEdit>(id);
}
#endif

These methods invoke the client-side data portal to create an instance of the business class and
load that object with pre-existing data from the database. The client-side data portal invokes the
server-side data portal based on the client configuration. The server-side data portal then invokes
the DataPortal_Fetch method of the PersonEdit object:
private void DataPortal_Fetch(int id)
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IPersonDal>();
using (var data = dal.Fetch(id))
{
data.Read();
using (BypassPropertyChecks)
{
Id = data.GetInt32(data.GetOrdinal("Id"));
FirstName = data.GetString(data.GetOrdinal("FirstName"));
LastName = data.GetString(data.GetOrdinal("LastName"));
}
}
}
}

The code in this method gets the DAL manager object from the DalFactory class. The DAL
manager object is wrapped in a using block so it is properly disposed when the action is complete.
The GetProvider method of the DAL manager is called to get an instance of the IPersonDal
provider. Notice that this code doesn’t know or care what provider is returned, only that some valid
implementation of IPersonDal is made available.
The Fetch method defined by IPersonDal returns an IDataReader object. That object is used to
retrieve the data from the database. The assumption is that the DAL Fetch method has done
whatever was necessary to create and return an open data reader containing the requested data.
You may choose to wrap the Fetch result in a SafeDataReader so it can automatically remove
null data values returned from the database. I discussed the SafeDataReader type in Chapter 3.
Because it implements the IDataReader interface, you can choose to return a SafeDataReader from
the DAL Fetch method itself, or wrap the Fetch method result in the DataPortal_Fetch method.
For example:
Using CSLA 4: Data Access Page 101
Rev 1.0
using (var data = new Csla.Data.SafeDataReader(dal.Fetch(id)))

The Read method is called on the data reader to move to the first row of returned data.
Next, the code enters a using block for the BypassPropertyChecks object of the business object.
This suppresses business and authorization rule checking for the object’s properties, meaning that
the properties can be set to the values from the data reader without incurring the overhead and
potential failure scenarios that could occur if the rules were run normally.
In many applications, the data from the database is trusted, and so there’s no need to run the
business rules against data that was just retrieved from the database. That’s the case in this sample
implementation.
In other situations, you may feel the need to run the business rules after the object has been
loaded with data from the database. If you do need to run the business rules once the object has
been loaded with data, you will need to manually call the CheckRules method of the
BusinessRules object at the bottom of the DataPortal_Fetch method. I recommend that this be
the last line of code in the method:
BusinessRules.CheckRules();

The specific DAL implementation varies depending on the DAL provider.

ADO.NET Provider
The DataAccess.SqlCe provider implements the Fetch method like this:
public System.Data.IDataReader Fetch(int id)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
var cm = ctx.Connection.CreateCommand();
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "SELECT Id,FirstName,LastName FROM Person WHERE Id=@id";
cm.Parameters.Add("@id", id);
return cm.ExecuteReader();
}
}

The ConnectionManager type from Csla.Data is used to get the existing database connection. As
I discussed earlier in this chapter, the database connection is already open, because the DalManager
object will have opened it before any DAL provider methods are invoked.
The database connection is then used to create a command object for the query, and that
command object is executed to return an IDataReader object as required by the IPersonDal
interface.

Entity Framework Provider


The DataAccess.SqlEf provider uses an EF query to retrieve the data from the database:
public System.Data.IDataReader Fetch(int id)
{
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var data = from r in ctx.ObjectContext.People
where r.Id == id
select r;
return new ListDataReader<Person>(data);
Using CSLA 4: Data Access Page 102
Rev 1.0
}
}

The query runs against the People collection of the EF ObjectContext object to retrieve a list of
entity objects that match the where clause.
Because the IPersonDal interface requires that the Fetch method return an IDataReader, the
result of the EF query is wrapped in a ListDataReader object that implements the IDataReader
interface. The ListDataReader class can be found in the DataAccess.SqlEf project.

Mock Provider
The DataAccess.Mock provider has a different implementation that uses a LINQ to Objects query:
public System.Data.IDataReader Fetch(int id)
{
return new ListDataReader<MockDb.PersonData>(MockDb.MockDb.Persons.Where(r => r.Id == id));
}

The LINQ Where method filters the results based on the id parameter value, and those results
are wrapped in a ListDataReader object.
The ListDataReader class can be found in the DataAccess.Mock project. It is a type I use for
creating mock DAL implementations. The ListDataReader type implements the IDataReader
interface, using the contents of a list, collection, or LINQ query result as the data source.
At this point you should understand how the client-side factory methods invoke the data portal,
and the data portal then invokes the DataPortal_Fetch method. And you should understand how
the DataPortal_Fetch method uses the DalFactory to get an IDalManager object for the DAL
provider. That DAL manager provides access to an implementation of the DAL type (IPersonEdit in
this example) so the DataPortal_XYZ method can call its Fetch method. The results of the Fetch
method are used to load the business object with data. The Fetch method itself may be
implemented in various ways by different DAL providers, as long as all implementations conform to
the IPersonDal interface and provide consistent behaviors.

Insert Operation
When an editable root object is saved, the Save or BeginSave method invokes the client-side data
portal by calling its Update or BeginUpdate method. That client-side method invokes the server-side
data portal based on the client configuration, and the server-side data portal the invokes one of
three methods on the business object:

1. DataPortal_Insert

2. DataPortal_Update

3. DataPortal_DeleteSelf

As I’ve previously discussed, the data portal uses the business object’s IsNew and IsDeleted
metastate properties to determine which of these methods should be invoked.
The DataPortal_Insert method is responsible for inserting data from a new object into the
database by using the DAL implementation:

Using CSLA 4: Data Access Page 103


Rev 1.0
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_Insert()
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IPersonDal>();
using (BypassPropertyChecks)
{
Id = dal.Insert(FirstName, LastName);
}
}
}

Notice the use of the Transactional attribute. Most insert, update, and delete actions will be
transactional to ensure that database integrity is preserved.
As with the DataPortal_Fetch method, the first thing this method does is get the IDalManager
object from the DalFactory class. The specific IDalManager implementation returned is based on
the application configuration.
The DAL manager’s GetProvider method is then used to get the concrete implementation of the
IPersonDal interface, so the DAL Insert method can be invoked to perform the insert action.

It is important to notice that all use of the business object’s properties are contained in a using
block for the BypassPropertyChecks object. This prevents business and authorization rules from
being run as these properties are used.
Again, this code is independent of any specific DAL implementation, and the code in the
DataAccess.Mock, DataAccess.SqlEf, and DataAccess.SqlCe projects are quite different. You can
look at the Mock implementation in the code download.

ADO.NET Provider
Here’s the SqlCe implementation of the Insert method:
public int Insert(string firstName, string lastName)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "INSERT INTO Person (FirstName,LastName) VALUES (@firstName,@lastName)";
cm.Parameters.Add("@firstName", firstName);
cm.Parameters.Add("@lastName", lastName);
cm.ExecuteNonQuery();
cm.Parameters.Clear();
cm.CommandText = "SELECT @@identity";
var r = cm.ExecuteScalar();
var newId = int.Parse(r.ToString());
return newId;
}
}
}

This method gets the connection to the database, sets up a command object to do the insert,
and executes that command object against the database. The database generates a new unique Id
value for the inserted row.
Because this is a SqlCe database, retrieving the new Id value for the inserted row is a separate
step from the insert query. The command object’s ExecuteNonQuery method is used to perform the
Using CSLA 4: Data Access Page 104
Rev 1.0
insert, and then a second command is executed with the ExecuteScalar method to retrieve the
@@identity value from the database.

When using full SQL Server you would retrieve this new Id value by calling the SCOPE_IDENTITY
SQL method as part of the database query. So the CommandText would look like this:
"INSERT INTO Person (FirstName,LastName) VALUES (@firstName,@lastName);
SELECT SCOPE_IDENTITY()"

In that case, there would be only one execution of a command object, and that is done using the
ExecuteScalar method to perform the insert and retrieve the new Id value in one database call.

Entity Framework Provider


For comparison purposes, here’s the SqlEf implementation of the Insert method:
public int Insert(string firstName, string lastName)
{
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var data = new Person { FirstName = firstName, LastName = lastName };
ctx.ObjectContext.AddToPeople(data);
var count = ctx.ObjectContext.SaveChanges();
if (count == 0)
throw new InvalidOperationException("PersonDal.Insert");
return data.Id;
}
}

This method creates a new instance of the Person entity that was generated from the EF edmx
file. The properties of that entity object are loaded with data, and the object is added to the EF
ObjectContext object’s People collection. Then the changes to the ObjectContext are committed
by calling its SaveChanges method.
As part of the update process, EF automatically retrieves the new database-generated Id
property value and puts it into the entity. That is the value returned as the result of the Insert
method.

Update Operation
The DataPortal_Update method is responsible for updating data from an existing object into the
database. It is invoked by the server-side data portal in response to a Save or BeginSave method
call on the client.
Here’s the DataPortal_Update method from the PersonEdit class:
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_Update()
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IPersonDal>();
using (BypassPropertyChecks)
{
dal.Update(Id, FirstName, LastName);
}
}
}

Using CSLA 4: Data Access Page 105


Rev 1.0
The code is basically the same as for DataPortal_Insert, except the IPersonDal object’s Update
method is invoked, and it doesn’t return a new database-generated Id value.

ADO.NET Provider
The Update method in the PersonDal class from the SqlCe provider looks like this:
public void Update(int id, string firstName, string lastName)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "UPDATE Person SET FirstName=@firstName,LastName=@lastName WHERE Id=@id";
cm.Parameters.Add("@id", id);
cm.Parameters.Add("@firstName", firstName);
cm.Parameters.Add("@lastName", lastName);
var rowsAffected = cm.ExecuteNonQuery();
if (rowsAffected == 0)
throw new DataNotFoundException("Person");
}
}
}

As with the Insert method, this code gets the database connection, and then sets up and
executes a command object to perform the update action.

Entity Framework Provider


The SqlEf implementation is worth reviewing as well:
public void Update(int id, string firstName, string lastName)
{
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var person = new Person();
person.Id = id;
var entityKey = new EntityKey("SqlDbEntities.People", "Id", id);
person.EntityKey = entityKey;
ctx.ObjectContext.People.Attach(person);

person.FirstName = firstName;
person.LastName = lastName;
var count = ctx.ObjectContext.SaveChanges();
if (count == 0)
throw new InvalidOperationException("PersonDal.Update");
}
}

Updating data with EF can be done in a couple ways. The simplest, but less efficient approach
involves the following steps:

1. Query the database to retrieve the existing data entity

2. Set the entity object’s properties

3. Save changes to the entity with the ObjectContext object’s SaveChanges method

Although the code to implement that approach is simple, it means reading the data from the
database in order to do an update, so it involves two database interactions.
Using CSLA 4: Data Access Page 106
Rev 1.0
The implementation in the Update method shown here uses a slightly more complex, but also
more efficient approach. It involves the following steps:

1. Create a Person entity object

2. Set its Id property

3. Create an EntityKey object, and load it with the entity’s primary key information

4. Set the Person object’s EntityKey property to this new EntityKey object

5. Attach the Person entity object to the ObjectContext object’s People collection

6. Save changes by calling the ObjectContext object’s SaveChanges method

This approach requires more code, but only requires one database interaction to perform the
table update.

Deferred Delete Operation


The deferred delete action occurs when an editable object is saved and its IsDeleted property is
true. When the object is an editable root object the server-side data portal invokes the
DataPortal_DeleteSelf method on the business object.
If your business class also supports immediate deletion through the DataPortal_Delete
method, the DataPortal_DeleteSelf method will just call that DataPortal_Delete method:
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_DeleteSelf()
{
using (BypassPropertyChecks)
{
DataPortal_Delete(Id);
}
}

I’ll discuss immediate deletion later in this chapter, but for now it is enough to know that the
DataPortal_Delete method will invoke the Delete method on the DAL provider object.

If your business class doesn’t support immediate deletion, the DataPortal_DeleteSelf method
will invoke the delete action directly:
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_DeleteSelf()
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IPersonDal>();
using (BypassPropertyChecks)
{
dal.Delete(Id);
}
}
}

You can see how this code is similar to the Insert and Update methods. It gets the DAL provider
object and invokes the Delete method defined by the IPersonDal interace.
Using CSLA 4: Data Access Page 107
Rev 1.0
ADO.NET Provider
The SqlCe implementation of the Delete method looks like this:
public void Delete(int id)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "DELETE Person WHERE Id=@id";
cm.Parameters.Add("@id", id);
var rowsAffected = cm.ExecuteNonQuery();
if (rowsAffected == 0)
throw new DataNotFoundException("Person");
}
}
}

Like the Insert and Update methods, this implementation gets the database connection and
sets up a command object. The command object is executed to delete the data, throwing an
exception if there was no data to delete.
You should understand that a “delete” operation doesn’t necessarily need to delete any data. In
some applications a delete operation updates each row to set a “deleted flag” indicating that the
row of data is no longer active. Although this example does delete rows of data from the database,
you could implement the Delete method to perform an update of the existing row instead of
deleting any data.

Entity Framework Provider


The SqlEf implementation performs a database query to get the entity to delete, and then it
deletes that entity from the People collection (and therefore the table):
public void Delete(int id)
{
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var item = (from r in ctx.ObjectContext.People
where r.Id == id
select r).FirstOrDefault();
if (item == null)
throw new DataNotFoundException("Person");
ctx.ObjectContext.DeleteObject(item);
var count = ctx.ObjectContext.SaveChanges();
if (count == 0)
throw new InvalidOperationException("PersonDal.Delete");
}
}

Retrieving the entity in order to delete it is somewhat inefficient because it requires two
database interactions, but EF requires that the entity be retrieved so it can properly delete the
entity and any related data.

Immediate Delete Operation


Immediate deletion occurs when a client-side factory method is invoked on the business class to call
the client-side data portal’s Delete or BeginDelete method. For example, this method is in the
PersonEdit business class:
Using CSLA 4: Data Access Page 108
Rev 1.0
public static void DeletePersonEdit(int id)
{
DataPortal.Delete<PersonEdit>(id);
}

The client-side data portal invokes the server-side data portal, and it then invokes the
DataPortal_Delete method on the business object:
[Transactional(TransactionalTypes.TransactionScope)]
private void DataPortal_Delete(int id)
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IPersonDal>();
dal.Delete(id);
}
}

This method invokes the same DAL provider Delete method I discussed in the previous section
about deferred deletion.
At this point you should understand how to implement persistence for an editable root object
with a data reader based DAL implementation. I’ll now revisit the same editable root object
scenario, but with a DTO-based DAL implementation.

DTO Interface
The DataAccess project in the EncapsulatedInvokeDto solution includes the IPersonDal interface:
public interface IPersonDal
{
List<PersonDto> Fetch();
PersonDto Fetch(int id);
void Insert(PersonDto data);
void Update(PersonDto data);
void Delete(int id);
}

This interface defines the data access operations for the person data entity. This DAL interface is
used to persist the PersonEdit editable root object, and the PersonList read-only list object (which
I’ll discuss later in this chapter).
The DataAccess.Mock, DataAccess.SqlCe, and DataAccess.SqlEf projects contain PersonDal
classes. Each class implements this IPersonDal interface in a different way, but with consistent
behaviors.
Each data access action includes data access invocation and data access implementation.
Because these samples are following the encapsulated invoke model, the data access invocation is
in DataPortal_XYZ or Child_XYZ methods contained in each business class. The data access
implementation is located in the Mock, SqlEf, and SqlCe DAL provider projects.
Notice that the interface relies on a PersonDto type. This is the data transfer object type that
provides a consistent data contract for use by the business object and any DAL provider
implementations:
public class PersonDto
{
public int Id { get; set; }
public string FirstName { get; set; }

Using CSLA 4: Data Access Page 109


Rev 1.0
public string LastName { get; set; }
}

The DTO type defines properties for each value that must flow between the data access
invocation code and the data access implementation code. The type is defined in the DataAccess
project so it is available to the business classes and DAL provider implementations. Please refer
back to Figure 10 to see how the business library and all DAL provider assemblies reference the
DataAccess assembly.

As I discuss the data access actions and how they are implemented, I won’t repeat the discussion
from the data reader implementation. For example, the factory methods in the PersonEdit class
are unaffected by the DAL implementation choices and so I won’t repeat those methods here.

Create Operation
The create action is implemented exactly the same in as in the EncapsulatedInvoke solution.
Please refer to that earlier discussion for details.

Fetch Operation
In the fetch action the server-side data portal invokes the DataPortal_Fetch method on the
PersonEdit business object. This method invokes the DAL to get back a PersonDto object
containing the person data from the database:
private void DataPortal_Fetch(int id)
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IPersonDal>();
var data = dal.Fetch(id);
using (BypassPropertyChecks)
{
Id = data.Id;
FirstName = data.FirstName;
LastName = data.LastName;
}
}
}

The result of the Fetch method is a PersonDto object containing the data values from the
database. Those values are used to load the business object with data.
Notice that the object’s properties are set within a using block for the BypassPropertyChecks
object to suppress rule checking. As in the data reader implementation, if you need to run business
rules once the business object has been loaded with data, you should add an explicit call to the
CheckRules method of BusinessRules as the last line of code in the DataPortal_Fetch method.

The DataAccess.Mock DAL provider includes a PersonDal class that implements the IPersonDal
interface from the DataAccess assembly. Its Fetch method looks like this:
public PersonDto Fetch(int id)
{
var data = from r in MockDb.MockDb.Persons
where r.Id == id
select new PersonDto { Id = r.Id, FirstName = r.FirstName, LastName = r.LastName };
if (data.Count() == 0)
throw new DataNotFoundException("Person");
return data.First();
}
Using CSLA 4: Data Access Page 110
Rev 1.0
This code uses a LINQ query to retrieve the appropriate row of data from the mock Persons
table. That data is placed into a new PersonDto object, and that object is returned as the result of
the method.
Notice that an exception is thrown if no matching data is found.
The DataAccess.SqlCe DAL provider also implements a Fetch method:
public PersonDto Fetch(int id)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
var cm = ctx.Connection.CreateCommand();
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "SELECT Id,FirstName,LastName FROM Person WHERE Id=@id";
cm.Parameters.Add("@id", id);
using (var dr = cm.ExecuteReader())
{
dr.Read();
var result = new PersonDto
{ Id = dr.GetInt32(0), FirstName = dr.GetString(1), LastName = dr.GetString(2) };
return result;
}
}
}

This implementation gets the database connection and sets up a command object to retrieve the
requested data. That command object is executed to get a data reader, and the values from the
data reader are used to create and populate a new PersonDto object.

It is important to understand that every data access technology in .NET ultimately


uses a database connection and data reader to get data from a database. This is true
for the ADO.NET Entity Framework, LINQ to SQL, TableAdapter and DataSet objects,
etc. You may not see the explicit use of a data reader, but you can be sure it was
used behind the scenes.

If no matching data is found, the data reader’s Read method will throw an exception, so the
behavior is consistent with the Mock implementation, in that an exception is thrown when no
matching data is found.

Insert Operation
The insert action is managed by the DataPortal_Insert method:
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_Insert()
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IPersonDal>();
using (BypassPropertyChecks)
{
var data = new DataAccess.PersonDto { FirstName = FirstName, LastName = LastName };
dal.Insert(data);
Id = data.Id;
}
}
}

Using CSLA 4: Data Access Page 111


Rev 1.0
This method gets the DAL provider object that implements the IPersonDal interface and invokes
its Insert method. That Insert method expects to get a PersonDto object as a parameter, so the
business object’s data is copied into a PersonDto object before the DAL is invoked. The
BypassPropertyChecks object is used to suppress business and authorization rule checking while
the business object’s properties are accessed.
Notice that the PersonDto object’s Id property is used as a return value after the Insert method
is called. This is because the Insert method of the DAL provider is expected to provide the
database-generated Id value from the newly inserted row as a result. That new Id value is used to
set the Id property of the business object.
The SqlCe implementation of the Insert method looks like this:
public void Insert(PersonDto data)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "INSERT INTO Person (FirstName,LastName) VALUES (@firstName,@lastName)";
cm.Parameters.Add("@firstName", data.FirstName);
cm.Parameters.Add("@lastName", data.LastName);
cm.ExecuteNonQuery();
cm.Parameters.Clear();
cm.CommandText = "SELECT @@identity";
var r = cm.ExecuteScalar();
var newId = int.Parse(r.ToString());
data.Id = newId;
}
}
}

This method is almost identical to the one from the data reader implementation, except that the
data values come from the PersonDto object instead of individual parameters defined by the
method. And instead of returning the database-generated Id value as the result of the method, the
value is returned through the PersonDto object’s Id property.
As with the data reader implementation, the use of @@identity to get the database-generated
Id value is unqiue to SQL Server Compact Edition, and you should use SCOPE_IDENTITY with full SQL
Server.

Update Operation
The update action is managed by the DataPortal_Update method:
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_Update()
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IPersonDal>();
using (BypassPropertyChecks)
{
var data = new DataAccess.PersonDto { Id = Id, FirstName = FirstName, LastName = LastName };
dal.Update(data);
}
}
}

Using CSLA 4: Data Access Page 112


Rev 1.0
A PersonDto object is created and loaded with data so it can be passed as a parameter to the
DAL provider’s Update method. This is done within a BypassPropertyChecks block to suppress
business and authorization rule checking during the data access operation.
The Update method in the SqlCe DAL provider looks like this:
public void Update(PersonDto data)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "UPDATE Person SET FirstName=@firstName,LastName=@lastName WHERE Id=@id";
cm.Parameters.Add("@id", data.Id);
cm.Parameters.Add("@firstName", data.FirstName);
cm.Parameters.Add("@lastName", data.LastName);
var rowsAffected = cm.ExecuteNonQuery();
if (rowsAffected == 0)
throw new DataNotFoundException("Person");
}
}
}

As with the Insert method, this Update method is very similar to the data reader
implementation. The only difference is that the input values are coming from the PersonDto object
instead of explicit parameters to the method.

Deferred Delete Operation


The deferred delete action is managed by the DataPortal_DeleteSelf method. If the business class
also supports immediate deletion, this method will typically just invoke the DataPortal_Delete
method:
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_DeleteSelf()
{
using (BypassPropertyChecks)
{
DataPortal_Delete(Id);
}
}

If only deferred deletion is supported, then the call to the DAL provider’s Delete method is made
directly within the method:
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_DeleteSelf()
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IPersonDal>();
using (BypassPropertyChecks)
{
dal.Delete(Id);
}
}
}

Either way, the DAL provider’s Delete method is the same as in the data reader implementation.
It gets the database connection, sets up a command object, and executes the command object to
delete the data.
Using CSLA 4: Data Access Page 113
Rev 1.0
Immediate Delete Operation
The immediate deletion implementation in EncapsulatedInvokeDto is identical to that from the
data reader solution. Please refer to that earlier discussion for information.
At this point you should understand how to implement persistence for an editable root object
using a pluggable DAL with either a data reader or DTO-based interface. The next stereotype I’ll
cover is an editable root list.

Editable Root List Persistence


The SkillEditList class is an example of an editable root list that contains SkillEdit editable
child objects. These classes can be found in the Library.Net project in the EncapsulatedInvoke
and EncapsulatedInvokeDto solutions.
An editable root list supports the Create, Fetch, Update, and Delete operations. Like I did with
the editable root stereotype, I’ll demonstrate how to implement persistence for an editable root list
with a data reader interface and then with a DTO interface.

Data Reader Interface


The data reader example implementation can be found in the EncapsulatedInvoke solution in the
sample download for this ebook. In that solution, the DataAccess project contains the ISkillDal
interface:
public interface ISkillDal
{
IDataReader Fetch();
IDataReader Fetch(int id);
int Insert(string name);
void Update(int id, string name);
void Delete(int id);
}

This interface defines data access actions that can be performed on the logical skill entity,
including retrieving a list of skills, a single skill, and performing insert, update, and delete actions.
The DataAccess.Mock, DataAccess.SqlCe, and DataAccess.SqlEf projects contain SkillDal
classes. Each class implements this ISkillDal interface in a different way, but with consistent
behaviors.
Each data access action includes data access invocation and data access implementation.
Because these samples are following the encapsulated invoke model, the data access invocation is
in DataPortal_XYZ or Child_XYZ methods contained in each business class. The data access
implementation is located in the Mock, SqlEf, and SqlCe DAL provider projects.

Create Operation
The create operation starts with the static factory methods in the SkillEditList class:
#if SILVERLIGHT
public static void NewSkillEditList(EventHandler<DataPortalResult<SkillEditList>> callback)
{
DataPortal.BeginCreate<SkillEditList>(callback, DataPortal.ProxyModes.LocalOnly);
}

Using CSLA 4: Data Access Page 114


Rev 1.0
#else
public static void NewSkillEditList(EventHandler<DataPortalResult<SkillEditList>> callback)
{
DataPortal.BeginCreate<SkillEditList>(callback);
}

public static SkillEditList NewSkillEditList()


{
return DataPortal.Create<SkillEditList>();
}
#endif

As in the PersonEdit class, the asynchronous factory for Silverlight sets the data portal’s proxy
mode to LocalOnly so the create operation occurs on the client without relaying the call to the
application server.
The .NET factories provide asynchronous and synchronous support, relying on the RunLocal
attribute to be applied to the DataPortal_Create method to avoid calling an application server to
do the operation. The .NET DataPortal_Create method is a simple override that exists only to add
the RunLocal attribute:
[RunLocal]
protected override void DataPortal_Create()
{
base.DataPortal_Create();
}

There is no explicit Silverlight implementation of DataPortal_Create because the base class


implementation from the BusinessListBase class is sufficient to initialize an empty collection.
Because there’s no initialization or default data loaded into a newly created empty list object,
there’s no need for a Create method in the ISkillDal interface, or in the SkillDal DAL provider
classes.
You can see that creating a new empty collection is similar to creating a new editable root
object. In the case of a collection though, there’s also the need to create new child objects that go
into the collection, so I will walk through the options for that functionality.

Child Create Techniques


Most editable collections allow new child objects to be added to the list. There are three common
techniques used to add a new child object to a list:

1. Calling code creates the new child object, and adds it to the list by calling the collection’s
Add method

2. Collection implements an AddItem method that is responsible for creating the new child
object and adding it to the list

3. Calling code invokes the collection’s AddNew method, and that method creates the new child
object and adds it to the list (also used by data binding scenarios)

If you want to support techniques 1 or 2, you will need to write code to support those scenarios.
The advantage of these two techniques is that you can pass parameter values to the new child
object, and it can use those values as part of its initialization.

Using CSLA 4: Data Access Page 115


Rev 1.0
The BusinessListBase and BusinessBindingListBase classes support technique number 3 by
default. By default, if the AddNew method is called on an editable list, a new child object will be
created and initialized through its Child_Create method, and then it is added to the collection. You
can disable that functionality, or override the default behavior to customize how it works.
The drawback to the AddNew technique is that you can not pass parameter values to the new
child object, so the new child must initialize without any context-specific information.
I will now discuss all three scenarios.

Calling Code Creates Child


The first technique requires that the child class implement a static factory so the calling code can
create and initialize a new child. If the initialization doesn’t require the application server this is not
difficult, because the factory method can look like this:
public static SkillEdit NewSkillEdit()
{
return DataPortal.CreateChild<SkillEdit>();
}

The SkillEdit class may implement a Child_Create method to initialize the new object. The
BusinessBase class provides a default Child_Create implementation that accepts no parameters.
That default method calls the CheckRules method to run all business rules defined for the object.
This default method is virtual, so you can override the method when necessary.
It is important to understand that the data portal’s CreateChild method can accept zero or
more parameters through a params array. The data portal will find and invoke a Child_Create
method overload that accepts the matching parameter count and types. The standard .NET method
overloading rules apply to this process.
It is also important to realize that the CreateChild method will never go across the network to
an application server. The data portal’s CreateChild and FetchChild methods invoke
Child_Create and Child_Fetch methods on the same machine where the calling code is running.

Given a NewSkillEdit method that calls the data portal’s CreateChild method, the calling code
can then add a new child to a collection like this:
var list = SkillEditList.NewSkillEditList();
var item = SkillEdit.NewSkillEdit();
list.Add(item);

If the initialization of a new child does require data access, then it must run on the application
server. This requires that a unit of work object be used to create and initialize the child. Here’s an
example of a unit of work class to create a new SkillEdit object:
[Serializable]
public class SkillEditCreator : ReadOnlyBase<SkillEditCreator>
{
public static readonly PropertyInfo<SkillEdit> ResultProperty =
RegisterProperty<SkillEdit>(c => c.Result);
public SkillEdit Result
{
get { return GetProperty(ResultProperty); }
private set { LoadProperty(ResultProperty, value); }
}

public static void GetSkillEditCreator(EventHandler<DataPortalResult<SkillEditCreator>> callback)


Using CSLA 4: Data Access Page 116
Rev 1.0
{
DataPortal.BeginFetch<SkillEditCreator>(callback);
}
#if !SILVERLIGHT
public static SkillEditCreator GetSkillEditCreator()
{
return DataPortal.Fetch<SkillEditCreator>();
}

private void DataPortal_Fetch()


{
Result = DataPortal.CreateChild<SkillEdit>();
}
#endif
}

This class follows the read-only root object stereotype, and has one responsibility: create and
initialize a new SkillEdit child object. That SkillEdit object is created in the DataPortal_Fetch
method, and is returned through the Result property.
If you need to pass parameters to the new child object’s Child_Create method, you will need to
define a criteria class so you can pass those parameters through the data portal as the
SkillEditCreator object is created. Specifically, any parameters provided to the
GetSkillEditCreator method must be passed through the data portal to the DataPortal_Fetch
method using a criteria object. The DataPortal_Fetch method can then pass the parameter values
to the CreateChild method so they are available to the Child_Fetch method in the SkillEdit
class.
The calling code that wants to add a new child to the collection can now use this
SkillEditCreator to create the new child object. The calling code is different for synchronous and
asynchronous scenarios. Remember that Silverlight and WP7 can only use the asynchronous
technique.
In a synchronous scenario the calling code looks like this:
var list = SkillEditList.NewSkillEditList();
var creator = SkillEditCreator.GetSkillEditCreator();
var item = creator.Result;
list.Add(item);

In an asynchronous scenario the calling code looks like this:


var list = SkillEditList.NewSkillEditList();
SkillEditCreator.GetSkillEditCreator((o, e) =>
{
if (e.Error != null)
throw e.Error;
else
list.Add(e.Object.Result);
});

It is important to remember that the asynchronous callback doesn’t run immediately. The code
in the callback lambda expression will run when the asynchronous GetSkillEditCreator method
completes. This means the application will continue to run while the new child object is created,
initialized, and returned from the server. The new child will appear in the list once it has been
returned, not instantly like in the synchronous scenario.

Using CSLA 4: Data Access Page 117


Rev 1.0
Collection Implements AddItem Method
Although requiring that the calling code understand how to create a child object and add it to the
list is valid, I prefer more abstraction. The less the calling code knows about the details of creating a
child object the more maintainable your code will be in the long run.
To raise the level of abstraction, you can create an AddItem method in the collection class. This
AddItem method is responsible for creating the child object and adding it to the list. The result is
that the calling code always looks like this:
list.AddItem();

The AddItem method might accept parameters that are passed to the new child so it can use
those context-specific values for initialization.
You should understand that this AddItem method can be implemented synchronously or
asynchronously, and you may want to name it appropriately: BeginAddItem for asynchronous and
AddItem for synchronous. Using this naming scheme helps the calling code know what behavior to
expect when the method is invoked.
When the calling code invokes BeginAddItem it should also handle the CollectionChanged event
(or ListChanged for a BusinessBindingListBase subclass) so it is notified when the new child
object has been added to the list.
The exact same factory method and unit of work object concepts from the previous section
apply to this technique as well.
If the child object is created on the client without the need for data access, the AddItem method
will look like this:
public void AddItem()
{
Add(SkillEdit.NewSkillEdit());
}

And the NewSkillEdit factory method in the SkillEdit class will look like this:
public static SkillEdit NewSkillEdit()
{
return DataPortal.CreateChild<SkillEdit>();
}

If the child object initialization requires data access, then a unit of work object, like the
SkillEditCreator discussed in the previous section, is required. In that case the synchronous
AddItem method looks like this:
public void AddItem()
{
var creator = SkillEditCreator.GetSkillEditCreator();
Add(creator.Result);
}

And the asynchronous BeginAddItem method looks like this:


public void BeginAddItem()
{
SkillEditCreator.GetSkillEditCreator((o, e) =>
{
if (e.Error != null)
throw e.Error;
Using CSLA 4: Data Access Page 118
Rev 1.0
else
Add(e.Object.Result);
});
}

As I discussed in the previous section, the data portal’s CreateChild method accepts a params
array, so you can pass in zero or more parameters. The data portal invokes a Child_Create method
overload that accepts matching parameter types based on standard .NET method overloading rules.

Using the AddNew Method on a Collection


The BusinessListBase and BusinessBindingListBase classes define an AddNew method that can
be invoked to create and add a new child object to the collection. Calling code on .NET always looks
like this:
var item = list.AddNew();

Calling code on Silverlight and WP7 looks like this:


list.AddNew();

On Silverlight, no result is returned because the AddNew method is asynchronous.


The AddNew method doesn’t accept parameters, so the newly create child object must be able to
initialize itself without any context-specific parameter values.
When the AddNew method is invoked, a virtual method named AddNewCore is invoked to do the
work of creating the child object, initializing that object, and adding it to the list.
On .NET the AddNew method is synchronous. On Silverlight the AddNew method is asynchronous,
and there is also a protected method named OnAddedNew that is invoked to indicate that the new
child has been added to the list. The OnAddedNew method must be invoked when the asynchronous
process of creating and initializing the child object is complete.
The CSLA .NET base classes provide a default implementation of AddNewCore that directly invokes
the data portal’s CreateChild method to create a new child object. In other words, by default the
AddNew method “just works” on .NET and Silverlight. You can override this behavior if you need to
customize the process.
The most common reason you’d need to customize the process is because the new child object
requires data access to be initialized, and so the Child_Create method must run on the application
server. This means you will have implemented a unit of work class like the SkillEditCreator class
discussed earlier in this chapter.
An override of the AddNewCore method on .NET looks like this:
protected override SkillEdit AddNewCore()
{
var creator = SkillEditCreator.GetSkillEditCreator();
var item = creator.Result;
Add(item);
return item;
}

The new child object is created synchronously, and then it is added to the list. Finally it is
returned as the result of the method.
An override of the AddNewCore method on Silverlight or WP7 looks like this:
Using CSLA 4: Data Access Page 119
Rev 1.0
protected override void AddNewCore()
{
SkillEditCreator.GetSkillEditCreator((o, e) =>
{
if (e.Error != null)
{
throw e.Error;
}
else
{
var item = e.Object.Result;
Add(item);
OnAddedNew(item);
}
});
}

The asynchronous GetSkillEditCreator method is invoked, and when it completes the new
SkillEdit object is added to the list, and the OnAddedNew method is called to indicate that the
asynchronous operation is complete.
If you want to disable the AddNew behavior you should set the AllowNew property to false. For
example:
public SkillEditList()
{
AllowNew = false;
}

If this protected property is false, calling the AddNew method will result in an exception being
thrown.
At this point you should understand how to create new collection classes, and how to create,
initialize, and add new child items to an editable collection. I will now move on to discuss the Fetch
operation.

Fetch Operation
The Fetch operation for an editable root list starts with the static factory methods in the
SkillEditList class:
public static void GetSkillEditList(EventHandler<DataPortalResult<SkillEditList>> callback)
{
DataPortal.BeginFetch<SkillEditList>(callback);
}
#if !SILVERLIGHT
public static SkillEditList GetSkillEditList()
{
return DataPortal.Fetch<SkillEditList>();
}
#endif

These methods invoke the client-side data portal to initiate the Fetch operation. The client-side
data portal invokes the server-side data portal based on the client configuration. The server-side
data portal invokes the DataPortal_Fetch method:
private void DataPortal_Fetch()
{
var rlce = RaiseListChangedEvents;
RaiseListChangedEvents = false;
using (var dalManager = DataAccess.DalFactory.GetManager())
{
Using CSLA 4: Data Access Page 120
Rev 1.0
var dal = dalManager.GetProvider<DataAccess.ISkillDal>();
var data = dal.Fetch();
while (data.Read())
Add(DataPortal.FetchChild<SkillEdit>(data));
}
RaiseListChangedEvents = rlce;
}

Notice that the Fetch and BeginFetch methods provide no criteria parameter to the data portal,
so the data portal finds and invokes the DataPortal_Fetch overload that accepts no criteria
parameter.
This method sets the collection object’s RaiseListChangedEvents to false before loading data
into the collection, and sets it to the previous value when the method is complete. This is an
important performance optimization. As items are added to a collection the collection normally
raises a CollectionChanged event (or a ListChanged event for BusinessBindingListBase), and
that event is often handled by code that performs some work. If you load hundreds of items into a
collection that event processing can cause performance issues. Setting RaiseListChangedEvents to
false helps prevent that from occurring.

Like in the PersonEdit methods, this method uses the DalFactory class to get the DAL manager
object from the currently configured DAL provider assembly. The manager’s GetProvider method is
used to get the ISkillDal implementation, and the Fetch method is invoked to get an IDataReader
object.
The Fetch method implementation in the DataAccess.SqlCe provider looks like this:
public IDataReader Fetch()
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
var cm = ctx.Connection.CreateCommand();
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "SELECT Id,Name FROM Skill";
return cm.ExecuteReader();
}
}

This method opens a database connection and sets up a command object to retrieve the data
from the database. The command object is executed to create a data reader, and that data reader is
returned to the calling code in the DataPortal_Fetch method.
Back in the DataPortal_Fetch method, notice how the code uses a while loop to process each
item in the data reader, passing the data reader to the data portal’s FetchChild method to create
and load each child object with data. This causes the data portal to create an instance of the
SkillEdit class, and to invoke that object’s Child_Fetch method:
private void Child_Fetch(System.Data.IDataReader data)
{
using (BypassPropertyChecks)
{
Id = data.GetInt32(data.GetOrdinal("Id"));
Name = data.GetString(data.GetOrdinal("Name"));
}
}

The parameter value is a data reader that is pointing to the row of data that should be used to
load this child object’s properties. The values are copied from the data reader into the properties
Using CSLA 4: Data Access Page 121
Rev 1.0
within the using block for the BypassPropertyChecks object. This ensures that business and
authorization rules don’t run as the properties are set.
If you don’t trust the data coming from the database you should explicitly run the child object’s
business rules at the bottom of the Child_Fetch method. This is done by calling the CheckRules
method on the BusinessRules object.

Update Operation
The client-side data portal’s Update or BeginUpdate methods are called when the Save or
BeginSave method is called on an editable root list object. The client-side data portal invokes the
server-side data portal, and the server-side data portal then invokes the DataPortal_Update
method on the root business object.
A root collection class will override the DataPortal_Update method as follows:
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_Update()
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
base.Child_Update();
}
}

The method is marked with the Transactional attribute, so all insert, update, and delete actions
taken for each child object in the list will be considered part of a single transaction.
This code also gets the DAL manager object to be used. Remember that the DAL manager is a
disposable object that is responsible for opening or reusing a database connection. The update of
all child objects should be contained within a using block that ensures that the DAL manager or
database connection remains open throughout the process of updating all child objects.
The BusinessListBase and BusinessBindingListBase classes implement a Child_Update
method that correctly updates all child objects contained in the collection. You will not normally
need to do anything, except call this method, to cause all child objects to be updated.
The Child_Update method takes the following four steps:

1. Set RaiseListChangedEvents to false

2. Update (and therefore delete) all items in the collection’s DeletedList

3. Clear the DeletedList

4. Update (and therefore insert or update) all items in the collection itself

5. Set RaiseListChangedEvents to its previous value

If you do need to implement your own update code for some rare edge case, you must follow
these three steps as well. Again, normal root collections should be able to call Child_Update as
shown in this example.

Using CSLA 4: Data Access Page 122


Rev 1.0
The child class must implement Child_Insert, Child_Update, and Child_DeleteSelf methods
because these will be invoked by the data portal to insert, update, and delete the child data. The
SkillEdit class implements these methods:
private void Child_Insert()
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.ISkillDal>();
using (BypassPropertyChecks)
{
Id = dal.Insert(Name);
}
}
}

private void Child_Update()


{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.ISkillDal>();
using (BypassPropertyChecks)
{
dal.Update(Id, Name);
}
}
}

private void Child_DeleteSelf()


{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.ISkillDal>();
using (BypassPropertyChecks)
dal.Delete(Id);
}
}

Each method retrieves the current DAL provider that implements the ISkillDal interface and
calls the appropriate DAL method to perform the data insert, update, or delete. Notice that all
interactions with the business object’s properties are within a BypassPropertyChecks block.
The SkillDal class in the SqlCe DAL provider implements these DAL methods:
public int Insert(string name)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "INSERT INTO Skill (Name) VALUES (@name)";
cm.Parameters.Add("@name", name);
cm.ExecuteNonQuery();
cm.Parameters.Clear();
cm.CommandText = "SELECT @@identity";
var r = cm.ExecuteScalar();
var newId = int.Parse(r.ToString());
return newId;
}
}
}

public void Update(int id, string name)


{

Using CSLA 4: Data Access Page 123


Rev 1.0
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "UPDATE Skill SET Name=@name WHERE Id=@id";
cm.Parameters.Add("@id", id);
cm.Parameters.Add("@name", name);
var rowsAffected = cm.ExecuteNonQuery();
if (rowsAffected == 0)
throw new DataNotFoundException("Skill");
}
}
}

public void Delete(int id)


{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "DELETE Skill WHERE Id=@id";
cm.Parameters.Add("@id", id);
var rowsAffected = cm.ExecuteNonQuery();
if (rowsAffected == 0)
throw new DataNotFoundException("Skill");
}
}
}

Each method in SkillDal is similar to the code I discussed earlier for the PersonDal class. A
database connection is opened (or reused) and a command object is initialized to perform the
appropriate action. That command object is then executed and any results are returned to the
calling code.

Immediate Delete Operation


It is possible to implement immediate delete for an editable root list. This is relatively rare, and
most collections don’t implement this functionality. Deleting a collection typically means deleting all
data that would be loaded into the collection if it were retrieved.
To implement an immediate delete operation the business class will include a static factory
method:
public static void DeleteSkillEditList()
{
DataPortal.Delete<SkillEditList>(null);
}

This method calls the client-side data portal’s Delete method, and it invokes the server-side data
portal. The server-side data portal will create an instance of the business class and will call its
DataPortal_Delete method. It is important to realize that the collection will be entirely empty at
this point, so the DataPortal_Delete method won’t interact with any data in the collection. It will
interact only with the database.
The DataPortal_Delete method will look like this:
[Transactional(TransactionalTypes.TransactionScope)]
private void DataPortal_Delete(object criteria)
{
using (var dalManager = DataAccess.DalFactory.GetManager())
Using CSLA 4: Data Access Page 124
Rev 1.0
{
var dal = dalManager.GetProvider<DataAccess.ISkillDal>();
dal.Delete();
}
}

Notice that a Delete method is invoked on the DAL provider. The ISkillDal interface in the
sample code doesn’t define this method. To implement the immediate delete functionality, the
ISkillDal interface will need to define such a Delete method, and the DAL provider
implementations will need to implement the method.
Such a Delete method in the SqlCe provider would look like this:
public void Delete()
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "DELETE Skill";
var rowsAffected = cm.ExecuteNonQuery();
}
}
}

This method deletes all data in the Skill table, because that is the data the SkillEditList
collection would contain if it were retrieved.
As I discussed with the editable root stereotype, you should understand that a “delete”
operation doesn’t necessarily need to delete any data. Although this example does delete rows of
data from the database, you could implement the Delete method to perform an update of each
existing row to set a “deleted flag” that just marks the row as deleted.

DTO Interface
The EncapsulatedInvokeDto project contains the sample code demonstrating how to implement
persistence operations for an editable root list. The basic structure of the code is similar to the code
I just discussed for the data reader interface.
The ISkillDal interface in the DataAccess project is different because it uses DTO types instead
of data readers to pass data between the business objects and the DAL:
public interface ISkillDal
{
List<SkillDto> Fetch();
SkillDto Fetch(int id);
void Insert(SkillDto data);
void Update(SkillDto data);
void Delete(int id);
}

The SkillDto class is also in the DataAccess project, and it looks like this:
public class SkillDto
{
public int Id { get; set; }
public string Name { get; set; }
}

Using CSLA 4: Data Access Page 125


Rev 1.0
It defines a public read-write property for every data value that needs to move between the
business objects and data access code.

Create Operation
The create operation is the same with a DTO interface as in the data reader example. Please refer to
the earlier discussion for details.

Fetch Operation
The Fetch operation is similar to the data reader implementation. The DataPortal_Fetch in the
SkillEditList class is a little different because it uses the DTO type:
private void DataPortal_Fetch()
{
var rlce = RaiseListChangedEvents;
RaiseListChangedEvents = false;
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.ISkillDal>();
var data = dal.Fetch();
foreach (var item in data)
Add(DataPortal.FetchChild<SkillEdit>(item));
}
RaiseListChangedEvents = rlce;
}

Instead of getting a data reader from the DAL Fetch method, this code gets a List<SkillDto>
and it then loops through that list to create a child object for each item in the list.
The Fetch method in the SqlCe DAL provider looks like this:
public List<SkillDto> Fetch()
{
var result = new List<SkillDto>();
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
var cm = ctx.Connection.CreateCommand();
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "SELECT Id,Name FROM Skill";
using (var dr = cm.ExecuteReader())
{
while (dr.Read())
result.Add(new SkillDto { Id = dr.GetInt32(0), Name = dr.GetString(1) });
}
}
return result;
}

As in the data reader implementation, this method gets the database connection and sets up a
command object to retrieve the data. That command object is executed to get a data reader, and
the values from the data reader are used to populate the List<SkillDto> that is returned as the
result of the method.
Back in the DataPortal_Fetch method, the code loops through that list, calling the data portal’s
FetchChild method to create each child object. A SkillDto object is passed as a parameter to the
child object’s Child_Fetch method. That method is in the SkillEdit class and looks like this:
private void Child_Fetch(DataAccess.SkillDto data)
{
using (BypassPropertyChecks)

Using CSLA 4: Data Access Page 126


Rev 1.0
{
Id = data.Id;
Name = data.Name;
}
}

This method sets the business object’s property values from the properties in the DTO passed in
as a parameter. The property manipulation occurs in a BypassPropertyChecks block to suppress
business and authorization rules from running.
If you don’t trust the data from the database you can manually call the CheckRules method on
the BusinessRules object at the end of the Child_Fetch method.

Update Operation
The update operation is also similar to the data reader implementation. In fact, the code in
SkillEditList is identical in both cases. The code in the SkillEdit child class is a little different:
private void Child_Insert()
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.ISkillDal>();
using (BypassPropertyChecks)
{
var data = new DataAccess.SkillDto { Name = Name };
dal.Insert(data);
Id = data.Id;
}
}
}

private void Child_Update()


{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.ISkillDal>();
using (BypassPropertyChecks)
{
var data = new DataAccess.SkillDto { Id = Id, Name = Name };
dal.Update(data);
}
}
}

private void Child_DeleteSelf()


{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.ISkillDal>();
using (BypassPropertyChecks)
dal.Delete(Id);
}
}

The Child_Insert and Child_Update methods create SkillDto objects and load them with data
from the business object. That DTO object is then passed as a parameter to the appropriate Insert
or Update DAL method.
The Child_Delete method is the same as in the data reader example.
The SkillDal class in the DataAccess.SqlCe project implements the DAL methods:

Using CSLA 4: Data Access Page 127


Rev 1.0
public void Insert(SkillDto data)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "INSERT INTO Skill (Name) VALUES (@name)";
cm.Parameters.Add("@name", data.Name);
cm.ExecuteNonQuery();
cm.Parameters.Clear();
cm.CommandText = "SELECT @@identity";
var r = cm.ExecuteScalar();
var newId = int.Parse(r.ToString());
data.Id = newId;
}
}
}

public void Update(SkillDto data)


{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "UPDATE Skill SET Name=@name WHERE Id=@id";
cm.Parameters.Add("@id", data.Id);
cm.Parameters.Add("@name", data.Name);
var rowsAffected = cm.ExecuteNonQuery();
if (rowsAffected == 0)
throw new DataNotFoundException("Skill");
}
}
}

public void Delete(int id)


{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "DELETE Skill WHERE Id=@id";
cm.Parameters.Add("@id", id);
var rowsAffected = cm.ExecuteNonQuery();
if (rowsAffected == 0)
throw new DataNotFoundException("Skill");
}
}
}

The code in these methods is comparable to the data reader code, except that the input values
are provided through the DTO instead of individual parameter values defined by the method. Also,
the Insert method returns the database-generated Id property through the DTO instead of
returning it as the result of the method.

Immediate Delete Operation


The immediate delete implementation is the same as in the data reader implementation. Please
refer to the earlier discussion for details.

Using CSLA 4: Data Access Page 128


Rev 1.0
At this point you should understand how to implement persistence for an editable root list and
its child objects. I will now discuss another type of editable collection: the dynamic list stereotype
and the dynamic root objects it contains.

Dynamic List and Object Persistence


The CategoryEditList and CategoryEdit classes implement the dynamic list and dynamic root
stereotypes. These can be found in the Library.Net projects of the EncapsulatedInvoke and
EncapsulatedInvokeDto solutions.
The dynamic list stereotype is quite different from the editable root list stereotype. Where the
editable root list contains child objects, a dynamic list contains root objects. An editable root list
saves all changed child objects as a batch, usually in a single database transaction. A dynamic list
saves each root object it contains, one at a time, as each root object is changed.
A dynamic list supports the Fetch operation, and this operation is responsible for creating the list
object and populating it with root objects. This process loads all the root objects into the list at one
time.
The interesting thing about the Fetch operation is that the collection’s implementation is similar
to that for an editable root list, except that it creates and populates root objects instead of child
objects. The root objects are a little different from a normal root object, because their Fetch
operation is usually initiated through an internal factory method instead of a public factory
method.
A dynamic list also supports the update operation, but not in the same way as an editable root
list. In this stereotype, the update operation occurs on each individual root object, and is usually
triggered by a data binding event that tells the dynamic list that the user is done editing a root
object.
The update operation for a dynamic list is very different from an editable root list, because the
dynamic root list calls the Save or BeginSave method on the individual root object, and the list itself
is never “saved”.

Data Reader Interface


The EncapsulatedInvoke solution contains an implementation of a dynamic list using a data reader
based interface. The DataAccess project includes the ICategoryDal interface:
public interface ICategoryDal
{
IDataReader Fetch();
int Insert(string name);
void Update(int id, string name);
void Delete(int id);
}

This interface defines the DAL actions that can be performed on the category data entity, and it
is similar to the previous DAL interfaces you’ve seen in this chapter.
The Fetch method retrieves the data for all the root objects that will be loaded into the
collection.

Using CSLA 4: Data Access Page 129


Rev 1.0
The Insert, Update, and Delete methods are used to insert, update, and delete individual root
object data.

Fetch Operation
The Fetch operation starts with a static factory method in the CategoryEditList collection class:
public static void GetCategoryEditList(EventHandler<DataPortalResult<CategoryEditList>> callback)
{
DataPortal.BeginFetch<CategoryEditList>(callback);
}

#if !SILVERLIGHT
public static CategoryEditList GetCategoryEditList()
{
return DataPortal.Fetch<CategoryEditList>();
}
#endif

As in the previous examples, the asynchronous factory is available to Silverlight, WP7, and .NET.
The synchronous factory is only available to .NET code.
These factory methods call the client-side data portal, and the client-side data portal invokes the
server-side data portal based on the client configuration. The server-side data portal creates an
instance of the CategoryEditList type and invokes the DataPortal_Fetch method on that object.
Zero or one criteria parameters may be passed to the data portal methods, and therefore to the
DataPortal_Fetch method. Here’s the code from the sample application:
private void DataPortal_Fetch()
{
var rlce = RaiseListChangedEvents;
RaiseListChangedEvents = false;
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.ICategoryDal>();
using (var data = dal.Fetch())
{
while (data.Read())
Add(CategoryEdit.GetCategoryEdit(
data.GetInt32(data.GetOrdinal("Id")), data.GetString(data.GetOrdinal("Category"))));
}
}
RaiseListChangedEvents = rlce;
}

This code is very similar to the editable root list implementation. It gets the data from the
database by calling the DAL Fetch method from the current DAL provider. For example, the SqlCe
provider has the following Fetch method in the CategoryDal class:
public System.Data.IDataReader Fetch()
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
var cm = ctx.Connection.CreateCommand();
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "SELECT Id,Category FROM Category";
return cm.ExecuteReader();
}
}

The results of this method are used by the DataPortal_Fetch method to populate the collection.
Using CSLA 4: Data Access Page 130
Rev 1.0
The DataPortal_Fetch method is different from the previous implementations you’ve seen, in
that the objects added to the collection are root objects. Each root object is created by invoking the
static factory method defined on the CategoryEdit class: GetCategoryEdit.

Here’s the GetCategoryEdit factory method:


#if !SILVERLIGHT
internal static CategoryEdit GetCategoryEdit(int id, string name)
{
var result = DataPortal.Fetch<CategoryEdit>();
using (result.BypassPropertyChecks)
{
result.Id = id;
result.Name = name;
}
return result;
}
#endif

Notice that there is no factory method on the Silverlight side, because the only time a
CategoryEdit object is created is on the application server as the dynamic list is being retrieved.
The exception is that if you create a 1-tier Silverlight application you will implement this factory
method on the Silverlight side.
Also notice that the method’s scope is internal. This is because the method should only be
invoked by the DataPortal_Fetch method of the dynamic list.
Finally, you can see that this isn’t a typical root factory method, because it accepts numerous
parameters and uses those values to set the properties of the business object.
The business object is created by calling the data portal’s Fetch method, but in a dynamic root
class the DataPortal_Fetch method typically does no work. Here’s that method in the
CategoryEdit class:
private void DataPortal_Fetch()
{}

The result of the GetCategoryEdit factory method is a root object populated with data from the
database, where that data was provided by the DataPortal_Fetch method of the dynamic list
parent object.
In summary, the static factory method in the collection class invokes the data portal’s Fetch or
BeginFetch method to retrieve the list. The data portal invokes the collection object’s
DataPortal_Fetch method, and that method gets the data from the DAL provider. Each row of data
from the database is used to create a dynamic root object, and that object is added to the list.

Update Operation
The update operation in a dynamic list is quite different from the update in an editable root list. In a
dynamic list, the update operation is usually automatically triggered by data binding when the user
moves off the current row in a datagrid control, or deletes a row in a datagrid control.
You can also force the update of an individual root object in the list by calling the SaveItem
method on the collection:
list.SaveItem(item);

Using CSLA 4: Data Access Page 131


Rev 1.0
This should only be done if you are not using data binding with a datagrid control, and if you fully
understand how data binding would have interacted with the list. The DynamicListBase and
DynamicBindingListBase classes are designed specifically to work with data binding, and if you
interact with them directly you must emulate data binding to get the expected results.
The SaveItem method is asynchronous. You can handle the collection’s Saved event to be
notified when the update operation for the dynamic root object is complete.

Because the update operation is always asynchronous, the dynamic list stereotype is
not well suited to web application development. If you do use a dynamic list in a
web application, you will need to implement thread synchronization code to ensure
the update completes before the page or service code completes.

When the user moves off a row in a datagrid control, or deletes a row in a datagrid control, or
you directly invoke the SaveItem method, one dynamic root object contained in the dynamic list is
updated. The dynamic list base class will invoke the BeginSave method of the root object, causing
that root object to be saved through the data portal.
When BeginSave is called on a root object, the BeginSave method calls the client-side data
portal’s BeginUpdate method. That causes the server-side data portal to invoke the root object’s
DataPortal_Insert, DataPortal_Update, or DataPortal_DeleteSelf method depending on the
metastate of the object. This is exactly the same as with any editable root object, and I’ve already
discussed this process in detail with the PersonEdit business type.
If you look in the sample code at the CategoryEdit class you will find the three DataPortal_XYZ
methods that invoke the data access behaviors. Each of these methods gets the current DAL
provider object and invokes the Insert, Update, or Delete DAL method to perform the appropriate
data access action.
The result is that the data for the individual dynamic root object is persisted.

DTO Interface
The EncapsulatedInvokeDto solution contains an implementation of a dynamic list using a data
reader based interface. The DataAccess project includes the ICategoryDal interface:
public interface ICategoryDal
{
List<CategoryDto> Fetch();
void Insert(CategoryDto data);
void Update(CategoryDto data);
void Delete(int id);
}

This interface defines the DAL actions that can be performed on the category data entity, using a
DTO instead of a data reader and explicit method parameter values. The CategoryDto contains the
values that need to flow between the business object and the data access code:
public class CategoryDto
{
public int Id { get; set; }
public string Category { get; set; }
}

Using CSLA 4: Data Access Page 132


Rev 1.0
The Fetch method defined by the ICategoryDal interface retrieves the data for all the root
objects that will be loaded into the collection.
The Insert, Update, and Delete methods are used to insert, update, and delete individual root
object data.

Fetch Operation
The factory methods for the Fetch operation are the same in the DTO example as they were in the
data reader example. The CategoryEditList class also contains the DataPortal_Fetch method,
and this method is a little different with a DTO-based DAL interface:
private void DataPortal_Fetch()
{
var rlce = RaiseListChangedEvents;
RaiseListChangedEvents = false;
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.ICategoryDal>();
var data = dal.Fetch();
foreach (var item in data)
Add(CategoryEdit.GetCategoryEdit(item));
}
RaiseListChangedEvents = rlce;
}

The DAL provider’s Fetch method returns a List<CategoryDto>, and the data in that list is used
to create and populate each dynamic root object that is added to the collection. The Fetch method
in the SqlCe provider looks like this:
public List<CategoryDto> Fetch()
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
var result = new List<CategoryDto>();
var cm = ctx.Connection.CreateCommand();
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "SELECT Id,Category FROM Category";
using (var dr = cm.ExecuteReader())
{
while (dr.Read())
{
result.Add(new CategoryDto { Id = dr.GetInt32(0), Category = dr.GetString(1) });
}
}
return result;
}
}

The result of this method is used by the DataPortal_Fetch method to create individual dynamic
root objects. Each root object is created by calling the static factory method in the CategoryEdit
class:
internal static CategoryEdit GetCategoryEdit(DataAccess.CategoryDto data)
{
var result = DataPortal.Fetch<CategoryEdit>();
using (result.BypassPropertyChecks)
{
result.Id = data.Id;
result.Name = data.Category;
}
return result;
}
Using CSLA 4: Data Access Page 133
Rev 1.0
Notice how the factory method accepts a parameter of type CategoryDto, allowing the parent’s
DataPortal_Fetch method to pass in each row of data to create the root objects.

The factory method creates a new instance of the root object using the data portal as I discussed
in the data reader implementation. Then that object’s properties are loaded with data from the
DTO parameter.
The result is a fully populated dynamic list object containing dynamic root objects.

Update Operation
The update operation works the same with a DTO interface as with the data reader interface. As
you can imagine, the DataPortal_XYZ methods and DAL methods that implement the insert,
update, and delete actions use CategoryDto objects to pass data between the business object code
and the DAL provider code.
I’ve already discussed the update process for an editable root object with the PersonEdit class
and the data reader implementation of the CategoryEdit class.
You can look at the CategoryEdit class in the EncapsulatedInvokeDto solution to see the DTO-
based DataPortal_XYZ methods, and you can look at the CategoryDal classes in the DAL provider
projects to see how the insert, update, and delete actions are implemented.

Editable Object Graph Persistence


At this point in the chapter you have seen how to implement persistence for an editable root, an
editable root list, and a dynamic list containing dynamic root objects. Those object graphs have
been relatively simple. The most complex is the editable root list containing child objects.
Many applications have more complex object graphs, consisting of a root parent containing child
objects, and those child objects containing other child (grandchild) objects. Anything beyond a
simple root parent-child graph is more complex in terms of object persistence.
The Library.Net projects in the two sample solutions include an OrderEdit class. This is the
root type for a more complex object graph, shown in Figure 14.

Using CSLA 4: Data Access Page 134


Rev 1.0
Figure 14. OrderEdit object graph.
An OrderEdit object contains an editable child collection of OrderLineItem objects. The
OrderLineItem class implements the editable child stereotype, and represents one line item in the
order.
Each OrderLineItem child object contains an editable child collection of OrderLinePerson
objects. The OrderLinePerson class implements the editable child stereotype, and represents one
person associated with the line item.
Although persistence of a more complex object graph is similar to persisting an editable root or
editable root list, the added levels of object hierarchy do make the data access more difficult.
For example, SQL Server allows multiple SELECT queries to be placed in a single database call. In
this case the resulting data reader starts out pointing to the results of the first SELECT statement in
the query, and you can call its NextResult method to make the data reader point to the results
from the next SELECT statement in the query. That’s an easy and efficient way to get data for an
editable root object and a list of child objects it contains. Parent-child is easy.
As soon as you add grandchild objects to the object graph (or use a database that doesn’t allow
multiple SELECT statements in a single query), you’ll need to query the database for each “level” of
objects in the object graph.
Typically, you’ll do a database query at the root object level, and then at each collection level.
For example, the objects in Figure 14 would perform a database query at the OrderEdit,
OrderLineItems, and OrderLinePersons levels.

Data Reader Interface


The DataAccess project in the EncapsulatedInvoke solution defines intefaces for the order, line
item, and line item person data entities.
The IOrderDal interface supports the order data entity:
public interface IOrderDal
{
int ShipOrder(int id);
IDataReader Fetch(int id);
int Insert(int customerId, DateTime? orderDate, DateTime? lastDate);
void Update(int id, int customerId, DateTime? orderDate, DateTime? lastDate);
void Update(int id, DateTime? lastDate);
void Delete(int id);
}

The order entity represents data stored in an Orders table.


The IOrderLineItemDal interface supports the line item entity:
public interface IOrderLineItemDal
{
IDataReader Fetch(int orderId);
int Insert(int orderId, DateTime? shipDate);
void Update(int id, int orderId, DateTime? shipDate);
void DeleteAllForOrder(int orderId);
void Delete(int lineItemId);
}

Using CSLA 4: Data Access Page 135


Rev 1.0
The line item entity represents data stored in an OrderLineItems table, with a foreign key to link
each line item row with an order in the Orders table. You can see how the Fetch method requires
the orderId parameter so it retrieves line items for a specific order.
Finally, the IOrderLineItemPersonDal supports the line item person entity:
public interface IOrderLineItemPersonDal
{
IDataReader Fetch(int lineItemId);
void Insert(int lineItemId, int personId);
void DeleteAllForLineItem(int lineItemId);
void Delete(int lineItemId, int personId);
}

The line item person entity represents a link table that links a row in the OrderLineItems table
to a row in the Persons table. This link table could contain other metadata about the relationship
beween the line item and person, but for this example the table contains two columns, and
therefore the entity contains only those two values as well.
You can see how the Fetch method requires the lineItemId parameter so it retrieves data for a
specific line item.
I’ll walk through each persistence operation for the object graph. I will focus more on the
process flow, and less on the specific DAL code, because the DAL provider code that implements
each of the DAL interfaces is essentially the same as the DAL code you’ve seen in every example so
far.

Create Operation
The create operation starts with the static factory methods in the root OrderEdit class:
#if SILVERLIGHT
public static void NewOrderEdit(int customerId, EventHandler<DataPortalResult<OrderEdit>> callback)
{
DataPortal.BeginCreate<OrderEdit>(customerId, callback, DataPortal.ProxyModes.LocalOnly);
}
#else
public static void NewOrderEdit(int customerId, EventHandler<DataPortalResult<OrderEdit>> callback)
{
DataPortal.BeginCreate<OrderEdit>(customerId, callback);
}

public static OrderEdit NewOrderEdit(int customerId)


{
return DataPortal.Create<OrderEdit>(customerId);
}
#endif

These factory methods are slightly different from the previous examples, because they require a
parameter value. When an order is created, it is created for a specific customer, and the
customerId parameter ensures that the customer is identified before the order is created.

The DataPortal_Create method accepts this value as a parameter. Here’s the Silverlight
implementation:
protected void DataPortal_Create(
int customerId, Csla.DataPortalClient.LocalProxy<OrderEdit>.CompletedHandler handler)
{
using (BypassPropertyChecks)
{
Using CSLA 4: Data Access Page 136
Rev 1.0
Id = -1;
CustomerId = customerId;
OrderDate = DateTime.Today;
LastEdit = DateTime.Today;
}
OrderLineItems = DataPortal.CreateChild<OrderLineItems>();
base.DataPortal_Create(handler);
}

Remember that the Silverlight method is potentially asynchronous, and when it is complete the
callback handler must be invoked. Even though this specific implementation is not async, the
handler still must be called. The base implementation of DataPortal_Create is invoked, because it
properly invokes the callback handler.
This Silverlight implementation is required because the Silverlight factory method uses the
LocalOnly proxy mode, ensuring that the object graph is created on the client, not on the
application server.
The .NET implementation uses the RunLocal attribute to achieve the same goal:
[RunLocal]
protected void DataPortal_Create(int customerId)
{
using (BypassPropertyChecks)
{
Id = -1;
CustomerId = customerId;
OrderDate = DateTime.Today;
LastEdit = DateTime.Today;
}
OrderLineItems = DataPortal.CreateChild<OrderLineItems>();
base.DataPortal_Create();
}

In both implementations, notice how the OrderEdit object’s properties are initialized, including
setting the CustomerId property to the value of the customerId parameter.
Also notice how both implementations call the data portal’s CreateChild method to create an
instance of the OrderLineItems child collection. This causes the data portal to invoke the
Child_Create method in the OrderLineItems class. If you look at that class you won’t find such a
method, because the base implementation in the BusinessListBase class is sufficient, and there’s
typically no need to override that method.
The result of this process is that an OrderEdit root object, containing an empty OrderLineItems
collection, is created and initialized.

Creating New Child Objects


As the application interacts with the OrderEdit object, new OrderLineItem objects will probably be
added to the child collection. In this application I am using the built-in support for the AddNew
method in the OrderLineItems collection. When the AddNew method is called, it invokes the client-
side data portal’s CreateChild method to create and initialize a new OrderLineItem object.
The OrderLineItem class implements a Child_Create method to initialize the new object:
public override void Child_Create()
{
using (BypassPropertyChecks)
{

Using CSLA 4: Data Access Page 137


Rev 1.0
Id = -1;
Persons = DataPortal.CreateChild<OrderLinePersons>();
}
base.Child_Create();
}

This method initializes the new object’s properties, including the Persons property that contains
an OrderLinePersons child collection object. The data portal’s CreateChild method is used to
create an instance of this new child collection. Again, I rely on the Child_Create implementation in
the BusinessListBase class to initialize the new collection object.
You can also use the other two techniques I discussed for adding child items to an editable
collection earlier in this chapter. See the discussion around adding SkillEdit child objects to the
SkillEditList collection for more information about the Add and AddItem method techniques.

Creating New Grandchild Objects


Once the application has an OrderLineItem object, it can associate people with that line item. That
means it will add OrderLinePerson child objects to the OrderLinePersons child collection.
The exact same techniques apply to a grandchild list as to a child list or an editable root list. You
can use the built-in AddNew functionality, or the Add method, or a custom AddItem method. Again,
please refer to the discussion around adding SkillEdit child objects to the SkillEditList
collection for more information about the Add and AddItem method techniques.
At this point you should understand how to create the root object of a complex object graph,
and how to create and initialize child collections and child objects to be added to those collections.

Fetch Operation
The Fetch operation is more interesting, because it typically requires multiple database interactions
to load the entire object graph. As I mentioned earlier, you typically need to make a database call
for each major level in the object graph hierarchy.
There are some technologies that can help you “avoid” multiple database interactions, including
the use of the ADO.NET Entity Framework or the DataSet object. It is important to recognize that in
most cases these technologies still do multiple database interactions. They just do the interactions
behind the scenes so you don’t explicitly see them. What looks to you like one database interaction
is one logical database interaction, possibly consisting of numerous calls to the database.
The data reader interface makes each database interaction explicit, and that gives you an
opportunity to see and optimize each interaction.
The Fetch operation starts with the static factory methods in the OrderEdit class:
public static void GetOrderEdit(int id, EventHandler<DataPortalResult<OrderEdit>> callback)
{
DataPortal.BeginFetch<OrderEdit>(id, callback);
}
#if !SILVERLIGHT
public static OrderEdit GetOrderEdit(int id)
{
return DataPortal.Fetch<OrderEdit>(id);
}
#endif

Using CSLA 4: Data Access Page 138


Rev 1.0
As usual, the client-side data portal invokes the server-side data portal based on the client
configuration. The server-side data portal invokes the DataPortal_Fetch method in the OrderEdit
class:
private void DataPortal_Fetch(int id)
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IOrderDal>();
var data = dal.Fetch(id);
data.Read();
using (BypassPropertyChecks)
{
Id = data.GetInt32(data.GetOrdinal("Id"));
CustomerId = data.GetInt32(data.GetOrdinal("CustomerId"));
OrderDate = data.GetDateTime(data.GetOrdinal("OrderDate"));
LastEdit = data.GetDateTime(data.GetOrdinal("OrderEditDate"));
}
OrderLineItems = DataPortal.FetchChild<OrderLineItems>(id);
}
}

By now this type of code should be familiar. The method gets the DAL provider and calls the
Fetch method to get a data reader that contains the data necessary to populate the OrderEdit
object. I won’t show the Fetch method from the OrderDal class, because you’ve seen several Fetch
methods at this point.
The FetchChild method is called to create and populate the OrderLineItems child collection
with child OrderLineItem objects. The code in the example passes the order id parameter value to
the FetchChild method, so the Child_Fetch method in the OrderLineItems class can retrieve the
child data:
#if !SILVERLIGHT
private void Child_Fetch(int orderId)
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IOrderLineItemDal>();
var data = dal.Fetch(orderId);
var rlce = RaiseListChangedEvents;
RaiseListChangedEvents = false;
while (data.Read())
Add(DataPortal.FetchChild<OrderLineItem>(data));
RaiseListChangedEvents = rlce;
}
}
#endif

This method gets the DAL provider implementation for the IOrderLineItemDal interface, and
calls its Fetch method to get a data reader with the data. This code is essentially identical to the
code used to load the SkillEditList collection with data earlier in this chapter.
As you have probably guessed, the OrderLineItem class contains a Child_Fetch that loads the
child object with data from the data reader:
private void Child_Fetch(System.Data.IDataReader data)
{
using (BypassPropertyChecks)
{
Id = data.GetInt32(data.GetOrdinal("Id"));
var shipDateIndex = data.GetOrdinal("ShipDate");
if (!data.IsDBNull(shipDateIndex))
Using CSLA 4: Data Access Page 139
Rev 1.0
ShipDate = data.GetDateTime(shipDateIndex);
Persons = DataPortal.FetchChild<OrderLinePersons>(Id);
}
}

This method also creates and populates the OrderLinePersons child collection by calling the
data portal’s FetchChild method. The line item’s Id property is passed as a parameter to the
FetchChild method, and therefore to the Child_Fetch method implemented in the
OrderLinePersons class.

At this point the process repeats. The collection’s Child_Fetch method retrieves the data
necessary to populate the child OrderLinePerson objects by invoking the DAL provider:
private void Child_Fetch(int lineItemId)
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IOrderLineItemPersonDal>();
var data = dal.Fetch(lineItemId);
var rlce = RaiseListChangedEvents;
RaiseListChangedEvents = false;
while (data.Read())
Add(DataPortal.FetchChild<OrderLinePerson>(data));
RaiseListChangedEvents = rlce;
}
}

The data portal’s FetchChild method is used to create and populate each individual
OrderLinePerson object based on the data in the data reader. The Child_Fetch method in the
OrderLinePerson class looks like this:
private void Child_Fetch(System.Data.IDataReader data)
{
using (BypassPropertyChecks)
{
LineItemId = data.GetInt32(data.GetOrdinal("LineItemId"));
PersonId = data.GetInt32(data.GetOrdinal("PersonId"));
}
}

The database interaction occurs at each major level of the object graph: OrderEdit,
OrderLineItems, and OrderLinePersons.

Combining Database Interactions


If you are using full SQL Server, you can avoid one of these database interactions by combining two
SELECT queries into one database call in the OrderEdit class. This is because SQL Server allows
multiple SELECT queries to execute as part of one command object execution.
In theory, you can also combine the grandchild query into that one database call. I find that
doing this substantially complicates the code necessary to populate the object graph, and so I only
combine the root and child queries in this manner, and do individual database queries to get each
set of grandchild object data.
Although the sample code doesn’t implement this combined query technique, I will briefly walk
through the changes you’d need to make to the existing code if you wanted to use the technique.

Using CSLA 4: Data Access Page 140


Rev 1.0
The first step in combining the queries is to change the database query in the OrderDal DAL
provider’s Fetch method. If you implemented a DataAccess.Sql provider, the Fetch method might
look like this:
public System.Data.IDataReader Fetch(int id)
{
using (var ctx = ConnectionManager<SqlConnection>.GetManager("LocalDb"))
{
var cm = ctx.Connection.CreateCommand();
cm.CommandType = System.Data.CommandType.Text;
var query = @"SELECT Id,CustomerId,OrderDate,OrderEditDate FROM [Order] WHERE Id=@id;
SELECT Id,ShipDate FROM OrderLineItem WHERE OrderId=@id";
cm.CommandText = query;
cm.Parameters.Add("@id", id);
return cm.ExecuteReader();
}
}

Notice that the query field contains two SELECT statements. The first SELECT retrieves the data
for the OrderEdit object, and the second retrieves the data for the child OrderLineItem objects.
The resulting data reader will read through the data from the first SELECT statement, and then
through the data from the second statement. It is important to remember that data readers are
linear: they read through data sequentially.
The DataPortal_Fetch method in the OrderEdit class must also be changed to accommodate
the multiple results in a single data reader:
private void DataPortal_Fetch(int id)
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IOrderDal>();
var data = dal.Fetch(id);
data.Read();
using (BypassPropertyChecks)
{
Id = data.GetInt32(data.GetOrdinal("Id"));
CustomerId = data.GetInt32(data.GetOrdinal("CustomerId"));
OrderDate = data.GetDateTime(data.GetOrdinal("OrderDate"));
LastEdit = data.GetDateTime(data.GetOrdinal("OrderEditDate"));
}
data.NextResult();
OrderLineItems = DataPortal.FetchChild<OrderLineItems>(data);
}
}

After the data for the OrderEdit object is read from the data reader, the data reader’s
NextResult method is called to move the data reader to the results of the second SELECT
statement.
Notice that this change to DataPortal_Fetch means that this implementation is incompatible
with the existing SqlEf, SqlCe and Mock implementations, or with implementations for other
databases that don’t support multiple queries in a single database command.

This fundamentally changes the expected behavior of the DAL implementations. You
need to take this into consideration, because all DAL providers must conform to the
same set of expected behaviors so they remain interchangeable.

Using CSLA 4: Data Access Page 141


Rev 1.0
The FetchChild method is now provided with the data reader object instead of the order id
parameter. This means that the Child_Fetch method in the OrderLineItems class must also be
different (and simpler):
private void Child_Fetch(IDataReader data)
{
var rlce = RaiseListChangedEvents;
RaiseListChangedEvents = false;
while (data.Read())
Add(DataPortal.FetchChild<OrderLineItem>(data));
RaiseListChangedEvents = rlce;
}

This new implementation no longer calls its own Fetch method from the OrderLineItemDal
provider, because it already has an open data reader containing the data it needs to create and
populate its child objects.
This data reader contains the exact same data as the OrderLineItemDal provider’s Fetch
method provided. The code in the OrderLineItem, OrderLinePersons, and OrderLinePerson
classes are unaffected.
At this point you should understand how to fetch a root object, its child objects, and grandchild
objects by using a data reader based DAL interface. I will now walk through the process of updating
data from a complex object graph.

Update Operation
The Update operation is straightforward compared to the Fetch operation.
Each data entity has a DAL provider interface: IOrderDal, IOrderLineItemDal, and
IOrderLineItemPersonDal.

The editable root class (OrderEdit) implements DataPortal_Insert, DataPortal_Update,


DataPortal_DeleteSelf, and DataPortal_Delete methods that invoke the Insert, Update, and
Delete methods of the IOrderDal DAL provider object. These methods are implemented just like
the comparable methods in the PersonEdit editable root object. The only difference is that the
insert and update methods need to trigger an update of the child objects.
Here are the insert and update methods from the OrderEdit class:
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_Insert()
{
OrderDate = DateTime.Today;
LastEdit = DateTime.Today;
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IOrderDal>();
using (BypassPropertyChecks)
{
Id = dal.Insert(CustomerId, OrderDate, LastEdit);
}
FieldManager.UpdateChildren(this);
}
}

[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_Update()
{

Using CSLA 4: Data Access Page 142


Rev 1.0
LastEdit = DateTime.Today;
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IOrderDal>();
using (BypassPropertyChecks)
{
dal.Update(Id, CustomerId, OrderDate, LastEdit);
}
FieldManager.UpdateChildren(this);
}
}

The code to interact with the OrderDal DAL provider should be nothing new at this point.

Using the UpdateChildren Method


The important thing to notice about both methods is the call to the UpdateChildren method:
FieldManager.UpdateChildren(this);

The FieldManager property is a protected method from the BusinessBase class, and it provides
access to the metadata maintained about the business object’s properties. The field manager is
aware of all child properties, assuming you’ve declared them using the techniques discussed in the
Using CSLA 4: Creating Business Objects ebook.
The field manager’s UpdateChildren method loops through all properties that reference child
objects, calling the data portal’s UpdateChild method on each child object. In the sample
application, the only child object contained in an OrderEdit object is the OrderLineItems child
collection.
All child properties are updated. If your object contains more than one child property, the
UpdateChild method will loop through every child property to call the data portal’s UpdateChild
method. The order in which child objects are updated is indeterminate. If you need one child object
to update before another child object you will need to update each child explicitly.
For example, instead of calling the field manager’s UpdateChildren method, the
DataPortal_Insert and DataPortal_Update code could do this:
//FieldManager.UpdateChildren(this);
DataPortal.UpdateChild(OrderLineItems, this);

By explicitly updating each child object, you can control the order in which the updates occur.
The field manager’s UpdateChildren method and the explicit data portal UpdateChild method
both accept zero or more parameters that will be passed to the child object’s Child_Update
method.

If the child object is a collection, the data portal will only invoke a Child_Update
method. If the child object is an editable child object, the data portal will
automatically invoke a Child_Insert, Child_Update, or Child_DeleteSelf method
depending on the IsNew and IsDelete metastate property values of the child object.

It is very common for a parent object to pass this as a parameter, so the child object has access
to the parent’s properties during the update process. Most child objects require the parent object’s
Id property (or other property values) as foreign keys that must be provided to the database.

Using CSLA 4: Data Access Page 143


Rev 1.0
Updating Child Collection Objects
Because the BusinessListBase and BusinessBindingListBase provide a protected
implementation of Child_Update, there is typically no need to provide your own implementation.
Neither the OrderLineItems nor OrderLinePersons classes override the default Child_Update
method. The following steps must be performed (in order) if you do override and replace the
default implementation:

1. Set RaiseListChangedEvents to false

2. Update (and therefore delete) all items in the collection’s DeletedList

3. Clear the DeletedList

4. Update (and therefore insert or update) all items in the collection itself

5. Set RaiseListChangedEvents to its previous value

The parameter value passed to the collection’s Child_Update method is automatically passed to
each child object in the collection by the default implementation in the CSLA .NET base classes. This
means the Child_Insert, Child_Update, and Child_DeleteSelf methods in the OrderLineItem
class must accept a parameter of type OrderEdit so their method signatures match the provided
parameter types:
private void Child_Insert(OrderEdit order)
{
using (BypassPropertyChecks)
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IOrderLineItemDal>();
using (BypassPropertyChecks)
{
Id = dal.Insert(order.Id, ShipDate);
}
FieldManager.UpdateChildren(this);
}
}
}

private void Child_Update(OrderEdit order)


{
using (BypassPropertyChecks)
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IOrderLineItemDal>();
using (BypassPropertyChecks)
{
dal.Update(Id, order.Id, ShipDate);
}
FieldManager.UpdateChildren(this);
}
}
}

private void Child_DeleteSelf(OrderEdit order)


{
using (BypassPropertyChecks)
{
Using CSLA 4: Data Access Page 144
Rev 1.0
using (var dalManager = DataAccess.DalFactory.GetManager())
{
FieldManager.UpdateChildren(this);
var dal = dalManager.GetProvider<DataAccess.IOrderLineItemDal>();
dal.Delete(order.Id);
}
}
}

Notice how the order parameter’s Id property value is supplied to the DAL methods so the
database has access to the correct foreign key value to perform each insert, update, and delete
action.
Also notice how the Child_Insert and Child_Update methods call the field manager’s
UpdateChildren method to update the grandchild objects. I won’t show the code in the
OrderLinePerson class, because it is a repeat of what you’ve now seen several times in this chapter.

The end result is that the OrderEdit root object updates the database, and then cascades the
insert, update, and delete actions through its children. The child objects cascade the operation
through its children.

Delete Operation
In the update operation discussion, I focused primarily on the insert and update actions. This is
because there are several ways to approach the deletion of the entire object graph, or child and
grandchild data within a complex object graph.

Deleting the Object Graph


I’ll start by discussing deletion of the entire object graph. This can occur through immediate or
deferred deletion of the editable root object at the top of the object graph. In the example I’m
using in this chapter, that is the OrderEdit object.
When you delete a root object (or a parent object), the data for all child objects in the object
graph must also be deleted, or at least updated to reflect that the parent object data no longer
exists.
The first decision you need to make is the architectural layer that will be responsible for deleting
all this data. Options include:

 Cascading delete functionality in the database


 Stored procedure deletes all data
 Data access implementation code deletes all data
 Data access invocation code calls various DAL providers to delete all data

All of these are valid options, though the use of cascade delete or stored procedures does
require that your database support those features. You can always implement the delete
operations in your DAL provider, even if your data store isn’t a relational database, or if your
database doesn’t support cascading deletes or stored procedures.

Using CSLA 4: Data Access Page 145


Rev 1.0
In the EncapsulatedInvoke sample I chose to implement the deletion of the object graph data in
the DAL provider. The OrderEdit class contains the DataPortal_DeleteSelf and
DataPortal_Delete methods that invoke this process:
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_DeleteSelf()
{
using (BypassPropertyChecks)
DataPortal_Delete(Id);
}

[Transactional(TransactionalTypes.TransactionScope)]
private void DataPortal_Delete(int id)
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IOrderDal>();
dal.Delete(id);
// cascading delete removed all data, so recreate child collection
OrderLineItems = DataPortal.CreateChild<OrderLineItems>();
}
}

Notice the call to the DAL provider’s Delete method. This method deletes all data for the entire
object graph. I’ll walk through that method in a moment.
Before covering the DAL code itself, I want to point out the line of code that sets the
OrderLineItems property to a new child collection by calling the data portal’s CreateChild
method. This is important, because it ensures that the object graph in memory reflects the data in
the database.
Because the DAL provider’s Delete method removed all data for this object graph in the
database, the current OrderEdit object no longer has any child data in the database. This means
that whatever data was in the child collection is invalid. The simplest way to get the object graph in
sync with the state of the database is to ensure that the OrderEdit object contains an empty child
collection.

Creating a new child collection removes any reference to the previous child
collection. This means that the OrderEdit object no longer has any child or
grandchild objects.

The SqlCe DAL provider implementation of the Delete method is found in the OrderDal class:
public void Delete(int id)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
var lineItemDal = DataAccess.DalFactory.GetManager().GetProvider<IOrderLineItemDal>();
lineItemDal.DeleteAllForOrder(id);

using (var cm = ctx.Connection.CreateCommand())


{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "DELETE [Order] WHERE Id=@id";
cm.Parameters.Add("@id", id);
var rowsAffected = cm.ExecuteNonQuery();
if (rowsAffected == 0)
throw new DataNotFoundException("Order");
}

Using CSLA 4: Data Access Page 146


Rev 1.0
}
}

You can see how this method creates a command object and uses it to delete the data from the
Order table. Before it does this, however, it invokes the DeleteAllForOrder method from the
IOrderLineItemDal implementation:
var lineItemDal = DataAccess.DalFactory.GetManager().GetProvider<IOrderLineItemDal>();
lineItemDal.DeleteAllForOrder(id);

It is necessary to remove the child data in the database before removing the data in the parent
table, otherwise there’d be a violation of relational integrity. The OrderDal code could have directly
deleted the data OrderLineItems table data, but it is better to keep all data access actions for a
logical data entity within that entity’s DAL implementation.
The OrderLineItemDal class contains the DeleteAllForOrder method. This method is a little
more complex, because it performs three steps:

1. Get a list of the line item id values

2. Loop through the line item id values to delete the LineItemPersons table data for each line
item

3. Delete the line item data

There are various ways to implement these steps. My goal in this code is not to optimize the
process, but to explicitly show the steps so they are easy to understand. In a real application you
will probably optimize the process to meet your needs. Here’s the DeleteAllForOrder method:
public void DeleteAllForOrder(int orderId)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
// make a copy of all the line item id values
var lineItemIds = new List<int>();
using (var lineItems = Fetch(orderId))
{
while (lineItems.Read())
lineItemIds.Add(lineItems.GetInt32(0));
}

// loop through and delete linked person records


var lineItemPersonDal =
DataAccess.DalFactory.GetManager().GetProvider<IOrderLineItemPersonDal>();
foreach (var item in lineItemIds)
lineItemPersonDal.DeleteAllForLineItem(item);

// delete the line item data


using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "DELETE OrderLineItems WHERE OrderId=@orderId";
cm.Parameters.Add("@orderId", orderId);
cm.ExecuteNonQuery();
}
}
}

Using CSLA 4: Data Access Page 147


Rev 1.0
It is necessary to make a copy of the line item id values, because I don’t want to open a second
database connection. If a data reader object is open on a connection, you can’t execute command
objects on that same connection. To avoid that, this code gets all the line item id values from the
data reader and then disposes the data reader to free up the database connection for other uses.
The next step is to loop through those line item id values, calling the DeleteAllForLineItem
method of the IOrderLineItemPersonDal DAL provider. This DeleteAllForLineItem method
deletes the OrderLineItemPersons table data for the specified line item:
public void DeleteAllForLineItem(int lineItemId)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "DELETE OrderLineItemPersons WHERE LineItemId=@lineItemId";
cm.Parameters.Add("@lineItemId", lineItemId);
cm.ExecuteNonQuery();
}
}
}

Because there are no great-grandchild objects or data relationships, this method is


straightforward. If you do have great-grandchild objects and data, this method would be
implemented much like the DeleteAllForOrder method.
Back in the DeleteAllForOrder method, once the line item child data has been deleted, the line
item rows themselves are deleted from the OrderLineItems table.
The end result is that when an OrderEdit object is deleted (immediate or deferred), all data for
the object graph is removed from the database, and the business object is reset so it has no child or
grandchild object references in memory.

Deleting Child and Grandchild Objects


It is also possible to remove individual OrderLineItem child objects or OrderLinePerson grandchild
objects from the object graph. This is done by removing the child or grandchild object from its
parent collection. Remember that removing an object from an editable collection results in that
child object being moved to the collection’s DeletedList, and the child’s IsDeleted property being
set to true.

Any time an object is removed from an editable list, the child object’s IsDeleted
property is set to true, and the object is moved to the collection’s DeletedList.

When the collection is updated, the first step in the collection’s Child_Update method is to
“update” all items in the DeletedList. Because every object in the DeletedList has an IsDeleted
value of true, the data portal will invoke that child object’s Child_DeleteSelf method.
The OrderLineItem child class has a Child_DeleteSelf method:
private void Child_DeleteSelf(OrderEdit order)
{
using (BypassPropertyChecks)
{
using (var dalManager = DataAccess.DalFactory.GetManager())

Using CSLA 4: Data Access Page 148


Rev 1.0
{
FieldManager.UpdateChildren(this);
var dal = dalManager.GetProvider<DataAccess.IOrderLineItemDal>();
dal.Delete(Id);
}
Persons = DataPortal.CreateChild<OrderLinePersons>();
}
}

Because an OrderLineItem object may contain child objects, it calls the field manager’s
UpdateChildren method to update its children before updating itself. This ensures that any pending
data operations in its OrderLinePerson child objects occur before the line item data is deleted.
You might wonder why this is important, but remember that a “delete” operation doesn’t always
delete the data. Sometimes a “deleting” data means setting a column value in a table to “inactive”
or “deleted” and the data isn’t physically removed. Because of this, it is important to ensure all data
updates occur to keep the object graph and database in sync.
Once all the data has been updated and/or deleted, the OrderLineItem object’s Persons
property is reset to an empty collection. This ensures that the object graph in memory matches the
state of the database, because a deleted line item obviously can’t have any child data.
The Delete method in the IOrderLineItemDal provider is responsible for deleting the line item
data, and any child data for the line item. The SqlCe provider implementation looks like this:
public void Delete(int lineItemId)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
// delete OrderLineItemPersons data
var lineItemPersonDal =
DataAccess.DalFactory.GetManager().GetProvider<IOrderLineItemPersonDal>();
lineItemPersonDal.DeleteAllForLineItem(lineItemId);

// delete line item


using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "DELETE OrderLineItems WHERE Id=@lineItemId";
cm.Parameters.Add("@lineItemId", lineItemId);
cm.ExecuteNonQuery();
}
}
}

This method invokes the same DeleteAllForLineItem method I discussed earlier, ensuring that
all child data in the OrderLineItemPersons is deleted before the line item row is deleted.
The OrderLinePerson class also has a Child_DeleteSelf method:
private void Child_DeleteSelf(OrderLineItem lineItem)
{
using (BypassPropertyChecks)
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IOrderLineItemPersonDal>();
dal.Delete(LineItemId, PersonId);
}
}
}

Using CSLA 4: Data Access Page 149


Rev 1.0
Because this object has no child objects, the code is simpler. It calls the DAL provider’s Delete
method to delete the row of data corresponding to this business object. Here’s the Delete method
in the SqlCe provider’s OrderLineItemPersonDal class:
public void Delete(int lineItemId, int personId)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText =
"DELETE OrderLineItemPersons WHERE LineItemId=@lineItemId AND PersonId=@personId";
cm.Parameters.Add("@lineItemId", lineItemId);
cm.Parameters.Add("@personId", personId);
cm.ExecuteNonQuery();
}
}
}

As you can see, deleting an individual child object is straightforward. Deleting an object with
children is more complex, because the application must ensure that the data for that object, and its
child objects, are properly deleted.

DTO Interface
The overall process and code structure is the same for a DTO-based interface as for the data reader
interface. I won’t repeat the walkthrough of the code.
Each parent create operation is responsible for initializing the properties of the parent object,
including properties that refer to child objects. This means the create operation for the parent also
creates the child. Similarly, the create of a child causes the creation of any grandchild objects.
The Fetch operation for a root object retrieves that object’s data, including its child objects. The
DAL provider is invoked by the root object’s DataPortal_Fetch method, and each child implements
a Child_Fetch method to load the child data. If there are grandchild objects, their data is typically
retrieved with individual database calls, and the objects are loaded with data in Child_Fetch
methods.
When a root object is saved, the data portal’s Update or BeginUpdate method is invoked,
resulting in a call to a DataPortal_XYZ method on the root object. If the root object is an editable
root, the data portal will invoke DataPortal_Insert, DataPortal_Update, or
DataPortal_DeleteSelf based on the metastate of the root object. If the root object is an editable
list, the data portal will call the object’s DataPortal_Update method. Each editable child and
grandchild object will implement Child_Insert, Child_Update, and Child_DeleteSelf methods to
interact with the DAL provider to perform the correct data action. Each editable child list may
override the Child_Update method, but the implementation in the BusinessListBase and
BusinessBindingListBase classes are usually sufficient.

In each case, the DataPortal_XYZ and Child_XYZ methods invoke the DAL provider to interact
with the database, typically passing DTO objects into the DAL methods.
When immediate deletion is implemented by a root object, the data portal’s Delete or
BeginDelete method is invoked, resulting in a call to the DataPortal_Delete method. This method
is responsible for deleting the root object’s data, along with any child data.
Using CSLA 4: Data Access Page 150
Rev 1.0
Remember that a “delete” operation may or may not delete data in the database. Instead of
deleting data, the delete implementation in a DAL provider might mark rows as “inactive” or
“deleted” by setting a column value.
Again, you can review the code in the EncapsulatedInvokeDto project and compare it to the
EncapsulatedInvoke project. You’ll see that the structure of the DAL interfaces is the same, the
methods just return and accept DTO types instead of IDataReader and primitive parameters.
The primary value of the DTO approach over the IDataReader approach is that there’s a higher
level of abstraction because the DAL interface is not coupled to ADO.NET in any way. The primary
drawbacks are that this approach requires more code, and adds some overhead as data is copied
into and out of the DTO objects as it flows between the Business and Data Access layers.
At this point you should understand how a complex object graph consisting of root, child, and
grandchild objects is persisted using the encapsulated invoke data portal model.

Command Object Persistence


The OrderShipper class is an example of command object stereotype that implements the concept
of shipping an order. As I discussed in the Using CSLA 4: Creating Business Objects ebook, the
command object stereotype is used to represent behaviors or actions other than viewing or editing
data.
A user may use an OrderInfo object to view order data, and an OrderEdit object to edit order
data. But when it comes to shipping an order, that may be a completely different user process or
scenario, and so you may implement a command object that contains the behaviors necessary to
ship an order.
Command objects can implement code that runs on the client before calling the application
server, code that runs on the application server, and code that runs on the client after the
application server is complete.
The server-side code may or may not interact with the database. It may interact with other
business objects on the server, or invoke a workflow, or interact with the server’s file system. Your
server-side code can perform any operation, algorithm, or behavior that is appropriate within the
context of the application server.
The OrderShipper class can be found in the Library.Net project in the EncapsulatedInvoke
and EncapsulatedInvokeDto solutions. This class illustrates the coding structure of a command
object, with placeholder comments indicating where you would interact with the database, invoke a
workflow, or perform other server-side operations.

Data Reader Interface


The DataAccess project in the EncapsulatedInvoke solution includes the IOrderDal interface:
public interface IOrderDal
{
int ShipOrder(int id);
IDataReader Fetch(int id);
int Insert(int customerId, DateTime? orderDate, DateTime? lastDate);
void Update(int id, int customerId, DateTime? orderDate, DateTime? lastDate);
void Update(int id, DateTime? lastDate);

Using CSLA 4: Data Access Page 151


Rev 1.0
void Delete(int id);
}

You’ve seen this interface earlier in this chapter. In this case I am focusing on the ShipOrder
method. This method will be implemented by each DAL provider to perform the data access
necessary to ship an order.
The DataPortal_Execute method in the OrderShipper class will invoke this method. As I
mentioned earlier, the DataPortal_Execute method does not have to invoke the DAL at all. It might
invoke a server-side workflow, update some files, invoke a service, or perform other actions. In fact,
it could do all of those actions if that is necessary to implement the behavior of the command.
The DataAccess.Mock, DataAccess.SqlCe, and DataAccess.SqlEf projects contain the OrderDal
classes I discussed earlier. Each class implements this ShipOrder method in a manner appropriate
for the specific data access technology supported by the provider.

Execute Operation
The execute operation starts with the client calling the Ship method in the OrderShipper class:
public static void Ship(int orderId, EventHandler<DataPortalResult<OrderShipper>> callback)
{
var cmd = new OrderShipper(orderId);
DataPortal.BeginExecute<OrderShipper>(cmd, callback);
}

#if !SILVERLIGHT
public static OrderShipper Ship(int orderId)
{
var cmd = new OrderShipper(orderId);
return DataPortal.Execute<OrderShipper>(cmd);
}
#endif

There are two overloads of the Ship method, one synchronous and the other asynchronous.
These are essentially static factory methods, but instead of retrieving an editable or read-only
object, they invoke the data portal’s Execute or BeginExecute method to execute the command.
Notice that the first thing these methods do is to create and initialize an instance of the
OrderShipper command. If the OrderShipper object needed to do some work before going to the
server, these factory methods would interact with the object prior to calling the data portal’s
Execute or BeginExecute method.

Similarly, if the OrderShipper object needed to do some work after coming back from the
server, these factory methods would interact with the object returned from the data portal to
perform that work.
The client-side data portal invokes the server-side data portal based on the client configuration.
The server-side data portal calls the DataPortal_Execute method in the OrderShipper object:
protected override void DataPortal_Execute()
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IOrderDal>();
ShippingNumber = dal.ShipOrder(OrderId);
}
}

Using CSLA 4: Data Access Page 152


Rev 1.0
In this simple implementation the method acquires a reference to the currently configured DAL
provider and invokes the ShipOrder method. The ShipOrder method is essentially the same in all
three DAL provider projects:
public int ShipOrder(int id)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
// ship order and generate shipping number
Update(id, DateTime.Today);

var lineItemDal = DataAccess.DalFactory.GetManager().GetProvider<IOrderLineItemDal>();


var lineItems = lineItemDal.Fetch(id);
while (lineItems.Read())
if (lineItems.IsDBNull(lineItems.GetOrdinal("ShipDate")))
{
lineItemDal.Update(
lineItems.GetInt32(lineItems.GetOrdinal("Id")),
lineItems.GetInt32(lineItems.GetOrdinal("OrderId")),
DateTime.Today);
}
return 123;
}
}

The SqlCe and SqlEf implementations wrap the code in a using block to ensure the same
database connection or EF object context is appropriately reused by the entire series of data access
actions.
The ShipOrder method calls the Update method of the OrderDal class to update the order with a
new OrderEditDate value:
public void Update(int id, DateTime? lastDate)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "UPDATE [Order] SET OrderEditDate=@orderEditDate WHERE Id=@id";
cm.Parameters.Add("@id", id);
cm.Parameters.Add("@orderEditDate", lastDate);
var rowsAffected = cm.ExecuteNonQuery();
if (rowsAffected == 0)
throw new DataNotFoundException("Order");
}
}
}

The ShipOrder method then loops through the line items for the order, updating the ShipDate
of each line item by calling the existing Update method implemented in the IOrderLineItemDal
implementation. It even uses the existing Fetch method to get the list of line items.
Although there are other ways to write this code that might be more efficient, I am using this
code to illustrate how a command implementation can leverage existing code to perform
comparatively complex actions.

DTO Interface
The DataAccess project in the EncapsulatednvokeDto solution includes the IOrderDal interface,
with a definition for the ShipOrder method:
Using CSLA 4: Data Access Page 153
Rev 1.0
public interface IOrderDal
{
int ShipOrder(int id);
OrderDto Fetch(int id);
void Insert(OrderDto data);
void Update(OrderDto data);
void Delete(int id);
}

This method signature is the same as in the data reader implementation, but the
implementation of this method in each DAL provider will be DTO-based.

Execute Operation
The execute operation follows the same general flow as with the data reader implementation. The
OrderShipper class implements Ship methods that invoke the data portal’s Execute or
BeginExecute methods. The client-side data portal calls the server-side data portal, and the server-
side data portal invokes the command object’s DataPortal_Execute method.
The DataPortal_Execute method is identical to the one in the data reader implementation,
because the ShipOrder method signature is also identical.
The ShipOrder method implementation in each DAL provider is different, because it makes use
of the existing DTO-based methods implemented in each project. For example, this is the
implementation in the DataAccess.SqlEf project:
public int ShipOrder(int id)
{
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
// ship order and generate shipping number
var order = Fetch(id);
order.OrderEditDate = DateTime.Today;
Update(order);

var lineItemDal = DataAccess.DalFactory.GetManager().GetProvider<IOrderLineItemDal>();


var lineItems = lineItemDal.Fetch(id);
foreach (var item in lineItems)
if (!item.ShipDate.HasValue)
{
item.ShipDate = DateTime.Today;
lineItemDal.Update(item);
}
return 123;
}
}

The existing Fetch method in the OrderDal class is used to retrieve an OrderDto, and then the
Update method is used to update the order data with a new OrderEditDate value.

The order’s line items are then retrieved by using the IOrderLineItemDal implementation, and
each line item’s ShipDate value is updated.
All of this work is done within a using block to ensure that the same database connection or
object context is reused by the various data access actions.
At this point you should understand how the DataPortal_Execute method of a command object
is invoked by the server-side data portal. This method might interact with the DAL provider as
shown in these examples, or it might perform other actions such as running a workflow or
interacting with other server-side resources.
Using CSLA 4: Data Access Page 154
Rev 1.0
Unit of Work Object Persistence
In the Using CSLA 4: Creating Business Objects ebook I discussed the concept of a unit of work
object. There are two basic types of unit of work:

1. Retrieving objects

2. Updating objects

Perhaps the most common scenario is to use a unit of work object that retrieves other objects.
In many applications it is necessary to retrieve multiple objects to correctly populate a UI or
implement an algorithm. It can be difficult to ensure that all necessary objects are available at the
same time when you are using the asynchronous data portal. Because Silverlight and WP7
applications must use the asynchronous data portal, and because WPF applications often use it to
maintain a responsive UI, it is important to understand how to implement this type of unit of work
object.
A unit of work object that performs object retrieval is typically implemented as a subclass of the
ReadOnlyBase class. This type of unit of work is a special case of a read-only object, where the
properties of the unit of work object are instances of other business objects. I’ll walk through an
example of this type of unit of work later in this section.
A less common scenario is where multiple editable root objects must be updated as part of a
single server call. Typically this is because these root objects need to be updated within the context
of a single database transaction, and as the result of a single user gesture, such as the user clicking a
Save button.
A unit of work object that performs an update of objects is implemented as a command object.
In this case the command object’s properties are instances of the editable root objects that are to
be saved.
In most cases there is no specific data access or persistence code for a unit of work object.
Instead, the unit of work object will make use of the existing synchronous factory methods
implemented by the objects being retrieved, or the synchronous Save method on the editable root
objects being updated.
Because of this, there is no difference in implementation between the data reader and DTO-
based implementations of any unit of work types.

Retreiving Objects
The PersonEditUoW class in the Library.Net projects of the EncapsulatedInvoke and
EncapsulatedInvokeDto solutions. This class implements a read-only object stereotype, with
properties that contain other business objects:
[Serializable]
public class PersonEditUoW : ReadOnlyBase<PersonEditUoW>
{
public static readonly PropertyInfo<PersonEdit> PersonEditProperty =
RegisterProperty<PersonEdit>(c => c.PersonEdit);
public PersonEdit PersonEdit
{
get { return GetProperty(PersonEditProperty); }

Using CSLA 4: Data Access Page 155


Rev 1.0
private set { LoadProperty(PersonEditProperty, value); }
}

public static readonly PropertyInfo<CategoryList> CategoryListProperty =


RegisterProperty<CategoryList>(c => c.CategoryList);
public CategoryList CategoryList
{
get { return GetProperty(CategoryListProperty); }
private set { LoadProperty(CategoryListProperty, value); }
}

public static void GetPersonEditUoW(


int personId, EventHandler<DataPortalResult<PersonEditUoW>> callback)
{
DataPortal.BeginFetch<PersonEditUoW>(personId, callback);
}

#if !SILVERLIGHT
public static PersonEditUoW GetPersonEditUoW(int personId)
{
return DataPortal.Fetch<PersonEditUoW>(personId);
}

private void DataPortal_Fetch(int personId)


{
PersonEdit = PersonEdit.GetPersonEdit(personId);
CategoryList = CategoryList.GetCategoryList();
}
#endif
}

The important thing to recognize is that this is a normal read-only implementation. It has
synchronous and asynchronous static factory methods that return an instance of the
PersonEditUoW type.

That resulting object has PersonEdit and CategoryList properties, each of which provide
access to a business object. You might write UI code like this:
var uow = PersonEditUoW.GetPersonEditUoW(personId);
var personEdit = uow.PersonEdit;
var categoryList = uow.CategoryList;

The result is that the UI code can guarantee that it has access to both the PersonEdit and
CategoryList objects at the same time, even if the server call is asynchronous. Here’s the UI code
with an asynchronous call:
PersonEdit person = null;
CategoryList catList = null;
var uow = PersonEditUoW.GetPersonEditUoW(personId, (o, e) =>
{
if (e.Error != null)
throw e.Error;
person = e.Object.PersonEdit;
catList = e.Object.CategoryList;
});

In many cases this can be critically important, because data binding may require both objects at
the same time to properly bind and render the UI.
Back in the PersonEditUoW class, the most interesting part of the code is the DataPortal_Fetch
method that runs on the server:
private void DataPortal_Fetch(int personId)
{
Using CSLA 4: Data Access Page 156
Rev 1.0
PersonEdit = PersonEdit.GetPersonEdit(personId);
CategoryList = CategoryList.GetCategoryList();
}

This method doesn’t invoke any DAL directly. Instead, it calls the existing synchronous static
factory methods already implemented by the PersonEdit and CategoryList classes.
Those factory methods invoke the “client-side” data portal. Because the code is already running
on the server, the “client-side” data portal is running on the server. When the client-side data portal
invokes the server-side data portal, it does so locally, without crossing any network boundary. This
is because the code is already running on the server, and the data portal configuration on the
application server is to run locally.
The server-side data portal invokes the DataPortal_Fetch methods on the PersonEdit and
CategoryList objects as normal. Those methods act no differently when invoked from the UI or
from another business object.
The result is that the unit of work object’s properties contain the two business objects. When
the unit of work object is returned to the client through the data portal, the calling code will have
access to those objects.

Updating Objects
The PersonsUpdater class in the Library.Net project is a command object that updates two
PersonEdit objects as a unit of work. Both PersonEdit objects are updated as part of the same
database transaction, so if either update fails they are both rolled back.
Here’s the code for the unit of work command class:
[Serializable]
public class PersonsUpdater : CommandBase<PersonsUpdater>
{
public static readonly PropertyInfo<PersonEdit> Person1Property =
RegisterProperty<PersonEdit>(c => c.Person1);
public PersonEdit Person1
{
get { return ReadProperty(Person1Property); }
private set { LoadProperty(Person1Property, value); }
}

public static readonly PropertyInfo<PersonEdit> Person2Property =


RegisterProperty<PersonEdit>(c => c.Person2);
public PersonEdit Person2
{
get { return ReadProperty(Person2Property); }
private set { LoadProperty(Person2Property, value); }
}

public static void Update(


PersonEdit person1, PersonEdit person2, EventHandler<DataPortalResult<PersonsUpdater>> callback)
{
var cmd = new PersonsUpdater { Person1 = person1, Person2 = person2 };
DataPortal.BeginExecute<PersonsUpdater>(cmd, callback);
}

#if !SILVERLIGHT
public static PersonsUpdater Update(PersonEdit person1, PersonEdit person2)
{
var cmd = new PersonsUpdater { Person1 = person1, Person2 = person2 };
return DataPortal.Execute<PersonsUpdater>(cmd);
}
Using CSLA 4: Data Access Page 157
Rev 1.0
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_Execute()
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
Person1 = Person1.Save();
Person2 = Person2.Save();
}
}
#endif
}

As with any command stereotype implementation, this class defines properties for the values
that flow from the client to the server, and then back to the client. In this case the properties each
contain a PersonEdit object.
The static factory methods create an instance of the PersonsUpdater class, and then execute
that command by invoking the data portal’s Execute or BeginExecute method.
The most interesting part of the code is the DataPortal_Execute method:
[Transactional(TransactionalTypes.TransactionScope)]
protected override void DataPortal_Execute()
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
Person1 = Person1.Save();
Person2 = Person2.Save();
}
}

Notice how the Transactional attribute is used to ensure that a TransactionScope object is
created before this method is invoked. This means that all actions taken within this method are
protected by a transaction.
Also, it is important to note the using block for the DalManager object that wraps all the work
done in this method. This ensures that a database connection or object context is kept open for
reuse as both PersonEdit objects are saved.
Each PersonEdit object is saved with a call to its synchronous Save method. The Save method
invokes the “client-side” data portal’s Update method. Because the code is already running on the
server, the client-side data portal is running on the server. When the client-side data portal invokes
the server-side data portal, it does so locally, without crossing any network boundary. This is
because the code is already running on the server, and the data portal configuration on the
application server is to run locally.
The server-side data portal invokes the appropriate DataPortal_XYZ method of the PersonEdit
object to perform the insert, update, or delete operation. This is based on the business object’s
metastate. I described this process earlier in this chapter when I discussed persistence of an
editable object.
At this point you should understand how unit of work objects are implemented for retrieving
and updating objects.

Using CSLA 4: Data Access Page 158


Rev 1.0
Read-Only List Persistence
The PersonList class is an example of a read-only root list that contains PersonInfo read-only
objects. These classes can be found in the Library.Net project in the EncapsulatedInvoke and
EncapsulatedInvokeDto solutions.
A read-only root list supports only the Fetch operation. Because the intent of a read-only list is to
return a set of read-only data for use by the calling code, there is no value in the create, update, or
delete operations.

Data Reader Interface


In the EncapsulatedInvoke project, the DataAccess project defines the IPersonDal interface that
you’ve seen previously:
public interface IPersonDal
{
IDataReader Fetch();
IDataReader Fetch(int id);
int Insert(string firstName, string lastName);
void Update(int id, string firstName, string lastName);
void Delete(int id);
}

The Fetch method returns an IDataReader instance that contains person data from the
database. This data can be used to populate the PersonList read-only collection.

Fetch Operation
The Fetch operation starts in the static factory method of the PersonList class:
public static void GetPersonList(EventHandler<DataPortalResult<PersonList>> callback)
{
DataPortal.BeginFetch<PersonList>(callback);
}

#if !SILVERLIGHT
public static PersonList GetPersonList()
{
return DataPortal.Fetch<PersonList>();
}
#endif

As you should expect, there are synchronous and asynchronous factory methods that invoke the
data portal’s Fetch and BeginFetch methods. As with any other object stereotype, the data portal
ultimately invokes the DataPortal_Fetch method on the PersonList object:
private void DataPortal_Fetch()
{
IsReadOnly = false;
var rlce = RaiseListChangedEvents;
RaiseListChangedEvents = false;
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IPersonDal>();
using (var data = dal.Fetch())
while (data.Read())
{
var item = DataPortal.FetchChild<PersonInfo>(data);
Add(item);
}

Using CSLA 4: Data Access Page 159


Rev 1.0
}
RaiseListChangedEvents = rlce;
IsReadOnly = true;
}

Because this object is a read-only list, items can not normally be added or removed from the
collection. To “unlock” the collection, the IsReadOnly property must be set to false. The setter for
this property is protected, so code outside the business class can’t change the value.
Once the collection’s IsReadOnly property is set to false, loading the collection with data is
done in exactly the same manner as in an editable root list. The RaiseListChangedEvents property
is set to false, the data is retrieved by invoking the DAL, and the data portal’s FetchChild method
is used to create and load objects that are added to the list.
Each DAL provider implements the Fetch method defined by the IPersonDal interface in its
PersonDal class. For example, the SqlEf provider’s implementation looks like this:
public System.Data.IDataReader Fetch()
{
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var data = from r in ctx.ObjectContext.People
select r;
return new ListDataReader<Person>(data);
}
}

The data is retrieved from the database using an EF query, and the results of that query are
wrapped in a ListDataReader so they are available as an IDataReader object.
The SqlCe provider implementation is more direct:
public System.Data.IDataReader Fetch()
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
var cm = ctx.Connection.CreateCommand();
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "SELECT Id,FirstName,LastName FROM Person";
return cm.ExecuteReader();
}
}

This implementation executes a SELECT command against the database and returns the resulting
data reader object.
Back in the PersonList class, the DataPortal_Fetch method loops through the results of the
DAL Fetch method, calling the data portal’s FetchChild method to create and load each child
object with data from the data reader. This causes the data portal to invoke the Child_Fetch
method defined in the PersonInfo class:
#if !SILVERLIGHT
private void Child_Fetch(System.Data.IDataReader data)
{
Id = data.GetInt32(data.GetOrdinal("Id"));
Name = string.Format("{0} {1}",
data.GetString(data.GetOrdinal("FirstName")),
data.GetString(data.GetOrdinal("LastName")));
}
#endif

Using CSLA 4: Data Access Page 160


Rev 1.0
This method accepts the data reader as a parameter, with the assumption that the data reader
will be pointing to the correct row of data for this object. The business object’s properties are then
loaded with data from the data reader.
Notice that this code doesn’t use BypassPropertyChecks to suppress rule processing. This is
because the property setters in a read-only class always use the LoadProperty helper method. For
example, here’s the Name property declaration in the PersonInfo class:
public static readonly PropertyInfo<string> NameProperty = RegisterProperty<string>(c => c.Name);
public string Name
{
get { return GetProperty(NameProperty); }
private set { LoadProperty(NameProperty, value); }
}

The property getter uses the GetProperty helper method, so this operation is subject to normal
authorization rules.
The setter is private in scope, and uses the LoadProperty helper method. This makes the
property read-only, so the value can only be changed by code in the PropertyInfo object, and it
means that no business, validation, or authorization rules are run as the property value is changed.
The end result is that the PersonList object is loaded with PersonInfo objects, and then the
IsReadOnly property is set back to true so the collection can’t be changed.

DTO Interface
The EncapsulatedInvokeDto solutions’s DataAccess project defines the IPersonDal interface:
public interface IPersonDal
{
List<PersonDto> Fetch();
PersonDto Fetch(int id);
void Insert(PersonDto data);
void Update(PersonDto data);
void Delete(int id);
}

As with the data reader implementation, this interface defines a Fetch method that returns a
List<PersonDto> object, and that data can be used to populate a read-only PersonList collection.

Fetch Operation
The overall flow of the Fetch operation is the same for a DTO-based model as for the data reader
model. The DataPortalFetch method in the PersonList class is slightly different, because it creates
the child objects using data from the List<T> instead of a data reader:
private void DataPortal_Fetch()
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.IPersonDal>();
var data = dal.Fetch();
IsReadOnly = false;
var rlce = RaiseListChangedEvents;
RaiseListChangedEvents = false;
foreach (var item in data)
Add(DataPortal.FetchChild<PersonInfo>(item));
RaiseListChangedEvents = true;
IsReadOnly = true;
Using CSLA 4: Data Access Page 161
Rev 1.0
}
}

Similarly, the Child_Fetch method in the PersonInfo class is slightly different:


private void Child_Fetch(DataAccess.PersonDto data)
{
Id = data.Id;
Name = string.Format("{0} {1}",
data.FirstName, data.LastName);
}

This method loads the business object’s properties with the data from the DTO.
The Fetch method implementation in each DAL provider is different as well. For example, the
SqlCe provider’s PersonDal class has this code:
public List<PersonDto> Fetch()
{
var result = new List<PersonDto>();
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
var cm = ctx.Connection.CreateCommand();
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "SELECT Id,FirstName,LastName FROM Person";
using (var dr = cm.ExecuteReader())
{
while (dr.Read())
result.Add(new PersonDto
{ Id = dr.GetInt32(0), FirstName = dr.GetString(1), LastName = dr.GetString(2) });
}
}
return result;
}

The data is retrieved from the database, and is then used to create the List<PersonDto>
collection that is returned as a result.

Name-Value List Persistence


A name-value list is a special type of read-only list, where the type of the child objects contained in
the list is pre-defined by the NameValueListBase or NameValueBindingListBase classes. This child
type defines two properties, a Key property containing the key or name value, and a Value property
containing the display value.
The purpose of the name-value list stereotype is to support common application scenarios
where a combobox or listbox control presents a list of display values, and where the corresponding
key value is bound to a property of a business object.
The name-value list stereotype has become less important over time, because many modern UI
designs present more than a single display value. Most XAML and HTML interfaces display images
and other rich data in their lists. In such scenarios you should use a standard read-only list with a
more complex read-only child type to meet the application requirements.
The CategoryList type in the Library.Net project in the EncapsulatedInvoke and
EncapsulatedInvokeDto projects is an implementation of the name-value list stereotype. As with a
standard read-only list, the only data portal operation supported by a name-value list is the Fetch
operation.

Using CSLA 4: Data Access Page 162


Rev 1.0
Data Reader Interface
The EncapsulatedInvoke solution’s DataAccess project defines the ICategoryDal interface that
represents the category data entity:
public interface ICategoryDal
{
IDataReader Fetch();
int Insert(string name);
void Update(int id, string name);
void Delete(int id);
}

The Fetch method is used to populate the CategoryList name-value list object. Each DAL
provider implements this method, returning a data reader with the category data needed to
populate the business object.

Fetch Operation
The Fetch operation starts with the typical static factory methods in the CategoryList class:
public static void GetCategoryList(EventHandler<DataPortalResult<CategoryList>> callback)
{
DataPortal.BeginFetch<CategoryList>(callback);
}

#if !SILVERLIGHT
public static CategoryList GetCategoryList()
{
return DataPortal.Fetch<CategoryList>();
}
#endif

Based ont this code, the data portal invokes the DataPortal_Fetch method on the
CategoryList object:
private void DataPortal_Fetch()
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.ICategoryDal>();
using (var data = dal.Fetch())
{
IsReadOnly = false;
var rlce = RaiseListChangedEvents;
RaiseListChangedEvents = false;
while (data.Read())
{
Add(new NameValuePair(
data.GetInt32(data.GetOrdinal("Id")), data.GetString(data.GetOrdinal("Category"))));
}
RaiseListChangedEvents = rlce;
IsReadOnly = true;
}
}
}

Because a name-value list is a read-only list, the IsReadOnly property must be set to false to
“unlock” the list, and then set back to true after the collection has been loaded with data.
As with any collection object, the RaiseListChangedEvents is set to false and then restored to
its original value after the data load is complete.

Using CSLA 4: Data Access Page 163


Rev 1.0
The DAL provider’s Fetch method is invoked to get a data reader containing the data necessary
to populate the collection with data. The interesting part of the code is where the NameValuePair
child objects are created:
Add(new NameValuePair(
data.GetInt32(data.GetOrdinal("Id")), data.GetString(data.GetOrdinal("Category"))));

The business object is of type NameValueListBase<K, V>. The NameValueListBase class defines
a NameValuePair to have a Key property of type K and a Value property of type V. In this case, the
CategoryList is of type NameValueListBase<int, string> , so the Key property is type int, and
the Value property is type string.
Having this pre-defined NameValuePair type simplifies the code necessary to create a name-
value list, because your code can simply use this existing type, loading each object with data and
adding it to the collection.
The Fetch method in each DAL provider is different, but is responsible for returning a valid data
reader. For example, the SqlEf implementation looks like this:
public System.Data.IDataReader Fetch()
{
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var data = from r in ctx.ObjectContext.CategoryTables
select r;
return new ListDataReader<CategoryTable>(data);
}
}

An EF query is used to retrieve the data, and the results of that query are wrapping in an object
that implements the IDataReader interface to conform to the requirements of the ICategoryDal
interface.

DTO Interface
The DataAccess project in the EncapsulatedInvokeDto defines an ICategoryDal interface for the
category data entity:
public interface ICategoryDal
{
List<CategoryDto> Fetch();
void Insert(CategoryDto data);
void Update(CategoryDto data);
void Delete(int id);
}

It also defines the CategoryDto type returned in a list from the Fetch method:
public class CategoryDto
{
public int Id { get; set; }
public string Category { get; set; }
}

These types are used to implement the CategoryList class’s DataPortal_Fetch and DAL
provider code in the solution.

Using CSLA 4: Data Access Page 164


Rev 1.0
Fetch Operation
The overall flow of the Fetch operation is the same in a DTO-based model as in the data reader
model. The DataPortal_Fetch method in the CategoryList class uses the DTO types instead of a
data reader:
private void DataPortal_Fetch()
{
using (var dalManager = DataAccess.DalFactory.GetManager())
{
var dal = dalManager.GetProvider<DataAccess.ICategoryDal>();
var data = dal.Fetch();
IsReadOnly = false;
var rlce = RaiseListChangedEvents;
RaiseListChangedEvents = false;
foreach (var item in data)
Add(new NameValuePair(item.Id, item.Category));
RaiseListChangedEvents = rlce;
IsReadOnly = true;
}
}

And the DTO type is used to create the list returned from each DAL provider. For example, the
SqlEf implementation looks like this:
public List<CategoryDto> Fetch()
{
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var data = from r in ctx.ObjectContext.CategoryTables
select new CategoryDto { Id = r.Id, Category = r.Category };
return data.ToList();
}
}

The data is retrieved using an EF query that generates a list of CategoryDto objects. That list is
returned as a result from the Fetch method.
At this point you should understand how to implement the Fetch operations for a read-only list
and a name-value list.
In this chapter I walked through each business object stereotype, demonstrating how to use the
encapsulated invoke data portal model to implement persistence for each stereotype. In the next
chapter I will walk through the same stereotypes, showing how to implement persistence using the
factory implementation data portal model.

Using CSLA 4: Data Access Page 165


Rev 1.0
Chapter 6:
Factory Implementation
In the factory implementation model the data portal creates an instance of an object factory type
you define for each type of business class. This object factory is responsible for creating instances of
the business objects, and for implementing the data access code necessary to retrieve or save the
business object data.
The object factory classes are usually contained in a separate DAL project that is dynamically
loaded when needed by the server-side data portal. To support a pluggable DAL, you will typically
implement a custom factory loader class that loads the correct DAL assembly based on the
application’s configuration.
Figure 15 illustrates the relationships between the data portal, the factory loader, and the
individual DAL assemblies that contain object factory implementations.

Figure 15. Assemblies involved in loading an object factory DAL


The dashed lines in the arrows represent dynamically loaded assemblies. The specific types to be
loaded are usually defined in the app.config or web.config file for the AppDomain where the
server-side data portal code is running. For example, the server-side data portal uses the
CslaObjectFactoryLoader configuration value in the appSettings element to identify the type of
any custom factory loader you might supply. For example:
<appSettings>
<add key="CslaObjectFactoryLoader" value="DataAccess.FactoryLoader,DataAccess"/>
</appSettings>

The default factory loader used by CSLA .NET (if you don’t specify your own) uses the factory
name value from each ObjectFactory attribute on a business class as an assembly qualified type
for the object factory type. For example, a business class might have the following attribute:
[Csla.Server.ObjectFactory("DataAccess.SqlCe.PersonDal,DataAccess.SqlCe")]
[Serializable]
public class PersonEdit : BusinessBase<PersonEdit>

Using CSLA 4: Data Access Page 166


Rev 1.0
The default factory loader will dynamically load the DataAccess.Sql assembly as the concrete
DAL, and will then use the PersonDal class in that assembly as the object factory type.
In this chapter I will demonstrate how to create a custom factory loader. When you create a
custom factory loader, you can interpret the factory name parameter from the ObjectFactory
attribute in any way you choose. In most cases, a custom factory loader will combine the factory
name parameter value with application configuration information to determine the assembly and
type name for each object factory type. The result is a pluggable DAL model.
Each DAL assembly maintains a reference to the business library assembly, because the object
factory code is responsible for creating and persistenting all business object instances. These
references are illustrated in Figure 16.

Figure 16. Concrete DAL assemblies reference business assemblies


It is important to understand that the business library and business classes do not have any
reference to the DAL implementations or the factory types. The business classes use the
ObjectFactory attribute to provide the data portal with the name of the object factory that should
be used to persist the business object, and the data portal uses the factory loader to dynamically
load the correct factory assembly and type.
The business library can be deployed on a smart client workstation or web server, without
deploying the DAL assemblies to the client workstation in 3- or 4-tier physical deployments.

In 1- or 2-tier physical deployments the DAL assemblies must also be on the client
workstation, because the “server-side” data portal components will run on the
client.

It is important to understand that the RunLocal attribute and ProxyMode.LocalOnly options will
not work if the DAL assemblies are only deployed to the server in a 3- or 4-tier deployment. The
object factory for every business class will include the create operation implementation, and if the
object factory is only deployed to the application server, then all object creation must occur on the
application server.
The business classes will not implement DataPortal_XYZ or Child_XYZ methods when using a
factory implementation or factory invocation data portal model. This is because the data access is
handled by the object factories.

Using CSLA 4: Data Access Page 167


Rev 1.0
To implement persistence, the object factory will interact with the private state and metastate
of the business objects. This breaks encapsulation and tightly couples the factory objects to their
corresponding business objects.
The Csla.Server namespace includes the ObjectFactory base class. You can subclass
ObjectFactory when creating your object factory classes. This base class provides a set of
protected methods that make it easier to break encapsulation and interact with the private state
and metastate of business objects. The methods available in the ObjectFactory class are listed
earlier in this book, in Table 18.
I will walk through the entire persistence process, including implementation of the Create, Fetch,
Update, Delete, and Execute operations. Before I do that, I’ll demonstrate how to implement a
custom factory loader.

Custom Factory Loader Implementation


As I discussed earlier, a custom factory loader can be created that interprets the factory name
parameter of each ObjectFactory attribute as you choose. For example, in the
FactoryImplementation solution, the business classes in the Library.Net project do not provide
an assembly qualified type name to the ObjectFactory attributes. Instead they provide a simpler
factory name. For example:
[Csla.Server.ObjectFactory("PersonDal")]
[Serializable]
public class PersonEdit : BusinessBase<PersonEdit>

A custom factory loader is used to combine the “PersonDal” value with application configuration
information to determine the assembly and full type name of the object factory type.
A custom factory loader is a class that implements the IObjectFactoryLoader interface from the
Csla.Server namespace. Here’s the interface definition:
public interface IObjectFactoryLoader
{
Type GetFactoryType(string factoryName);
object GetFactory(string factoryName);
}

The GetFactoryType method returns the Type object for the object factory type based on the
object factory name parameter from an ObjectFactory attribute.
The GetFactory method returns an instance of the object factory type. Usually the GetFactory
method will call the GetFactoryType method to get the Type object, and will then use the .NET
Framework’s Activator type to create an instance of that type.
The FactoryImplementation solution includes a DataAccess project. That project contains a
FactoryLoader class:
public class FactoryLoader : Csla.Server.IObjectFactoryLoader
{
public string Assembly { get; set; }

public FactoryLoader()
{
Assembly = ConfigurationManager.AppSettings["ObjectFactoryAssembly"];
}

Using CSLA 4: Data Access Page 168


Rev 1.0
public object GetFactory(string factoryName)
{
return Activator.CreateInstance(GetFactoryType(factoryName));
}

public Type GetFactoryType(string factoryName)


{
var typeName = string.Format("{0}.{1},{0}", Assembly, factoryName);
var factoryType = Type.GetType(typeName);
if (factoryType == null)
throw new ArgumentException(string.Format("Can not find type '{0}'", typeName));
return factoryType;
}
}

The object’s constructor retrieves the ObjectFactoryAssembly value from the app.config or
web.config file. The expectation is that this value will contain the name of the assembly that
contains the concrete DAL implementation. For example:
<appSettings>
<add key="ObjectFactoryAssembly" value="DataAccess.Mock"/>
<!--<add key="ObjectFactoryAssembly" value="DataAccess.SqlCe"/>-->
<!--<add key="ObjectFactoryAssembly" value="DataAccess.SqlEf"/>-->
<add key="CslaObjectFactoryLoader" value="DataAccess.FactoryLoader,DataAccess"/>
</appSettings>

Looking at the code in the FactoryLoader class, you can see how the GetFactoryType
implementation combines the factoryName parameter value with the assembly name from the
config file to create an assembly qualified type name. The assembly name is also used as the
namespace for the object factory type:
var typeName = string.Format("{0}.{1},{0}", Assembly, factoryName);

The GetType method from the .NET Framework’s Type class is then used to dynamically get a
Type object corresponding to this type name, and that value is returned as a result of the method.

The GetFactory method is comparatively simple, because it simply invokes the standard .NET
CreateInstance method to create an instance of the type returned from the GetFactoryType
method.
Although this custom factory loader is simple, it is effective and can meet the needs of many
applications. If your application has more complex requirements, such as loading the object factory
objects using an IoC framework, your custom factory implementation may be quite different.
At this point you should understand how a custom factory loader is implemented such that it
returns the Type object for an object factory type, or an instance of that type. The factory loader is
invoked by the server-side data portal when the data portal needs an object factory type or
instance to do its work.
I will now walk through each business object stereotype, describing how to implement
persistence using the factory implementation data portal model.

Editable Root Object Persistence


The PersonEdit business class is an implementation of an editable root stereotype. You can find
this type in the Library.Net projects in the FactoryImplementation solution.

Using CSLA 4: Data Access Page 169


Rev 1.0
As in Chapter 5, I am starting with the editable root stereotype, because this stereotype covers
the primary data access actions (create, fetch, insert, update, and delete). Most of the other
stereotypes are variations on these concepts, or are subsets of these actions.
The solution includes three concrete DAL implementations. The DataAccess.Mock project
contains an implementation that uses a mock database. The DataAccess.SqlCe project uses raw
ADO.NET to interact with a SQL Server Compact Edition database. And the Data Access.SqlEf
project uses the ADO.NET Entity Framework (EF) to interact with a SQL Server Express database.
In each case, those projects contain a PersonDal class that inherits from the ObjectFactory base
class in the Csla.Server namespace:
public class PersonDal : Csla.Server.ObjectFactory
{
}

The requirements for an object factory class are minimal. The default factory loader, as well as
the custom factory loader implemented in the FactoryImplementation solution, requires only the
following:

 The class must be public


 The class must have a default constructor

If you have created your own factory loader, you may impose different restrictions on object
factory types.
The reason the PersonDal classes inherit from the ObjectFactory base class is to gain access to
the protected methods ObjectFactory provides. You will see those protected methods used
throughout the code as each data portal operation is implemented.
I’ll start with the create operation.

Create Operation
The create operation starts with the NewPersonEdit factory methods in the PersonEdit class:
public static void NewPersonEdit(EventHandler<DataPortalResult<PersonEdit>> callback)
{
DataPortal.BeginCreate<PersonEdit>(callback);
}

#if !SILVERLIGHT
public static PersonEdit NewPersonEdit()
{
return DataPortal.Create<PersonEdit>();
}
#endif

The client-side data portal invokes the server-side data portal based on the client configuration.
Because the PersonEdit class has an ObjectFactory attribute, the server-side data portal uses
the factory loader to get an instance of the PersonDal object factory. The data portal then invokes
the Create method on that factory object, and it returns the result of the Create method to the
client.

Using CSLA 4: Data Access Page 170


Rev 1.0
Because the Create method doesn’t interact with the database, it is the same in the Mock, SqlCe,
and SqlEf DAL implementations. Each of those DataAccess projects includes a PersonDal class with
this Create method:
public PersonEdit Create()
{
var result = new PersonEdit();
LoadProperty(result, PersonEdit.IdProperty, -1);
MarkNew(result);
CheckRules(result);
return result;
}

Notice that the static factory methods call the data portal’s Create and BeginCreate methods,
passing no criteria parameter. As a result, the data portal invokes a matching Create method with
no criteria parameter on the factory object.
If a criteria parameter is passed to the data portal’s Create or BeginCreate methods, the data
portal will invoke a Create method on the factory object with a matching parameter type. You may
have multiple Create method overloads in the object factory class, and they will be invoked as
appropriate based on the type of parameter passed to the data portal on the client.
The object factory’s Create method implements the following steps:

1. Create an instance of the PersonEdit business object

2. Load the business object’s properties with default values

3. Mark the business object as new (setting IsNew and IsDirty to true)

4. Invoke all business and validation rules on the business object

5. Return the business object

Notice that this factory method is completely responsible for creating the object, setting its state,
and its metastate, and returning the object as a result. This is completely unlike the encapsulated
invoke or encapsulated implementation models, where the data portal creates the business object
and manages its metastate automatically.
The result of this method is a new PersonEdit business object that has default values in its
properties, and the correct metastate.

Fetch Operation
The fetch action starts with the GetPersonEdit factory methods in the PersonEdit class:
public static void GetPersonEdit(int id, EventHandler<DataPortalResult<PersonEdit>> callback)
{
DataPortal.BeginFetch<PersonEdit>(id, callback);
}

#if !SILVERLIGHT
public static PersonEdit GetPersonEdit(int id)
{
return DataPortal.Fetch<PersonEdit>(id);
}
#endif
Using CSLA 4: Data Access Page 171
Rev 1.0
These methods invoke the client-side data portal to create an instance of the business class and
load that object with pre-existing data from the database. The client-side data portal invokes the
server-side data portal based on the client configuration. The server-side data portal then asks the
factory loader to create an instance of the object factory defined by the ObjectFactory attribute on
the PersonEdit business class. The data portal invokes the Fetch method on that factory object.
Notice that the static factory methods call the data portal’s Fetch and BeginFetch methods,
passing an int criteria parameter. As a result, the data portal invokes a matching Fetch method
with an int criteria parameter on the factory object.
If a different (or no) criteria parameter is passed to the data portal’s Fetch and BeginFetch
methods, the data portal will invoke a Fetch method on the factory object with a matching
parameter type. You may have multiple Fetch method overloads in the object factory class, and
they will be invoked as appropriate based on the type of parameter passed to the data portal on the
client.
The factory object’s Fetch method is responsible for the following:

1. Create an instance of the PersonEdit business object

2. Retrieve appropriate data from the database

3. Load the business object’s properties with values from the database

4. Mark the business object as old (setting IsNew and IsDirty to false)

5. Optionally invoke all business and validation rules on the business object

6. Return the business object

Each DAL implementation performs step 2 differently, but otherwise every implementation is
consistent.

Mock Implementation
The DataAccess.Mock implementation uses the mock database:
public PersonEdit Fetch(int id)
{
var result = new PersonEdit();
var data = MockDb.MockDb.Persons.Where(r => r.Id == id).First();
using (BypassPropertyChecks(result))
{
LoadProperty(result, PersonEdit.IdProperty, data.Id);
result.FirstName = data.FirstName;
result.LastName = data.LastName;
}
MarkOld(result);
return result;
}

The code that accesses the business object’s properties is within a using block for the object’s
BypassPropertyChecks object. This suppresses rule checking during the process, and ensures that
no business, validation, or authorization rules will run as the object is loaded with data.

Using CSLA 4: Data Access Page 172


Rev 1.0
Entity Framework Implementation
The SqlEf implementation is similar, though it uses an EF query to get the data:
public PersonEdit Fetch(int id)
{
var result = new PersonEdit();
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var data = (from r in ctx.ObjectContext.People
where r.Id == id
select r).First();
using (BypassPropertyChecks(result))
{
LoadProperty(result, PersonEdit.IdProperty, data.Id);
result.FirstName = data.FirstName;
result.LastName = data.LastName;
}
}
MarkOld(result);
return result;
}

The same steps are followed, but an ObjectContextManager is used to create or reuse the EF
object context, and therefore the underlying database connection. That EF ObjectContext is then
used for the EF query to get the data from the database based on the criteria parameter.
The data from the EF entity is then used to load the business object’s property values, the
MarkOld method is used to set the business object’s metastate, and the business object is returned
as a result.

ADO.NET Implementation
Finally, the SqlCe implementation uses an ADO.NET database query to get the data:
public PersonEdit Fetch(int id)
{
var result = new PersonEdit();
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "SELECT Id,FirstName,LastName FROM Person WHERE Id=@id";
cm.Parameters.Add("@id", id);
using (var dr = cm.ExecuteReader())
{
var idIndex = dr.GetOrdinal("Id");
var firstIndex = dr.GetOrdinal("FirstName");
var lastIndex = dr.GetOrdinal("LastName");
dr.Read();
using (BypassPropertyChecks(result))
{
LoadProperty(result, PersonEdit.IdProperty, dr.GetInt32(dr.GetOrdinal("Id")));
result.FirstName = dr.GetString(dr.GetOrdinal("FirstName"));
result.LastName = dr.GetString(dr.GetOrdinal("LastName"));
}
}
}
}
MarkOld(result);
return result;
}

Using CSLA 4: Data Access Page 173


Rev 1.0
A ConnectionManager object is used to create or reuse the database connection. The connection
object is used to create and execute a command object that performs the SELECT query. The result
is a data reader containing the data.
The data from the data reader is used to load the business object’s property values, the MarkOld
method is used to set the business object’s metastate, and the business object is returned as a
result.
In all three implementations the result is a PersonEdit business object containing the existing
data from the database based on the criteria parameter value.

Update Operation
When an editable root object is saved, the Save or BeginSave method invokes the client-side data
portal by calling its Update or BeginUpdate method. That client-side method invokes the server-side
data portal based on the client configuration, and the server-side data portal uses the factory
loader to get an instance of the appropriate factory object based on the ObjectFactory attribute
on the PersonEdit business class.
The data portal then invokes the Update method on the factory object, passing the business
object as a parameter to the Update method. Because database updates are bi-directional, the
Update method must return the business object as a result.

Within your Update method implementation, you need to use the business object’s IsNew and
IsDeleted metastate properties to determine whether to perform an insert, update, or delete
action. In all three concrete DAL implementations, the Update method in the PersonDal class looks
the same:
[Csla.Transactional(Csla.TransactionalTypes.TransactionScope)]
public PersonEdit Update(PersonEdit obj)
{
if (obj.IsDeleted)
{
if (!obj.IsNew)
using (BypassPropertyChecks(obj))
Delete(obj.Id);
MarkNew(obj);
}
else if (obj.IsNew)
{
using (BypassPropertyChecks(obj))
{
var newId = InsertPerson(obj.FirstName, obj.LastName);
LoadProperty(obj, PersonEdit.IdProperty, newId);
}
MarkOld(obj);
}
else if (obj.IsDirty)
{
using (BypassPropertyChecks(obj))
{
UpdatePerson(obj.Id, obj.FirstName, obj.LastName);
}
MarkOld(obj);
}
return obj;
}

Using CSLA 4: Data Access Page 174


Rev 1.0
This method is marked with the Transactional attribute from the Csla namespace, using the
TransactionScope parameter value. Because the Update method has this attribute, the data portal
will ensure that the code is running within a TransactionScope object before the Update method is
invoked.
The business object’s metastate properties are used to determine whether to perform a delete,
insert, or update action. I’ll discuss each action in detail.

Delete Action
The delete action occurs if the business object’s IsDeleted property is true.
If the business object’s IsNew property is false, then we have a reasonable expectation that the
object corresponds to data in the database. In that case a Delete method is invoked to delete the
data:
if (obj.IsDeleted)
{
if (!obj.IsNew)
using (BypassPropertyChecks(obj))
Delete(obj.Id);
MarkNew(obj);
}

The immediate delete operation (discussed later) also requires a Delete method in the
PersonDal class, and I’m simply reusing that existing method. Here’s the Delete method from the
SqlCe implementation:
[Csla.Transactional(Csla.TransactionalTypes.TransactionScope)]
public void Delete(int id)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "DELETE Person WHERE Id=@id";
cm.Parameters.Add("@id", id);
var rowsAffected = cm.ExecuteNonQuery();
if (rowsAffected == 0)
throw new InvalidOperationException("Zero rows deleted");
}
}
}

Although this method has the Transactional attribute, in this specific scenario it is not being
invoked by the data portal, and so the attribute is not used and has no effect on the method. This
code is already running within a transaction because of the Transactional attribute on the Update
method of the PersonDal class; a method that was invoked by the data portal.
The Delete method creates a command object for the DELETE query, and executes the command
to delete the data.
Back in the Update method, it is important to notice that the MarkNew method is called to set the
business object’s metastate so IsNew and IsDirty are true, and IsDeleted is false. Because the
business object no longer corresponds to a row of data in the database, and because the object’s
properties no longer match values in the database, the object is both new and changed.

Using CSLA 4: Data Access Page 175


Rev 1.0
Insert Action
If the business object isn’t marked for deletion, but IsNew is true, then the object’s data needs to
be inserted into the database. This is done by calling an InsertPerson method:
else if (obj.IsNew)
{
using (BypassPropertyChecks(obj))
{
var newId = InsertPerson(obj.FirstName, obj.LastName);
LoadProperty(obj, PersonEdit.IdProperty, newId);
}
MarkOld(obj);
}

The InsertPerson method is a private method in the PersonDal class. Notice that this method
returns the new database-generated Id property value for the data, and that value is placed into
the business object’s Id property.
The call to the MarkOld method is also important. The MarkOld method sets the object’s IsNew
and IsDirty properties to false.
Now that the business object’s data has been inserted into the database, there is a reasonable
expectation that the object corresponds to a row of data so it is no longer new. Additionally, there
is a reasonable expectation that the object’s properties match values in the database, so it is no
longer dirty or changed.
The InsertPerson method is different for each DAL implementation. For example, the SqlEf
implementation looks like this:
private int InsertPerson(string firstName, string lastName)
{
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var data = new Person { FirstName = firstName, LastName = lastName };
ctx.ObjectContext.AddToPeople(data);
var count = ctx.ObjectContext.SaveChanges();
if (count == 0)
throw new InvalidOperationException("PersonDal.Insert");
return data.Id;
}
}

This is standard EF code, where a Person entity object is created, and the business object’s
property values are used to populate the entity object’s properties. The entity object is then added
to the EF ObjectContext object’s People collection and the changes are committed to the database
by calling the SaveChanges method.
Once the changes have been committed, the database-generated Id property is automatically
placed back into the Person entity object, so that value can be returned as a result of the
InsertPerson method.

Update Action
The update action occurs if the business object isn’t marked for deletion and isn’t new. In this case
the business object’s data needs to be updated into the database. This is done by calling an
UpdatePerson method from the PersonDal class’s Update method:

Using CSLA 4: Data Access Page 176


Rev 1.0
else if (obj.IsDirty)
{
using (BypassPropertyChecks(obj))
{
UpdatePerson(obj.Id, obj.FirstName, obj.LastName);
}
MarkOld(obj);
}

As an optimization, this code only runs if the business object has been changed. If the IsDirty
property is false, the object hasn’t been changed so there is nothing to update.
The code that accesses the business object’s properties is within a using block for the object’s
BypassPropertyChecks object. This suppresses rule checking during the process, and avoids
authorization rule violations.
The call to the MarkOld method is also important. The MarkOld method sets the object’s IsNew
and IsDirty properties to false.
The UpdatePerson method is different in each concrete DAL implementation. The SqlCe
implementation, for example, looks like this:
private void UpdatePerson(int id, string firstName, string lastName)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "UPDATE Person SET FirstName=@firstName,LastName=@lastName WHERE Id=@id";
cm.Parameters.Add("@id", id);
cm.Parameters.Add("@firstName", firstName);
cm.Parameters.Add("@lastName", lastName);
var rowsAffected = cm.ExecuteNonQuery();
if (rowsAffected == 0)
throw new InvalidOperationException("Zero rows updated");
}
}
}

A command object is created and loaded with parameter values corresponding to the business
object’s property values. The command is then executed to perform the UPDATE query in the
database.
You can see how the object factory’s Update method uses the business object’s metastate to
determine whether to perform a delete, insert, or update action. Each of those actions is
implemented differently depending on the type of data access technology being used, but they all
perform the same steps, and interact with the business object’s properties and metastate in a
consistent manner.

Immediate Delete Operation


Immediate deletion occurs when a client-side factory method is invoked on the business class to call
the client-side data portal’s Delete or BeginDelete method. For example, this method is in the
PersonEdit business class:
public static void DeletePersonEdit(int id)
{
DataPortal.Delete<PersonEdit>(id);
}
Using CSLA 4: Data Access Page 177
Rev 1.0
The client-side data portal invokes the server-side data portal, and it then invokes the Delete
method implemented by the object factory. For example, here’s the SqlEf implementation of this
method from the PersonDal class:
[Csla.Transactional(Csla.TransactionalTypes.TransactionScope)]
public void Delete(int id)
{
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var item = (from r in ctx.ObjectContext.People
where r.Id == id
select r).FirstOrDefault();
if (item == null)
throw new InvalidOperationException("Person");
ctx.ObjectContext.DeleteObject(item);
var count = ctx.ObjectContext.SaveChanges();
if (count == 0)
throw new InvalidOperationException("PersonDal.Delete");
}
}

This method basically invokes the same DAL provider Delete method I discussed from the
update operation when IsDeleted is true. In this case, however, the Delete method is invoked
directly by the data portal, so the Transactional attribute is important. Based on this attribute, the
data portal ensures that the code is running within a TransactionScope object before the Delete
method is invoked.
Because this method is implemented using EF, it retrieves the Person entity from the database,
deletes it from the ObjectContext object, and saves the changes to the context by calling the
SaveChanges method. The result is that the data is deleted from the database.

At this point you should understand how to implement persistence for an editable root object
with a factory object, including the Create, Fetch, Update, and immediate Delete operations.

Editable Root List Persistence


The FactoryImplementation solution includes the SkillEditList class in the Library.Net project.
This class is an editable root list that contains SkillEdit editable child objects. Any ObjectFactory
attribute applied to a child class is ignored, but the root object must have an ObjectFactory
attribute. Here’s the declaration of the SkillEditList class:
[Csla.Server.ObjectFactory("SkillDal")]
[Serializable]
public class SkillEditList : BusinessListBase<SkillEditList, SkillEdit>

The custom factory loader will combine the “SkillDal” parameter value with the application
configuration information to create an assembly qualified type name for the object factory type.
Each of the three concrete DAL projects implements a SkillDal class.

Create Operation
The create operation works the same with an editable root list as for an editable root object. The
business class implements static factory methods that call the data portal, and the data portal
relays the call to the server.

Using CSLA 4: Data Access Page 178


Rev 1.0
On the server, the data portal uses the factory loader to get an instance of the object factory
type. Then the data portal invokes the Create method of the factory object to get a new instance of
the business object.
Because the Create method doesn’t interact with the database, it is the same in the SkillDal
classes of all three concrete DAL projects:
public SkillEditList Create()
{
return new SkillEditList();
}

Collections don’t have metadata that can be affected by methods such as MarkNew or MarkOld, so
there’s no need to try and set metadata on the new business object. The metadata of a collection is
calculated based on the metadata of the child objects it contains.

Child Create Techniques


In Chapter 5 I provided a complete discussion of the various options available for creating new child
objects and adding them to an editable collection. Those same options apply when using a factory-
based data portal model. To recap, the options are:

1. Calling code creates the new child object, and adds it to the list by calling the collection’s
Add method

2. Collection implements an AddItem method that is responsible for creating the new child
object and adding it to the list

3. Calling code invokes the collection’s AddNew method, and that method creates the new child
object and adds it to the list (also used by data binding scenarios)

As I discussed in Chapter 5, each of these options requires or allows you to write the code that
creates the child object.
Because the factory-based data portal models generally require that all DAL code run on the
server, you should consider whether creating a child object needs data access or other server-side
resources.

Creating the Child Locally


If a new child object can be created without any database interaction, you may consider creating an
internal factory method in the child class to synchronously and locally create the child object. For
example, the SkillEdit child class contains this static factory method and corresponding
Child_Create method:
internal static SkillEdit NewSkillEdit()
{
return DataPortal.CreateChild<SkillEdit>();
}

#if SILVERLIGHT
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public override void Child_Create()
#else
protected override void Child_Create()

Using CSLA 4: Data Access Page 179


Rev 1.0
#endif
{
using (BypassPropertyChecks)
Id = -1;
base.Child_Create();
}

The static factory method calls the data portal’s CreateChild method to create an instance of
the child object. The CreateChild method always runs synchronously, and doesn’t go across the
network to an application server, so it runs local to where it was invoked.
The scope of the Child_Create method must be different on Silverlight due to limitations on
reflection and dynamic method invocation, otherwise the method is the same on .NET, Silverlight,
and WP7.
The result of this code is that any of the three options for creating and adding a new child object
to the collection can use this static factory method to create and initialize an instance of the child
type.

Creating the Child on the Server


If new child objects must be initialized with default values from the database, then you need to
implement a read-only command object to create and initialize the child object. I discussed this
concept in Chapter 5, including a detailed walkthrough of the SkillEditCreator class.
The SkillEditCreator class is a little different when using a factory-based data portal model,
because the class has an ObjectFactory method, and doesn’t have a DataPortal_Fetch method.
Instead, the data access code for the class is contained in an object factory class. Here’s the
declaration of the SkillEditCreator class:
[Csla.Server.ObjectFactory("SkillDal", "CreateSkill")]
[Serializable]
public class SkillEditCreator : ReadOnlyBase<SkillEditCreator>

The ObjectFactory attribute indicates that the data portal should use the SkillDal object
factory type, and that the Fetch operation should cause the object factory’s CreateSkill method to
be invoked, instead of the default Fetch method.
As you can imagine, each of the SkillDal classes in the concrete DAL implementations includes
a CreateSkill method. That method is responsible for creating and returning a SkillEditCreator
object.
Because the sample FactoryImplemetation solution doesn’t actually talk to the database to
create a SkillEdit object, the CreateSkill methods in all three DAL providers is the same:
public SkillEditCreator CreateSkill()
{
var result = new SkillEditCreator();
var newChild = new SkillEdit();
MarkAsChild(newChild);
MarkNew(newChild);
LoadProperty(result, SkillEditCreator.ResultProperty, newChild);
return result;
}

This code creates the SkillEditCreator object that will be returned as a result.

Using CSLA 4: Data Access Page 180


Rev 1.0
It then creates a new SkillEdit editable child object and marks it as a child by calling the
MarkAsChild method. The new child object is also marked as being a new object with a call to the
MarkNew method.

In a real application the new SkillEdit child would be initialized with default values loaded
from the database.
The new SkillEdit child object is then loaded into the SkillEditCreator object’s Result
property, and the SkillEditCreator is returned as a result.
The result of this effort is that any of the three options for creating and adding a new child
object to the SkillEditList collection can use the SkillEditCreator to get a new child object
using code like this:
var creator = SkillEditCreator.GetSkillEditCreator();
var newChild = creator.Result;

Or in an asynchronous setting, such as Silverlight, the code would look like this:
SkillEdit newChild = null;
SkillEditCreator.GetSkillEditCreator((o, e) =>
{
if (e.Error != null)
throw e.Error;
newChild = e.Object.Result;
});

Once the calling code has the new child object, that object can be added to the collection using
one of the three options I discussed in Chapter 5.

Fetch Operation
The Fetch operation for an editable root list works much like the fetch for an editable object. The
business class implements static factory methods, and they invoke the client-side data portal. The
client-side data portal invokes the server-side data portal, and it uses the factory loader to load an
instance of the correct object factory type based on the ObjectFactory attribute on the business
class.
The data portal then invokes the Fetch method on the factory object. In the case of an editable
root list, that Fetch method is responsible for the following:

1. Create an instance of the SkillEditList business object

2. Set the collection’s RaiseListChangedEvents property

3. Retrieve appropriate data from the database

4. Create an instance of the SkillEdit child object for each row of data

5. Mark each child object as old (setting IsNew and IsDirty to false)

6. Optionally invoke all business and validation rules on each child business object

7. Add each child object to the SkillEditList collection

Using CSLA 4: Data Access Page 181


Rev 1.0
8. Restore the collection’s RaiseListChangedEvents property

9. Return the SkillEditList business object

As you can see, the Fetch method is responsible for not only creating the collection it will return
as a result, but it is also responsible for creating and loading each child object’s state and metastate.
Each DAL implementation is somewhat different, based on the data access technology being
used. But they each follow the same steps.

Mock Implementation
The Mock implementation retrieves its data from the mock database:
public SkillEditList Fetch()
{
var result = new SkillEditList();
result.RaiseListChangedEvents = false;
var data = MockDb.MockDb.Skills;
foreach (var item in data)
{
var child = new SkillEdit();
MarkAsChild(child);
MarkOld(child);
LoadProperty(child, SkillEdit.IdProperty, item.Id);
LoadProperty(child, SkillEdit.NameProperty, item.Name);
result.Add(child);
}
result.RaiseListChangedEvents = true;
return result;
}

You can see how the method creates the SkillEditList object and sets its
RaiseListChangedEvents property.

The method then retrieves the data from the mock database, and loops through each row of
data to create and populate SkillEdit child objects. The MarkAsChild and MarkOld methods are
called on each child object to set the metastate.
Finally the fully populated collection is returned as a result of the method, and the data portal
returns it to the client.

Entity Framework Implementation


The SqlEf implementation is similar:
public SkillEditList Fetch()
{
var result = new SkillEditList();
result.RaiseListChangedEvents = false;
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var data = from r in ctx.ObjectContext.Skills
select r;
foreach (var item in data)
{
var child = new SkillEdit();
MarkAsChild(child);
MarkOld(child);
LoadProperty(child, SkillEdit.IdProperty, item.Id);
LoadProperty(child, SkillEdit.NameProperty, item.Name);

Using CSLA 4: Data Access Page 182


Rev 1.0
result.Add(child);
}
}
result.RaiseListChangedEvents = true;
return result;
}

An EF ObjectContext object is used to access the database, and an EF query is run to select the
data. The code then loops through each row of data to create and populate the SkillEdit child
objects.

ADO.NET Implementation
The ADO.NET implementation is in the DataAccess.SqlCe project, and the SkillDal class contains
this Fetch method:
public SkillEditList Fetch()
{
var result = new SkillEditList();
result.RaiseListChangedEvents = false;
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
var cm = ctx.Connection.CreateCommand();
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "SELECT Id,Name FROM Skill";
using (var dr = cm.ExecuteReader())
{
while (dr.Read())
{
var child = new SkillEdit();
MarkAsChild(child);
MarkOld(child);
LoadProperty(child, SkillEdit.IdProperty, dr.GetInt32(0));
LoadProperty(child, SkillEdit.NameProperty, dr.GetString(1));
result.Add(child);
}
}
}
result.RaiseListChangedEvents = true;
return result;
}

The same steps are followed in this method, the only difference being in the way the data is
retrieved from the database.

Update Operation
When an editable root list is saved by calling its Save or BeginSave method, the client-side data
portal’s Update or BeginUpdate method is invoked. This results in a call to the server-side data
portal, which gets an object factory instance from the factory loader based on the ObjectFactory
attribute on the business class.
The server-side data portal then invokes the Update method of the factory object, passing the
collection as a parameter. Because update operations are bi-directional, the Update method also
returns the business object as a result so it can be returned to the client with any changes that
occurred to the business objects on the server.
When persisting an editable root list, the Update method implements the following steps:

1. Set the collection’s RaiseListChangedEvents property


Using CSLA 4: Data Access Page 183
Rev 1.0
2. Update each child item in the SkillEditList collection’s DeletedList

3. Clear the collection’s DeletedList

4. Update each child item in the collection

5. Restore the collection’s RaiseListChangedEvents property

6. Return the collection as a result

I usually isolate the update of child items into a separate private method. In the SkillDal classes
you’ll find an UpdateSkillEdit method that updates the individual child items. By isolating this
code, the Update method itself is the same in all three DAL implementations:
[Csla.Transactional(Csla.TransactionalTypes.TransactionScope)]
public SkillEditList Update(SkillEditList obj)
{
obj.RaiseListChangedEvents = false;
foreach (var item in GetDeletedList<SkillEdit>(obj))
UpdateSkillEdit(item);
GetDeletedList<SkillEdit>(obj).Clear();
foreach (var item in obj)
UpdateSkillEdit(item);
obj.RaiseListChangedEvents = true;
return obj;
}

The only exception is that the Mock implementation doesn’t use the Transactional attribute
because it doesn’t interact with a real database.
The UpdateSkillEdit method is responsible for updating each editable child object. Updating an
editable child object is the same as updating an editable root object, in that the object’s metastate
is used to determine whether to perform a delete, insert, or update action.
Again, I isolate each data action into a separate method, so the UpdateSkillEdit method is the
same in all three DAL implementations:
private void UpdateSkillEdit(SkillEdit obj)
{
if (obj.IsDeleted)
{
if (!obj.IsNew)
using (BypassPropertyChecks(obj))
DeleteSkill(obj.Id);
MarkNew(obj);
}
else if (obj.IsNew)
{
using (BypassPropertyChecks(obj))
{
var newId = InsertSkill(obj.Name);
LoadProperty(obj, SkillEdit.IdProperty, newId);
}
MarkOld(obj);
}
else if (obj.IsDirty)
{
using (BypassPropertyChecks(obj))
{
UpdateSkill(obj.Id, obj.Name);
}
Using CSLA 4: Data Access Page 184
Rev 1.0
MarkOld(obj);
}
}

If you compare this method to the Update method in the PersonDal class, you will see that the
flow of the logic is the same. This same logical flow should be used to update any editable root or
child object.
As you can imagine, the DeleteSkill, InsertSkill, and UpdateSkill methods are different for
each DAL provider based on the type of data access technology being used. The code in these
methods is comparable to the methods in the PersonDal class, so I won’t walk through them in
detail.
The result of the Update method in the SkillDal class is that the child objects in the collection’s
DeletedList are deleted, and the child objects in the collection itself are inserted or updated based
on their individual metastate.

Immediate Delete Operation


Although it is not common, it is possible to implement an immediate delete operation on an
editable root list type. The overall implementation is the same as I discussed in Chapter 5, in that
the business class implements a static method that invokes the Delete or BeginDelete method of
the client-side data portal to start the process.
The server-side data portal then uses the factory loader to create the appropriate factory object,
and the data portal invokes the Delete method on this object.
The Delete method in an object factory is then responsible for deleting all data that would have
been loaded into the collection in a Fetch operation based on the same criteria parameter value.
For example, the SkillDal class in the SqlCe DAL implementation includes this code:
[Csla.Transactional(Csla.TransactionalTypes.TransactionScope)]
public void Delete()
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "DELETE Skill";
var rowsAffected = cm.ExecuteNonQuery();
}
}
}

This method uses a command object to delete all records from the Skill table, and therefore
from the SkillEditList collection.
At this point you should understand how to implement the Create, Fetch, Update, and
immediate Delete operations for an editable root list. And you should see how the same techniques
for creating and adding child objects to a collection from Chapter 5 apply in a factory-based data
portal model.

Using CSLA 4: Data Access Page 185


Rev 1.0
Dynamic List and Object Persistence
The CategoryEditList class in the Library.Net project of the FactoryImplementation solution is a
dynamic list. As I discussed in Chapter 5 and in the Using CSLA 4: Creating Business Objects ebook, a
dynamic list is quite different from an editable root list, because it contains editable root objects.
Additionally, it saves changes to the individual root objects it contains instead of saving all changes
to its child objects in a batch.
The CategoryDal class in each concrete DAL implementation contains the data access code for
the CategoryEditList collection, and the CategoryEdit editable root objects. The CategoryDal
class represents the behaviors possible against the logical category data entity.
Both the CategoryEditList dynamic list and CategoryEdit dynamic root classes have
ObjectFactory attributes. The CategoryEditList class needs a factory that implements the Fetch
operation, and the CategoryEdit class needs a factory that implements the update operation.
As I mentioned, I put all the category-related DAL methods into the CategoryDal class, so both
business classes refer to that same object factory type. The ObjectFactory attribute on the
CategoryEditList class does specify a custom name for the Fetch method:
[Csla.Server.ObjectFactory("CategoryDal", "FetchEditList")]
[Serializable]
public class CategoryEditList : DynamicListBase<CategoryEdit>

The CategoryEdit class just specifies the object factory name:


[Csla.Server.ObjectFactory("CategoryDal")]
[Serializable]
public class CategoryEdit : BusinessBase<CategoryEdit>

With these attributes in place, the data portal will now invoke methods on the CategoryDal class
to perform the data portal operations.

Fetch Operation
When a dynamic list is retrieved, it is loaded with the editable root objects it contains. Although
each editable root object could load itself from the database, it is more efficient to retrieve all the
data as a single query, and to then use that data to populate the editable root objects.
This process is very similar to the Fetch operation for an editable root list, except that the
MarkAsChild method isn’t called to mark the “child” objects as children.

For example, here’s the FetchEditList method from the SqlEf implementation of the
CategoryDal class:
public CategoryEditList FetchEditList()
{
var result = new CategoryEditList();
var rlce = result.RaiseListChangedEvents;
result.RaiseListChangedEvents = false;
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var data = from r in ctx.ObjectContext.CategoryTables
select r;
foreach (var item in data)
{
var edit = new CategoryEdit();
using (BypassPropertyChecks(edit))

Using CSLA 4: Data Access Page 186


Rev 1.0
{
LoadProperty(edit, CategoryEdit.IdProperty, item.Id);
edit.Name = item.Category;
}
MarkOld(edit);
result.Add(edit);
}
}
result.RaiseListChangedEvents = rlce;
return result;
}

This method creates the new CategoryEditList collection and sets its RaiseListChangedEvents
property to false. It then executes an EF query to get data from the database.
Once it has the data, the method loops through each row of data, and it creates a CategoryEdit
object for that row. The data is used to load the properties of the CategoryEdit object, and the
MarkOld method is called to set the object’s metastate.

Notice that MarkAsChild is not called. The CategoryEdit object is an editable root object, not a
child.
Once all the CategoryEdit editable root objects have been loaded and added to the collection,
the CategoryEditList collection is returned as a result.

Update Operation
As the user interacts with the editable root objects in the dynamic list, the CategoryEditList
object will automatically save each root object. As I discuss in the Using CSLA 4: Creating Business
Objects ebook, the save of each root object is typically triggered by data binding events. The
DynamicListBase and DynamicBindingListBase classes are implemented so they react properly in
smart client data binding scenarios where the collection is bound to a datagrid control that raises
the correct data binding events.
When an individual CategoryEdit editable root object is saved, its BeginSave method is called.
That results in a call to the client-side data portal’s BeginUpdate method. The client-side data portal
invokes the server-side data portal, which then uses the factory loader to get an instance of the
appropriate object factory type.
The data portal then calls the Update method on the factory object, passing the CategoryEdit
editable root object to the method as a parameter. Because updates are bi-directional, the Update
method also returns the business object as a result.
Because CategoryEdit is an editable root object, the code to implement its Update method, and
corresponding delete, insert, and update actions, is the same as for the PersonEdit and SkillEdit
classes I’ve already discussed. I won’t repeat that content here, you can look at the three
CategoryEdit classes to see how they implement the Update method.

At this point you should understand how to use the factory implementation data portal model
for persistence of an editable root object, an editable root list with editable child objects, and a
dynamic list containing root objects. Next, I will discuss persisting a more editable complex object
graph.

Using CSLA 4: Data Access Page 187


Rev 1.0
Editable Object Graph Persistence
At this point in the chapter you have seen how to implement persistence for an editable root, an
editable root list, and a dynamic list containing dynamic root objects. Those object graphs have
been relatively simple. The most complex is the editable root list containing child objects.
Many applications have more complex object graphs, consisting of a root parent containing child
objects, and those child objects containing other child (grandchild) objects. Anything beyond a
simple root parent-child graph is more complex in terms of object persistence.
The Library.Net projects in the two sample solutions include an OrderEdit class. This is the
root type for a more complex object graph, shown in Figure 17, and is the same as Figure 14 in
Chapter 5.

Figure 17. OrderEdit object graph.


An OrderEdit object contains an editable child collection of OrderLineItem objects. The
OrderLineItem class implements the editable child stereotype, and represents one line item in the
order.
Each OrderLineItem child object contains an editable child collection of OrderLinePerson
objects. The OrderLinePerson class implements the editable child stereotype, and represents one
person associated with the line item.
Please refer to the discussion of an complex editable object in Chapter 5 for more information.
I typically create an object factory class in my DAL project for each logical data entity in the
database. This includes data entities, such as an order line item, that only correspond to child
business objects.
This may seem a little strange at first, because a child business object will never use the data
portal to directly invoke a factory object. Only a root business object will use the data portal to
invoke a factory object.
But when you implement the object factory class for an editable root object that contains child
objects, the code to persist those child objects must go into some object factory class. I find that
Using CSLA 4: Data Access Page 188
Rev 1.0
putting the DAL methods for a child object into its own object factory class helps organize the data
access code. The result is that the code is more readable and maintainable.
The three data access projects in the FactoryImplementation project follow this
recommendation, and include OrderDal, OrderLineItemDal, and OrderLineItemPersonDal classes.
The methods of the OrderDal class are directly invoked by the data portal to persist the editable
root OrderEdit business object. The methods in OrderDal call the methods in OrderLineItemDal to
persist the editable child OrderLineItem business objects. And the methods in OrderLineItemDal
call the methods in OrderLineItemPersonDal to persiste the editable child OrderLinePerson
business objects.
The only business class with an ObjectFactory attribute is the OrderEdit root class:
[Csla.Server.ObjectFactory("OrderDal")]
[Serializable]
public class OrderEdit : BusinessBase<OrderEdit>

The child classes do not have an ObjectFactory attribute, because they are never directly
persisted using the data portal.

Create Operation
The create operation for the OrderEdit editable root object is implemented in a Create method of
the OrderDal classes in each of the DAL projects. Because the sample application doesn’t interact
with the database to create the OrderEdit object or its child objects, the Create methods are the
same in each DAL implementation:
public OrderEdit Create(int customerId)
{
var result = new OrderEdit();
MarkNew(result);
LoadProperty(result, OrderEdit.IdProperty, -1);
LoadProperty(result, OrderEdit.CustomerIdProperty, customerId);
LoadProperty(result, OrderEdit.OrderDateProperty, DateTime.Today);
LoadProperty(result, OrderEdit.OrderEditProperty, DateTime.Today);
var old = new OrderLineItemDal();
LoadProperty(result, OrderEdit.OrderLineItemsProperty, old.CreateList());
return result;
}

This method follows the same steps I outlined for the PersonEdit create operation. The only
meaningful difference is that the OrderLineItemDal is used to create an instance of the
OrderLineItems editable child list:
var old = new OrderLineItemDal();
LoadProperty(result, OrderEdit.OrderLineItemsProperty, old.CreateList());

The CreateList method in the OrderLineItemsDal class is responsible for creating a new child
list object:
public OrderLineItems CreateList()
{
var result = new OrderLineItems();
MarkAsChild(result);
return result;
}

Using CSLA 4: Data Access Page 189


Rev 1.0
The result is that the Create method of the OrderDal object is a new OrderEdit business object,
containing an empty OrderLineItems child list. This OrderEdit object is returned to the data portal,
and the data portal returns it to the code that called the static factory method on the OrderEdit
class.

Creating New Child Objects


As the application interacts with an OrderEdit object, it will typically add new child objects to the
OrderLineItems child collection. You can use any of the three options for adding new child objects
to a collection that I discussed in Chapter 5, when I discussed adding child objects to the
SkillEditList editable root list.
In the sample application I am using the built-in support for the collection’s AddNew method. You
may recall that the default implementation provided by CSLA .NET invokes the data portal’s
CreateChild method to create a new child object. To properly initialize each new OrderLineItem
child object, the OrderLineItem class overrides the Child_Create method:
#if SILVERLIGHT
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public override void Child_Create()
#else
protected override void Child_Create()
#endif
{
using (BypassPropertyChecks)
{
Id = -1;
Persons = DataPortal.CreateChild<OrderLinePersons>();
}
base.Child_Create();
}

The method signatures for Silverlight and .NET are different due to Silverlight limitations on
reflection and dynamic method invocation. Otherwise the implementations are the same.

Creating New Grandchild Objects


A different technique is used to add new OrderLinePerson child objects to the OrderLinePersons
collection. This is because a parameter is required to properly initialize the new child object, and
the built-in AddNew technique has no provision for passing parameter values to a new object.
The OrderLinePerson class implements a synchronous factory method, and that method calls
the data portal’s CreateChild method to create the new child object:
public static OrderLinePerson NewOrderLinePerson(int personId)
{
return DataPortal.CreateChild<OrderLinePerson>(personId);
}

#if SILVERLIGHT
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void Child_Create(int personId)
#else
private void Child_Create(int personId)
#endif
{
using (BypassPropertyChecks)
{
LineItemId = -1;

Using CSLA 4: Data Access Page 190


Rev 1.0
PersonId = personId;
}
}

I discussed this technique earlier in this chapter when I covered creating new child objects for
the SkillEditList editable collection, and also in Chapter 5.

Fetch Operation
The Fetch operation for an OrderEdit editable root object is the same as for any editable root
object. The OrderEdit class implements static factory methods that invoke the data portal, and the
data portal ultimately calls the Fetch method on the appropriate OrderDal factory object.

Loading the Root Object


Each DAL provider uses a slightly different implementation for the Fetch method, based on the data
access technology being used. The SqlEf implementation looks like this:
public OrderEdit Fetch(int id)
{
var result = new OrderEdit();
MarkOld(result);
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var data = (from r in ctx.ObjectContext.Orders
where r.Id == id
select r).First();
LoadProperty(result, OrderEdit.IdProperty, data.Id);
LoadProperty(result, OrderEdit.CustomerIdProperty, data.CustomerId);
if (data.OrderDate.HasValue)
LoadProperty(result, OrderEdit.OrderDateProperty, data.OrderDate.Value);
if (data.OrderEditDate.HasValue)
LoadProperty(result, OrderEdit.OrderEditProperty, data.OrderEditDate.Value);
var old = new OrderLineItemDal();
LoadProperty(result, OrderEdit.OrderLineItemsProperty, old.FetchList(id));
}
return result;
}

An EF ObjectContext object is used to access the database, and an EF query is run to retrieve
the root object’s data. The data values in the entity object returned from the query are used to
populate the properties of the OrderEdit business object.

Loading the Child Objects


Notice how the OrderLineItems collection is then loaded by calling the FetchList method on an
OrderLineItemDal object:
var old = new OrderLineItemDal();
LoadProperty(result, OrderEdit.OrderLineItemsProperty, old.FetchList(id));

This code is in the using block for the ObjectContextManager, ensuring that the same database
connection will be reused to retrieve the child object data.
In the OrderLineItemDal class, the FetchList method creates and populates the child
collection:
public OrderLineItems FetchList(int orderId)
{
var result = new OrderLineItems();
MarkAsChild(result);
Using CSLA 4: Data Access Page 191
Rev 1.0
result.RaiseListChangedEvents = false;
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var data = from r in ctx.ObjectContext.OrderLineItems
where r.OrderId == orderId
select r;
var olpd = new OrderLineItemPersonDal();
foreach (var item in data)
{
var child = new Library.OrderLineItem();
MarkAsChild(child);
MarkOld(child);
var childId = item.Id;
LoadProperty(child, Library.OrderLineItem.IdProperty, childId);
if (item.ShipDate.HasValue)
LoadProperty(child, Library.OrderLineItem.ShipDateProperty, item.ShipDate.Value);
LoadProperty(child, Library.OrderLineItem.PersonsProperty, olpd.FetchList(childId));
result.Add(child);
}
}
result.RaiseListChangedEvents = true;
return result;
}

This method uses an EF query to get the list of line item entities, and those entity objects are
used to load individual OrderLineItem child objects with data.

Loading the Grandchild Objects


As part of this process, the FetchList method on an OrderLineItemPersonDal object is used to
create the OrderLinePersons child collection contained in each OrderLineItem object:
LoadProperty(child, Library.OrderLineItem.PersonsProperty, olpd.FetchList(childId));

Entity Framework Implementation


The FetchList method in the OrderLineItemPersonDal class populates the child collection with
objects:
public OrderLinePersons FetchList(int lineItemId)
{
var result = new OrderLinePersons();
MarkAsChild(result);
result.RaiseListChangedEvents = false;
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var lineItem = (from r in ctx.ObjectContext.OrderLineItems
where r.Id == lineItemId
select r).First();
var data = from r in lineItem.People
select new { LineItemId = lineItem.Id, PersonId = r.Id };
foreach (var item in data)
{
var child = new OrderLinePerson();
MarkAsChild(child);
MarkOld(child);
LoadProperty(child, OrderLinePerson.LineItemIdProperty, item.LineItemId);
LoadProperty(child, OrderLinePerson.PersonIdProperty, item.PersonId);
result.Add(child);
}
}
result.RaiseListChangedEvents = true;
return result;
}

Using CSLA 4: Data Access Page 192


Rev 1.0
This code is a little strange due to the way EF works with link tables. A query is run to get the
LineItem data entity for the current line item, and then a second query is run to get the list of
Person entities attached to that line item. The resulting data is then used to load individual
OrderLinePerson child objects, and they are added to the collection.

ADO.NET Implementation
The SqlCe implementation may be easier to understand, because it uses a more straightforward
SQL query against the OrderLinePersons link table:
public OrderLinePersons FetchList(int lineItemId)
{
var result = new OrderLinePersons();
MarkAsChild(result);
result.RaiseListChangedEvents = false;
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
var cm = ctx.Connection.CreateCommand();
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText =
"SELECT LineItemId,PersonId FROM OrderLinePersons WHERE LineItemId=@lineItemId";
cm.Parameters.Add("@lineItemId", lineItemId);
using (var dr = cm.ExecuteReader())
{
while (dr.Read())
{
var child = new OrderLinePerson();
MarkAsChild(child);
MarkOld(child);
LoadProperty(child, OrderLinePerson.LineItemIdProperty, dr.GetInt32(0));
LoadProperty(child, OrderLinePerson.PersonIdProperty, dr.GetInt32(1));
result.Add(child);
}
}
}
result.RaiseListChangedEvents = true;
return result;
}

In this case, the LineItemId and PersonId column values are directly retrieved in a single query,
and are used to populate each OrderLinePerson child object.
Both implementations achieve the same result: an OrderLinePersons collection populated with
OrderLinePerson child objects.

Throughout this entire Fetch operation, notice how every business object’s metadata is properly
set, using the protected methods from the ObjectFactory base class. All individual objects are
marked as being old with the MarkOld method, and all child objects are marked as children with the
MarkAsChild method.

Update Operation
The update operation occurs when the Save or BeginSave method is called on the OrderEdit root
object. This triggers the insert, update, or delete of the root object, along with all its child and
grandchild objects.

Using CSLA 4: Data Access Page 193


Rev 1.0
Updating the Root Object
The process starts with the server-side data portal invoking the OrderDal object factory’s Update
method. Each DAL provider implements this method differently based on the data access
technology being used. Here’s the SqlCe implementation, for example:
public OrderEdit Update(OrderEdit obj)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
if (obj.IsDeleted)
{
if (!obj.IsNew)
using (BypassPropertyChecks(obj))
Delete(obj.Id);
MarkNew(obj);
}
else if (obj.IsNew)
{
using (BypassPropertyChecks(obj))
{
var newId = InsertOrder(obj.CustomerId, obj.OrderDate, obj.LastEdit);
LoadProperty(obj, OrderEdit.IdProperty, newId);
}
MarkOld(obj);
}
else if (obj.IsDirty)
{
using (BypassPropertyChecks(obj))
{
UpdateOrder(obj.Id, obj.CustomerId, obj.OrderDate, obj.LastEdit);
}
MarkOld(obj);
}
var old = new OrderLineItemDal();
old.UpdateList(obj, obj.OrderLineItems);
return obj;
}
}

This method follows the same structure and steps as I discussed earlier for the PersonEdit
editable root object. The code uses private methods to perform the delete, insert, and update
actions, allowing this method to remain focused on selecting the correct action based on the
metastate of the OrderEdit business object.

Deleting the Child Objects


The Delete method in the OrderDal class must delete the order’s line item data before attempting
to delete the order itself. This is necessary due to relational constraints in the database. The SqlCe
implementation of the Delete method looks like this:
private void Delete(int id)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
var old = new OrderLineItemDal();
old.DeleteForOrder(id);
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "DELETE [Order] WHERE Id=@id";
cm.Parameters.Add("@id", id);
var rowsAffected = cm.ExecuteNonQuery();

Using CSLA 4: Data Access Page 194


Rev 1.0
if (rowsAffected == 0)
throw new InvalidOperationException("Order");
}
}
}

The interesting part of this code is where the DeleteForOrder method on the OrderLineItemDal
object is invoked:
var old = new OrderLineItemDal();
old.DeleteForOrder(id);

This DeleteForOrder method deletes the line item data for the order. As you can imagine,
before each line item is deleted, any related child data in the OrderLinePersons table must be
deleted to avoid a relational integrity conflict.
The SqlCe implementation in the OrderLineItemDal class looks like this:
public void DeleteForOrder(int orderId)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
// delete the line item person data
using (var cm = ctx.Connection.CreateCommand())
{
var lineItems = new List<int>();
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "SELECT Id FROM OrderLineItem WHERE OrderId=@orderId";
cm.Parameters.Add("@orderId", orderId);
using (var dr = cm.ExecuteReader())
while (dr.Read())
lineItems.Add(dr.GetInt32(0));
var olpd = new OrderLineItemPersonDal();
foreach (var item in lineItems)
olpd.DeleteForLineItem(item);
}

// delete the line item data


using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "DELETE OrderLineItems WHERE OrderId=@orderId";
cm.Parameters.Add("@orderId", orderId);
cm.ExecuteNonQuery();
}
}
}

When implementing this behavior with ADO.NET, the trick is to avoid reusing the database
connection when it has an active data reader in use. To avoid any attempts to delete child data
while retrieving the list of line items, the code copies the line item Id values into a List<int> so it
can dispose the data reader before calling the DeleteForLineItem method on the
OrderLineItemPersonDal object to delete the child data for each line item.

The DeleteForLineItem method in the OrderLineItemPersonDal class deletes the data for the
specified line item. For example, here’s the SqlCe implementation:
public void DeleteForLineItem(int lineItemId)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{

Using CSLA 4: Data Access Page 195


Rev 1.0
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "DELETE OrderLineItemPersons WHERE LineItemId=@lineItemId";
cm.Parameters.Add("@lineItemId", lineItemId);
cm.ExecuteNonQuery();
}
}
}

To recap, the Update method in the OrderDal class calls the OrderLineItemDal object to delete
the order’s line items before deleting the order data. The OrderLineItemDal object’s
DeleteForOrder method calls the OrderLineItemPersonDal object to delete the line item’s person
data before deleting the line item records.
You could choose to implement this process in many different ways. In a real application you will
probably use cascading deletes in the database, or you will use more sophisticated database DELETE
queries to optimize this process.
I chose this particular implementation to provide complete detail about the process, and to
demonstrate how each object factory class can implement behaviors relative to a data entity.

Updating the Child Objects


Back in the Update method of the OrderDal class, the OrderEdit object may also be inserted or
updated. The code to do these actions is similar to the code I discussed earlier for the PersonEdit
root object.
The new concept in this code compared to the PersonEdit implementation, is that the
UpdateList method of the OrderLineItemDal object is invoked to update the child items in the
OrderLineItems child collection. This occurs after the root object’s data has been saved to the
database. The UpdateList method is called like this:
var old = new OrderLineItemDal();
old.UpdateList(obj, obj.OrderLineItems);

The UpdateList method in the OrderLineItemDal class is basically the same in all three DAL
implementations. The only difference between the implementations is that the SqlEf and SqlCe
versions wrap the code in a using block for an ObjectContextManager or ConnectionManager
respectively. This ensures that the same database connection is reused throughout the process.
Here’s the code for the SqlCe implementation of the UpdateList method in the OrderLineItemDal
class:
public void UpdateList(OrderEdit order, OrderLineItems orderLineItems)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
var olpd = new OrderLineItemPersonDal();
var deletedList = GetDeletedList<OrderLineItem>(orderLineItems);
foreach (var item in deletedList)
{
olpd.DeleteForLineItem(item.Id);
Delete(item);
}
deletedList.Clear();

foreach (var item in orderLineItems)


{
if (item.IsNew)
Insert(order, item);
else if (item.IsDirty)
Using CSLA 4: Data Access Page 196
Rev 1.0
Update(order, item);
MarkOld(item);
olpd.UpdateList(item, item.Persons);
}
}
}

Like the other collection update methods you’ve seen, this one updates the items in the
DeletedList, then it clears the DeletedList, and finally it updates the items in the collection itself.

The Delete, Insert, and Update methods delete, insert, and update the OrderLineItem child
objects. I won’t show the code for all of these methods, because they are comparable to methods
you’ve already seen.
The important thing to notice are the DeleteForLineItem and UpdateList methods that are
called on the OrderLineItemPersonDal object to update the OrderLinePersons child collection
contained in each OrderLineItem object.

Deleting the Grandchild Objects


The DeleteForLineItem method is called to delete the data for the OrderLinePersons collection
before the OrderLineItem data is deleted:
olpd.DeleteForLineItem(item.Id);
Delete(item);

I discussed the DeleteForLineItem method in the OrderLinePersons class earlier in this section.
This code is reusing that same method.
Once all the items in the OrderLineItems collection’s DeletedList have been deleted, each item
in the collection is inserted or updated based on the child object’s metastate.

Updating the Grandchild Objects


In the OrderLineItemDal class, the UpdateList method on the OrderLineItemPersonDal object is
called to update the OrderLinePersons child collection’s data. This occurs for each line item that is
inserted or updated.
The UpdateList method in the SqlCe implementation of the OrderLineItemPersonDal class
looks like this:
public void UpdateList(OrderLineItem lineItem, OrderLinePersons orderLinePersons)
{
var deletedList = GetDeletedList<OrderLinePerson>(orderLinePersons);
foreach (var item in deletedList)
Delete(item);
deletedList.Clear();

foreach (var item in orderLinePersons)


{
if (item.IsNew)
{
LoadProperty(item, OrderLinePerson.LineItemIdProperty, lineItem.Id);
Insert(item);
}
MarkOld(item);
}
}

Using CSLA 4: Data Access Page 197


Rev 1.0
Because the OrderLinePersons table is a simple link table, there’s no need to implement an
update action, so this code only handles delete and insert actions.
As with all editable collections, the items in the DeletedList are deleted first, and the
DeletedList is cleared. Then the items in the collection itself are inserted.

Immediate Delete Operation


If the OrderEdit editable root class implements static factory methods to support immediate
deletion, that requires that the OrderDal object factory class implement a Delete method.
Each DAL provider will implement the Delete method differently, depending on the data access
technology being used. Perhaps the simplest is the SqlEf implementation, because EF automatically
takes care of deleting all child data associated with the order:
public void Delete(int id)
{
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var item = (from r in ctx.ObjectContext.Orders
where r.Id == id
select r).First();
ctx.ObjectContext.DeleteObject(item);
var count = ctx.ObjectContext.SaveChanges();
if (count == 0)
throw new InvalidOperationException("OrderDal.Delete");
}
}

This implementation retrieves the Order entity using an EF query, deletes the entity from the
ObjectContext, and saves the changes with the SaveChanges method. Because the EF entity model
understands the data relationships in the database, it automatically deletes all relevant data.
The SqlCe implementation is more complex, because it must take care of deleting the line item
child data before deleting the order data:
public void Delete(int id)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
var old = new OrderLineItemDal();
old.DeleteForOrder(id);
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "DELETE [Order] WHERE Id=@id";
cm.Parameters.Add("@id", id);
var rowsAffected = cm.ExecuteNonQuery();
if (rowsAffected == 0)
throw new InvalidOperationException("Order");
}
}
}

Notice how this code reuses same the DeleteForOrder method on the OrderLineItemDal object
that I discussed earlier in this section. Based on that earlier discussion, you should remember that
this DeleteForOrder method uses the DeleteForLineItem method of the OrderLIneItemPersonDal
object to first delete the person data for each line item.

Using CSLA 4: Data Access Page 198


Rev 1.0
In each case the result is the same: the data for the order in the Order table, and all its child
table data, is deleted from the database.
At this point you should understand how to implement persistence for a complex object graph
composed of editable root, child, and grandchild objects. You may choose to implement your
persistence using the highly factored approach shown here, or you might optimize some aspects of
the data access based on the capabilities of the specific data access technology you are using.

Command Object Persistence


The OrderShipper class in the Library.Net project is an implementation of a command object
stereotype. It includes an ObjectFactory attribute to direct the data portal to use an object factory
to execute the command on the application server:
[Csla.Server.ObjectFactory("OrderDal")]
[Serializable]
public class OrderShipper : CommandBase<OrderShipper>

As I discussed in Chapter 5, a command object might or might not interact with the database on
the server. A command object represents any behavior that needs to be executed on the server,
possibly including database interaction, launching a workflow, running an algorithm, or interacting
with other server resources such as the server’s file system.
This includes the possibility of interacting with other business objects on the application server,
and that is the technique I used to implement the Execute method for the OrderShipper command
object. This Execute method is in the OrderDal class of each DAL project because the primary focus
is on the order data entity.

Execute Operation
Each of the three Execute method implementations is basically the same, with the exception that
the SqlCe and SqlEf implementations have the Transactional attribute, and they wrap the code in
a using block for a ConnectionManager and ObjectContextManager to ensure one database
connection is resused for all database interactions.
Here’s the SqlEf implementation in the OrderDal class:
[Csla.Transactional(Csla.TransactionalTypes.TransactionScope)]
public OrderShipper Execute(OrderShipper obj)
{
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
// ship order and generate shipping number
var order = OrderEdit.GetOrderEdit(obj.OrderId);
LoadProperty(obj, OrderEdit.OrderEditProperty, DateTime.Today);

foreach (var item in order.OrderLineItems)


if (!item.ShipDate.HasValue)
LoadProperty(item, Library.OrderLineItem.ShipDateProperty, DateTime.Today);

order = order.Save();

LoadProperty(obj, OrderShipper.ShippingNumberProperty, 123);


return obj;
}
}

Using CSLA 4: Data Access Page 199


Rev 1.0
Although this method could be implemented with direct database access, I have chosen instead
to implement it by using the existing OrderEdit object graph. Notice how the code uses the
standard synchronous static factory method from the OrderEdit class to get the object, then the
object graph is updated to reflect the new ship date values, and then it is saved by calling the
synchronous Save method.

Unit of Work Object Persistence


As I discussed in Chapter 5, there are two basic types of unit of work:

1. Retrieving objects

2. Updating objects

A unit of work object that performs object retrieval is typically implemented as a subclass of the
ReadOnlyBase class. This type of unit of work is a special case of a read-only object, where the
properties of the unit of work object are instances of other business objects. I’ll walk through an
example of this type of unit of work later in this section.
A unit of work object that performs an update of objects is implemented as a command object.
In this case the command object’s properties are instances of the editable root objects that are to
be saved.

Retrieving Objects
The PersonEditUoW class in the Library.Net project is an implementation of a read-only unit of
work stereotype. This class uses the ObjectFactory attribute to provide the data portal with the
name of the object factory type and Fetch method name that should be used to persist this
business object:
[Csla.Server.ObjectFactory("PersonDal", "FetchUoW")]
[Serializable]
public class PersonEditUoW : ReadOnlyBase<PersonEditUoW>

This means that the PersonDal class in each of the three DAL projects includes a FetchUoW
method that is responsible for implementing the Fetch operation for the PersonEditUoW business
object.
Like in Chapter 5, the existing static factory methods on the PersonEdit and CategoryList
classes are used to fetch the two business objects that are retrieved by the PersonEditUoW object.
This means that the FetchUoW methods are essentially the same in each DAL project. Here’s the
SqlEf implementation:
public PersonEditUoW FetchUoW(int personId)
{
var result = new PersonEditUoW();
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
LoadProperty(result, PersonEditUoW.PersonEditProperty, PersonEdit.GetPersonEdit(personId));
LoadProperty(result, PersonEditUoW.CategoryListProperty, CategoryList.GetCategoryList());
}
return result;
}

Using CSLA 4: Data Access Page 200


Rev 1.0
The SqlEf and SqlCe methods wrap the code in a using block for an ObjectContextManager or
ConnectionManager to ensure that the same database connection is reused throughout the
process.
The PersonEdit and CategoryList properties of the unit of work object are loaded with object
references, so those two business objects are returned to the client as a single unit of work.

Updating Objects
The PersonsUpdater class in the Library.Net project is an implementation of a unit of work object
that updates multiple editable root objects as part of a single unit of work and a single database
transaction.
This class includes an ObjectFactory attribute:
[Csla.Server.ObjectFactory("PersonDal")]
[Serializable]
public class PersonsUpdater : CommandBase<PersonsUpdater>

This means that the PersonDal class in each DAL project includes an Execute method to
implement the server-side behavior for this unit of work object. The Execute method uses the
existing behaviors of the PersonEdit editable root objects it is saving. For example, here’s the
SqlCe implementation:
[Csla.Transactional(Csla.TransactionalTypes.TransactionScope)]
public PersonsUpdater Execute(PersonsUpdater obj)
{
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
var person1 = obj.Person1.Save();
LoadProperty(obj, PersonsUpdater.Person1Property, person1);
var person2 = obj.Person2.Save();
LoadProperty(obj, PersonsUpdater.Person2Property, person2);
}
return obj;
}

The SqlCe and SqlEf implementations use the Transactional attribute to ensure that the entire
operation is transactionally protected.
They also wrap the code in a using block for the object context or database connection manager
to ensure that the same database connection is reused throughout the process.
The existing synchronous Save methods from the PersonEdit root objects are used to save the
two objects, and the updated PersonEdit objects are placed into the Person1 and Person2
properties of the command object so they are returned to the calling code.
At this point you should understand how persistence is implemented for unit of work objects,
including read-only and update-based objects.

Read-Only List Persistence


The PersonList class is an example of a read-only root list that contains PersonInfo read-only
objects. These classes can be found in the Library.Net project.

Using CSLA 4: Data Access Page 201


Rev 1.0
A read-only root list supports only the Fetch operation. Because the intent of a read-only list is to
return a set of read-only data for use by the calling code, there is no value in the create, update, or
delete operations.
Only the root object has the ObjectFactory attribute, because this is the only object directly
retrieved through the data portal:
[Csla.Server.ObjectFactory("PersonDal", "FetchList")]
[Serializable]
public class PersonList : ReadOnlyListBase<PersonList, PersonInfo>

A custom Fetch method name is supplied because the PersonDal already has a Fetch method
that retrieves the PersonEdit business object.

Fetch Operation
The Fetch operation is implemented in each DAL project’s PersonDal class. The method in each
class is named FetchList, based on the value in the ObjectFactory attribute applied to the
PersonList read-only list class.
A Fetch method for the PersonList read-only list must implement the following steps:

1. Create an instance of the PersonList business object

2. Set the collection’s IsReadOnly property to false

3. Set the collection’s RaiseListChangedEvents property

4. Retrieve appropriate data from the database

5. Create an instance of the PersonInfo child object for each row of data

6. Add each child object to the PersonList collection

7. Restore the collection’s RaiseListChangedEvents property

8. Set the collection’s IsReadOnly property to false

9. Return the PersonList business object

Here’s the SqlEf implementation of the FetchList method:


public PersonList FetchList()
{
var result = new PersonList();
SetIsReadOnly(result, false);
var rlce = result.RaiseListChangedEvents;
result.RaiseListChangedEvents = false;
using (var ctx = ObjectContextManager<SqlDbEntities>.GetManager("SqlDbEntities"))
{
var data = from r in ctx.ObjectContext.People
select r;
foreach (var item in data)
{
var child = new PersonInfo();
LoadProperty(child, PersonInfo.IdProperty, item.Id);
LoadProperty(child, PersonInfo.NameProperty,
Using CSLA 4: Data Access Page 202
Rev 1.0
string.Format("{0} {1}", item.FirstName, item.LastName));
result.Add(child);
}
}
result.RaiseListChangedEvents = rlce;
SetIsReadOnly(result, true);
return result;
}

You can see how each of the steps is implemented by this method by using the protected
methods provided by the ObjectFactory base class.
The result is that a fully populated PersonList object is returned through the data portal to the
calling code.

Name-Value List Persistence


As I discussed in Chapter 5, a name-value list is a special case of a read-only list. The CategoryList
class in the Library.Net project is an implementation of a name-value list.
This class uses the ObjectFactory attribute so the data portal invokes a FetchList method on
the CategoryDal factory object:
[Csla.Server.ObjectFactory("CategoryDal", "FetchList")]
[Serializable]
public class CategoryList : NameValueListBase<int, string>

The CategoryDal object factory type is used because it represents the logical category data
entity.

Fetch Operation
Each of the three DAL projects implements a FetchList method in the CategoryDal class. They
follow the same steps as for any read-only list. The only difference is that a name-value list supplies
its own NameValuePair child object type, as I discussed in Chapter 5.
The SqlCe implementation looks like this:
public CategoryList FetchList()
{
var result = new CategoryList();
SetIsReadOnly(result, false);
var rlce = result.RaiseListChangedEvents;
result.RaiseListChangedEvents = false;
using (var ctx = ConnectionManager<SqlCeConnection>.GetManager("LocalDb"))
{
using (var cm = ctx.Connection.CreateCommand())
{
cm.CommandType = System.Data.CommandType.Text;
cm.CommandText = "SELECT Id,Category FROM Category";
using (var dr = cm.ExecuteReader())
{
var idIndex = dr.GetOrdinal("Id");
var categoryIndex = dr.GetOrdinal("Category");
while (dr.Read())
result.Add(new Csla.NameValueListBase<int, string>.NameValuePair(
dr.GetInt32(idIndex), dr.GetString(categoryIndex)));
}
}
}
result.RaiseListChangedEvents = true;
SetIsReadOnly(result, true);
Using CSLA 4: Data Access Page 203
Rev 1.0
return result;
}

Each row of data retrieved from the database is used to create a new read-only child object:
result.Add(new Csla.NameValueListBase<int, string>.NameValuePair(
dr.GetInt32(idIndex), dr.GetString(categoryIndex)));

That child object is added to the collection.


In this chapter I have demonstrated how to implement the data portal persistence operations
for each business object stereotype, using the factory implementation data portal model.

Using CSLA 4: Data Access Page 204


Rev 1.0
Conclusion
This book has provided you with the information necessary to implement object persistence for
your CSLA .NET business domain objects.
You have learned how the data portal supports four data access models:

1. Encapsulated invoke

2. Factory implementation

3. Factory invoke

4. Encapsulated implementation

And you have walked through the encapsulated invoke and factory implementation models in
detail.
This is the third book in the Using CSLA 4 ebook series. Subsequent ebooks will explore data
portal configuration, authentication, and how to use a business layer composed of domain objects
to create various types of application interface.

Using CSLA 4: Data Access Page 205


Rev 1.0

You might also like