data layer design

30
Data Layer Design Architecture Guidance......................................................................... 3 Data Layer Guidelines ......................................................................... 3 Data Layer ...................................................................................... 3 Design Considerations ...................................................................... 3 Specific Design Considerations .......................................................... 4 Design Patterns ............................................................................... 4 Designing Data Components ................................................................ 4 Choose Data Access Technology ........................................................ 4 Choose How Retrieving and Persisting Business Entities ........................ 5 Determine How Connecting the Data Source........................................ 5 Determine Strategies for Handling Data Source Errors .......................... 5 Design Service Agents ...................................................................... 5 Data Access Technology Matrix............................................................. 6 Data Access Technologies ................................................................. 6 Object-Relational Data Access ........................................................... 6 Disconnected and Offline Data Access ................................................. 7 SOA and Service Scenarios ............................................................... 7 N-tier and General Scenarios ............................................................. 8 Designing Business Entities ................................................................. 10 Choose the Representation .............................................................. 10 Choose a Design for Business Entities ................................................ 10 Determine Serialization Support ....................................................... 11 Domain Driven Design ..................................................................... 11 Entity Framework ............................................................................. 12 Anti-Patterns To Avoid In N-Tier Applications ........................................ 12 Understanding N-Tier ...................................................................... 12 Custom Service or RESTful Service? .................................................. 12 Anti-Pattern #1: Tight Coupling ........................................................ 13 Anti-Pattern #2: Assuming Static Requirements.................................. 13 Anti-Pattern #3: Mishandled Concurrency .......................................... 14 Anti-Pattern #4: Stateful Services..................................................... 14 Anti-Pattern #5: Two Tiers Pretending to be Three .............................. 15 Anti-Pattern #6: Undervaluing Simplicity ........................................... 15 N-Tier Application Patterns ................................................................. 15 Change Set .................................................................................... 15 DTOs ............................................................................................ 16 Simple Entities ............................................................................... 16 Self-Tracking Entities ...................................................................... 16 Implementing N-Tier with the Entity Framework ................................. 17 Concurrency Tokens ........................................................................ 17 Serialization ................................................................................... 17 Working with the ObjectStateManager ............................................... 18 Patterns Other Than Simple Entities in .NET 3.5 SP1............................ 19 API Improvements in .NET 4 ............................................................ 20 Building N-Tier Apps with EF4 ............................................................. 20 Self-Tracking Entities ...................................................................... 21 Data Transfer Objects ..................................................................... 24 Tips .............................................................................................. 26 Conclusion ..................................................................................... 26 Figures.............................................................................................. 27

Upload: alfred-crombez

Post on 08-Apr-2015

621 views

Category:

Documents


1 download

DESCRIPTION

Small research on how designing a data layer.

TRANSCRIPT

Page 1: Data Layer Design

Data Layer DesignArchitecture Guidance......................................................................... 3

Data Layer Guidelines ......................................................................... 3Data Layer...................................................................................... 3Design Considerations ...................................................................... 3Specific Design Considerations .......................................................... 4Design Patterns ............................................................................... 4

Designing Data Components ................................................................ 4Choose Data Access Technology ........................................................ 4Choose How Retrieving and Persisting Business Entities ........................ 5Determine How Connecting the Data Source........................................ 5Determine Strategies for Handling Data Source Errors .......................... 5Design Service Agents...................................................................... 5

Data Access Technology Matrix............................................................. 6Data Access Technologies ................................................................. 6Object-Relational Data Access ........................................................... 6Disconnected and Offline Data Access................................................. 7SOA and Service Scenarios ............................................................... 7N-tier and General Scenarios............................................................. 8

Designing Business Entities.................................................................10Choose the Representation ..............................................................10Choose a Design for Business Entities................................................10Determine Serialization Support .......................................................11Domain Driven Design.....................................................................11

Entity Framework ............................................................................. 12Anti-Patterns To Avoid In N-Tier Applications ........................................12

Understanding N-Tier ......................................................................12Custom Service or RESTful Service? ..................................................12Anti-Pattern #1: Tight Coupling ........................................................13Anti-Pattern #2: Assuming Static Requirements..................................13Anti-Pattern #3: Mishandled Concurrency ..........................................14Anti-Pattern #4: Stateful Services.....................................................14Anti-Pattern #5: Two Tiers Pretending to be Three ..............................15Anti-Pattern #6: Undervaluing Simplicity ...........................................15

N-Tier Application Patterns .................................................................15Change Set....................................................................................15DTOs ............................................................................................16Simple Entities ...............................................................................16Self-Tracking Entities ......................................................................16Implementing N-Tier with the Entity Framework .................................17Concurrency Tokens........................................................................17Serialization...................................................................................17Working with the ObjectStateManager ...............................................18Patterns Other Than Simple Entities in .NET 3.5 SP1............................19API Improvements in .NET 4 ............................................................20

Building N-Tier Apps with EF4 .............................................................20Self-Tracking Entities ......................................................................21Data Transfer Objects .....................................................................24Tips ..............................................................................................26Conclusion .....................................................................................26

Figures.............................................................................................. 27

Page 2: Data Layer Design

Data Access Technologies ...................................................................27Current Data Technologies ...............................................................27Native Data Technologies.................................................................27WCF Data Services..........................................................................28Future Data Technologies ................................................................28

Entity Framework ..............................................................................29Comparing N-Tier Patterns with EF4 ..................................................29

References........................................................................................ 29Book References ...............................................................................29

Patterns of Enterprise Application Architecture ....................................29Web References ................................................................................29

MSDN ...........................................................................................29MSDN Patterns & Practices ............................................................30

InfoQ ............................................................................................30Blogs ............................................................................................30

Page 3: Data Layer Design

Architecture Guidance

Data Layer Guidelines

Data Layer

• Data access components• Data helpers/utilities: common data access logic sometimes provided by data access

framework (Object/Relational Mapping).• Service agents

Design Considerations

• Choose an appropriate data access technology (Data Access Technology Matrix).• Implement a loosely coupled interface to the data access layer with interface

components such as gateways, interface types or abstract base classes.• Encapsulate data access functionality; The data access layer hides details of data

source access.• Decide how to map application entities to data source structures. Common design

approaches follow the Domain Model or Table Module patterns or use Object/Relational Mapping (O/RM) frameworks. Identify a strategy for populating businessentities from the data source, making them available to the business layer of theapplication (Designing Business Entities).

• Consider consolidating data structures. If you are exposing data through services,consider using Data Transfer Objects (DTOs) to help you organize the data intounified structures. In addition, DTOs encourage coarse-grained operations whileproviding a structure designed to move data across different boundary layers. DTOscan span business entities for aggregate operations. If you are using the Table DataGateway or Active Record pattern, you may consider using a DataTable to representthe data.

• Decide how you will manage connections. The data access layer creates andmanages all connections to all data sources required by the application. Choose anappropriate method for storing and protecting connection information (encryptingsections of the configuration file, limiting storage of configuration information to theserver).

• Determine how you will handle data exceptions. The data access layer catches and(at least initially) handles all exceptions associated with data sources and CRUD(Create, Read, Update, and Delete) operations. Exceptions concerning the dataitself, and data source access and timeout errors, are passed to other layers only ifthe failures affect application responsiveness or functionality.

• Consider security risks. The data access layer protects against attacks that try tosteal or corrupt data, and protects the mechanisms used to gain access to the datasource. Security should be implemented in the data access layer as well as in thedata source. Database access should be through parametrized queries to preventSQL injection attacks succeeding.

• Reduce round trips. Consider batching commands into a single database operation.• Consider performance and scalability objectives.

Page 4: Data Layer Design

• Consider accessing the functionality and data provided by service agents onlythrough data access components. This provides a consistent data access interfaceregardless of the data source.

Specific Design Considerations

• Batching, Binary Large Objects (BLOBs), Connections, Data Format, ExceptionManagement

• Object Relational Mapping◦ Handle O/R mismatches using design patterns such as Repository or O/RM

tools such as the ADO.NET Entity Framework.◦ A Domain Driven Design approach, which is based on modeling entities

based on objects within a domain, is often an appropriate choice.◦ For stateless services, group entities and support options that will partially

load domain entities with only the required data (lazy loading). This allowsapplications to handle the higher user load required to support statelessoperations, and limit the use of resources by avoiding holding initializeddomain models for each user in memory.

• Queries, Stored Procedures, Stored Procedures vs. Dynamic SQL, Transactions,Validation, XML

Design Patterns

• General: Active Record, Data Mapper, Data Transfer Object, Domain Model, QueryObject, Repository, Row Data Gateway, Table Data Gateway, Table Module

• Batching: Parallel Processing, Partitioning• Transactions: Capture Transaction Details, Coarse-Grained Lock, Implicit Lock,

Optimistic Offline Lock, Pessimistic Offline Lock, Transaction Script

Designing Data Components

Choose Data Access Technology

• Choice is determined by the type of data and how data must be manipulated withinthe application.

• Consider using the ADO.NET Entity Framework (EF) if you want to create a datamodel and map it to a relational database, using a flexible schema with theflexibility of separating the mapping schema from the object model. If using EF, alsoconsider using LINQ to Entities allowing queries over strongly typed entities.

• Consider using WCF Data Services (formerly known as ADO.NET Data Services) ifdeveloping a RIA or an n-tier rich client application, wanting to access data througha resource-centric service interface. WCF Data Services is built on top of EF andallows you to expose parts of an Entity Model through a REST interface.

• Consider using ADO.NET Core if you need a low level API for full control over dataaccess or if building an application that must support a disconnected data accessexperience.

• Consider using ADO.NET Sync Services if designing an application that must supportoccasionally connected scenarios, or requires collaboration between databases.

• Consider using LINQ to XML if using XML data in the application, and wanting toexecute queries using the LINQ syntax.

Page 5: Data Layer Design

Choose How Retrieving and Persisting Business Entities

• Choose a strategy for populating business entities from the data store and forpersisting them back to the data store. An impedance mismatch exists between anobject-oriented data model and the relational data store. The most commonapproaches use O/RM tools and frameworks to handle this mismatch.

• Consider using an O/RM framework that translates between domain entities and thedatabase. In a greenfield environment, use an O/RM tool to generate a schema tosupport the object model and provide a mapping between the database and domainentities. In a brownfield environment with an existing database schema, use anO/RM tool for mapping between the domain model and relational model.

• A common pattern is domain driven design, based on modeling entities on objectswithin a domain (see Designing Business Entities).

• Ensure grouping entities correctly to achieve a high level of cohesion. This maymean requiring additional objects within the domain model, and that related entitiesare grouped into aggregate roots.

• When working with Web applications or services, group entities and provide optionsfor partially loading domain entities with only the required data. This minimizes theuse of resources by avoiding holding initialized domain models for each user inmemory, and allows applications to handle higher user load.

Determine How Connecting the Data Source

• Identify how to connect to the data source, protect user credentials, and performtransactions.

• Connections, Connection Pooling, Transactions and Concurrency

Determine Strategies for Handling Data Source Errors

• Design an overall strategy to handle data source errors. All exceptions associatedwith data sources should be caught by the data access layer. Exceptions concerningthe data itself, and data source access and timeout errors, should be handled in thislayer and passed to other layers only if the failures affect application responsivenessor functionality.

• Exceptions, Retry Logic, Timeouts

Design Service Agents

• Service agents manage the semantics of communicating with external services,providing additional services such as basic mapping between the format of the dataexposed by the service and the format the application requires, caching, and offlineor intermittent connection support.

• Adding a service reference generates a proxy and the data classes that representthe data contract from the service.

• For most applications, the service agent acts as an abstraction layer between thebusiness layer and the remote service, and can provide a consistent interfaceregardless of the data format. In smaller applications, the presentation layer, mayaccess the service agent directly.

Page 6: Data Layer Design

Data Access Technology Matrix

Data Access Technologies

• ADO.NET Core provides facilities for the general retrieval, update, and managementof data. It includes providers for SQL Server, OLE DB, ODBC, SQL Server CE, andOracle databases.

• ADO.NET Data Services Framework exposes data using the Entity Data Model,through RESTful Web services accessed over HTTP. The data can be addresseddirectly using URIs. The Web service can be configured to return the data as plainAtom and JavaScript Object Notation (JSON) formats.

• ADO.NET Entity Framework provides a strongly typed data access experience overrelational databases. It moves the data model from the physical structure ofrelational tables to a conceptual model that accurately reflects common businessobjects. It introduces a common Entity Data Model within the ADO.NETenvironment, allowing developers to define a flexible mapping to relational data.This mapping helps to isolate applications from changes in the underlying storageschema. It also supports LINQ to Entities, which provides LINQ support for businessobjects exposed through the Entity Framework. When used as an O/RM product,developers use LINQ to Entities against business objects, which Entity Frameworkwill convert to Entity SQL that is mapped against an Entity Data Model managed bythe Entity Framework. Developers also have the option of working directly with theEntity Data Model and using Entity SQL in their applications.

• ADO.NET Sync Services is a provider included in the Microsoft Sync Framework, andis used to implement synchronization for ADO.NET-enabled databases. It enablesdata synchronization to be built into occasionally connected applications. Itperiodically gathers information from the client database and synchronizes it withthe server database.

• Language Integrated Query (LINQ) provides class libraries that extend C# andVisual Basic with native language syntax for queries. It is primarily a querytechnology supported by different assemblies throughout the .NET Framework.Queries can be performed against a variety of data formats, including DataSet(LINQ to DataSet), XML (LINQ to XML), in-memory objects (LINQ to Objects),ADO.NET Data Services (LINQ to Data Services), and relational data (LINQ toEntities).

• LINQ to SQL provides a lightweight, strongly typed query solution against SQLServer. LINQ to SQL is designed for easy, fast object persistence scenarios wherethe classes in the mid-tier map very closely to database table structures. Startingwith .NET Framework 4.0, LINQ to SQL scenarios will be integrated and supportedby the ADO.NET Entity Framework; however, LINQ to SQL will continue to be asupported technology.

Object-Relational Data Access

Technology Benefits Considerations

ADO.NETEntityFramework(EF)

• Decouples database structurefrom the logical data model.

• Entity SQL provides aconsistent query languageacross all data sources anddatabase types.

• Requires changing the designof entities and queries ifcoming from a moretraditional data accessmethod.

Page 7: Data Layer Design

• Separates meta data intowell-defined architecturallayers.

• Allows business logicdevelopers to access the datawithout knowing databasespecifics.

• Use of a provider modelallows it to be mapped tomany databases.

• Has more layers ofabstraction than LINQ toDataSet.

• Can be used with or withoutLINQ to Entities.

• If database structurechanges, the Entity DataModel must be regeneratedand EF libraries re-deployed.

LINQ toEntities

• A LINQ-based solution forrelational data in theADO.NET EF.

• Provides strongly typed LINQaccess to relational data.

• Supports LINQ-based queriesagainst objects built on top ofthe EF Entity Data Model.

• Processing occurs on theserver.

• Requires the ADO.NET EntityFramework.

LINQ to SQL

• Simple way to read/writeobjects when the data objectmodel matches the physicaldatabase model.

• Provides strongly typed LINQquery access to SQL data.

• Processing occurs on theserver.

• Functionality integrated intothe EF as of .NET Framework4.0.

• Maps LINQ queries directly tothe database instead ofthrough a provider (onlyworks with Microsoft SQLServer).

Disconnected and Offline Data Access

Technology Benefits Considerations

LINQ toDataSet

• Allows full-featured queriesagainst a DataSet.

• All processing occurs on theclient.

ADO.NETSyncServices

• Enables synchronizationbetween databases,collaboration, and offlinescenarios.

• Synchronization can executein the background.

• Provides a hub-and-spoketype of architecture forcollaboration betweendatabases.

• Requires implementation ofown change tracking.

• Exchanging large chunks ofdata during synchronizationcan reduce performance.

SOA and Service Scenarios

Technology Benefits Considerations

Page 8: Data Layer Design

ADO.NETDataServicesFramework

• Data can be addresseddirectly via a URI using aREST-like scheme.

• Data can be returned ineither Atom or JSON formats.

• Includes a lightweightversioning scheme to simplifythe release of new serviceinterfaces.

• The .NET Framework,Silverlight, and AJAX clientlibraries allow to work directlywith objects and providestrongly typed LINQ access toADO.NET Data Services.

• These client libraries alsoprovide a familiar API surfaceto Windows Azure Tables,SQL Data Services, and otherMicrosoft services.

• Is only applicable to service-oriented scenarios.

LINQ to DataServices

• Allows creating LINQ-basedqueries against client-sidedata returned from ADO.NETData Services.

• Supports LINQ-based queriesagainst REST data.

• Can only be used with theADO.NET Data Servicesclient-side framework.

N-tier and General Scenarios

Technology Benefits Considerations

ADO.NETCore

• Includes .NET managed codeproviders for connectedaccess to a wide range ofdata stores.

• Provides facilities fordisconnected data storageand manipulation.

• Code is written directlyagainst specific providers,thereby reducing re-usability.

• The relational databasestructure may not match theobject model, requiringcreation of a data-mappinglayer.

ADO.NETDataServicesFramework

• Data can be addresseddirectly via a URI using aREST-like scheme.

• Data can be returned ineither Atom or JSON formats.

• Includes a lightweightversioning scheme to simplifythe release of new serviceinterfaces.

• Provider model allows anyIQueryable data source to beused.

• Is only applicable to service-oriented scenarios.

• Provides a resource-centricservice that maps well todata-heavy services, but mayrequire more work if amajority of the services areoperation-centric.

Page 9: Data Layer Design

• The .NET Framework,Silverlight, and AJAX clientlibraries provide a familiarAPI surface to Windows AzureTables, SQL Data Services,and other Microsoft services.

ADO.NETEntityFramework

• Separates meta-data intowell-defined architecturallayers.

• Supports LINQ to Entities forquerying complex objectmodels.

• Use of a provider modelallows it to be mapped tomany database types.

• Allows you to build servicesthat have well definedboundaries, and data/servicecontracts for sending andreceiving well defined entitiesacross the service boundary.

• Instances of entities fromyour Entity Data Model aredirectly serializable andconsumable by Web services.

• Full flexibility in structuringthe payload – send individualentities, collections ofentities, or an entity graph tothe server.

• Eventually will allow for truepersistence-ignorant objectsto be shipped across serviceboundaries.

• Requires changing the designof entities and queries ifcoming from a moretraditional data accessmethod.

• Entity objects can be sentacross a network, or the DataMapper pattern can be usedto transform entities intoobjects that are moregeneralized DataContracttypes. The planned POCOsupport will eliminate theneed to transform objectswhen sending them over anetwork.

• Building service endpointsthat receive a generalizedgraph of entities is lessservice oriented thanendpoints that enforcestricter contracts on thetypes of payload that mightbe accepted.

LINQ toObjects

• Allows you to create LINQ-based queries against objectsin memory.

• Represents a new approachto retrieving data fromcollections.

• Can be used directly with anycollections that supportIEnumerable orIEnumerable<T>.

• Can be used to query strings,reflection-based meta-data,and file directories.

• Works only with objects thatimplement the IEnumerableinterface.

LINQ to XML

• Allows you to create LINQ-based queries against XMLdata.

• Is comparable to theDocument Object Model

• Relies heavily on genericclasses.

• Is not optimized to work withuntrusted XML documents,which require different

Page 10: Data Layer Design

(DOM), which brings an XMLdocument into memory, butis much easier to use.

• Query results can be used asparameters to XElement andXAttribute objectconstructors.

security mitigationtechniques.

LINQ to SQL

• Provides a simple techniquefor retrieving and updatingdata as objects when theobject model and thedatabase model are thesame.

• As of .NET Framework 4.0,the Entity Framework will bethe recommended dataaccess solution for LINQ-to-relational scenarios.

• LINQ to SQL will continue tobe supported and will evolvebased on feedback receivedfrom the community.

Designing Business Entities

Choose the Representation

• Custom business objects are common language runtime (CLR) objects that describeentities in your system. The objects are created manually or using an O/RMtechnology. Custom business objects are appropriate if complex business rules orbehavior must be encapsulated along with the related data. If custom businessobjects need to be accessed across AppDomain, process, or physical boundaries, aservice layer can be implemented that provides access via Data Transfer Objects(DTO) and operations that update or edit your custom business objects.

• DataSets are a form of in-memory database closely mapping to the actual databaseschema. DataSets are typically used when building a data-oriented applicationwhere the data in the application logic maps very closely to the database schema.DataSets cannot be extended to encapsulate business logic or business rules.Although DataSets can be serialized to XML, they should not be exposed acrossprocess or service boundaries.

• XML is used to represent business entities only if the presentation layer requires itor if application logic must work with the content based on its schema (for example,a message routing system routing messages based on some well-known nodes inthe XML document). Using and manipulating XML can use large amounts ofmemory.

Choose a Design for Business Entities

• Domain Model is a design pattern that defines business objects representing realworld entities within the business domain. The business or domain entities containboth behavior and structure (business rules and relationships are encapsulatedwithin the domain model). The domain model design requires in-depth analysis ofthe business domain and typically does not map to the relational database models.Consider using it when the business domain has complex business rules that relateto the business domain, when designing a rich client and the domain model can be

Page 11: Data Layer Design

initialized and held in memory, or when not working with a stateless business layerthat requires initialization of the domain model with every request.

• Table Module is a design pattern that defines entities based on tables or viewswithin a database. Operations used to access the database and populate the tablemodule entities are usually encapsulated within the entity, but can also be providedby data access components. Consider using this design pattern if the tables or viewswithin the database closely represent the business entities, or if business logic andoperations relate to a single table or view.

• Custom XML objects represent deserialized XML data that can be manipulated withinthe application code. Objects are instantiated from classes defined with attributesthat map properties within the class to elements and attributes within the XMLstructure. Consider using custom XML objects if the consumed data is already inXML format; XML data must be generated from non-XML data sources; or workingwith read-only document-based data.

Determine Serialization Support

• To pass business entities across physical boundaries such as application domain,process, and service interface boundaries, data must be serialized. Keep in mind theperformance impact when also serializing the data when crossing logical boundaries.

• Expose serializable business entities directly only if required. If another layer in theapplication, on the same physical tier, is consuming business entities, the moststraightforward approach is to expose business entities directly throughserialization. This creates a dependency between the consumers of business entitiesand their implementation. This approach is not recommended unless you canmaintain direct control over the consumers and remote access to business entitiesbetween physical tiers is not required.

• Convert business entities into serializable data transfer objects. To decouple theconsumers of business entities from the internal implementation of the businesslayer, consider translating business entities into special serializable data transferobjects. Data Transfer Object (DTO) is a design pattern used to package multipledata structures into a single structure for transfer across boundaries. Data transferobjects are also useful when the consumers have a different data representation ormodel. This approach allows changing the internal implementation of the businesslayer without affecting the business entity consumers, and allows versioning ofinterfaces more easily.

• Expose XML directly. In some cases, business entities are serialized and exposed asXML. Attributes on the business entities control the serialization.

Domain Driven Design

Domain Driven Design (DDD) is an object-oriented approach to designing software based onthe business domain, its elements and behaviors, and the relationships between them. Itaims to enable software systems that are a realization of an underlying business domain bydefining a domain model expressed in the language of business domain experts. Thedomain model can be viewed as a framework from which solutions can then be rationalized.

Domain Driven Design requires good understanding of the business domain mostly providedto the development team by business domain experts. The whole team agrees to only use asingle language that is focused on the business domain, and which excludes any technicaljargon. Quite often, communication problems within development teams are due not only to

Page 12: Data Layer Design

misunderstanding the language of the domain, but also due to the fact that the domain’slanguage is itself ambiguous.

The domain model is expressed using entities, value objects, aggregate roots, repositories,and domain services; organized into coarse areas of responsibility known as BoundedContexts:

• Entities are objects in the domain model that have a unique identity that does notchange throughout the state changes of the software. Entities encapsulate bothstate and behavior.

• Value objects are objects in the domain model that are used to describe certainaspects of a domain. They do not have a unique identity and are immutable (forexample a customer address object).

• Aggregate roots are entities that group logically related child entities or valueobjects together, control access to them, and coordinate interactions between them.

• Repositories are responsible for retrieving and storing aggregate roots, typicallyusing an O/RM framework.

• Domain services represent operations, actions, or business processes and providefunctionality that refers to other objects in the domain model. At times, certainfunctionality or an aspect of the domain cannot be mapped to any objects with aspecific life-cycle or identity; such functionality can be declared as a domain service(for example, a catalog pricing service within the e-commerce domain).

While Domain Driven Design provides many technical benefits, such as maintainability, itshould be applied only to complex domains where the model and the linguistic processesprovide clear benefits in the communication of complex information, and in the formulationof a common understanding of the domain.

Entity Framework

Anti-Patterns To Avoid In N-Tier Applications

Understanding N-Tier

• A well-designed application has multiple layers with carefully manageddependencies. Those layers live in a single tier or can be split across multiple tiers.

• A layer is an organizational concept, while a tier denotes physical separation or atleast a design that will allow physical separation if needed.

• N-tier applications have at a minimum a database tier, a middle tier that exposes aservice, and a client tier.

• Main focus of presented anti-patterns is creating and consuming custom WCFservices that persist data using the Entity Framework.

Custom Service or RESTful Service?

• The key difference is that REST services are resource-centric while custom servicesare operation-centric.

• With REST, data is divided into resources, each resource is given a URL, andstandard operations on those resources allowing CRUD are implemented.

• With custom services, any arbitrary method can be created and those operationscan be tailored to the specific needs of the application.

Page 13: Data Layer Design

• ADO.NET Data Services in combination with the Entity Framework (EF) makes iteasy to create both RESTful services and clients to work with them. The frameworkcan provide more functionality to RESTful services automatically because theservices are constrained to follow a specific pattern.

• For many applications, the constraints of REST are just too much. For example,sometimes the operations involve multiple resources at once.

• Often the ideal solution for an application is a mixture of REST and custom services.

Anti-Pattern #1: Tight Coupling

• Loose coupling is more difficult than tight coupling, and often the performance is notas good.

• Why introduce an interface and dependency injection? Why build an abstraction withcustom objects mapped to the database instead of filling a DataTable and passing itaround?

• In the short term you gain some efficiency with tight coupling, but in the long runevolving the application can become almost impossible.

• When you have modules that work together closely within a tier, sometimes tightcoupling is the right choice, but in other cases, components need to be kept atarm's length from one another.

• Tiers do not always change at the same rate. The trick is to identify which parts ofthe application might have different rates of change and which parts are tightlycoupled to each other.

• First, consider the boundary between the database and the mid-tier. Using the EFalready helps here because its mapping system provides an abstraction betweenmid-tier code and the database. The same questions should be considered betweenthe mid-tier and the client.

• A particularly common and painful example of this anti-pattern in action is anarchitecture that uses table adapters (moves the data into a DataSet with the sameschema) to retrieve data from the database and Web services that exchangeDataSets with the client (tightly coupling the mid-tier to the client).

Anti-Pattern #2: Assuming Static Requirements

• Two cases where changing requirements have an especially significant impact:◦ Treating the client as trusted◦ The mid-tier service assuming that the client will be implemented using a

particular technology• If you perform validation only on the client and trust the received data on the mid-

tier to send it directly to the database without re-validating, the chance thatsomething will eventually go wrong is much larger than you might think.

• Always validate and enforce some degree of security on the mid-tier, even if thatmay mean validating or performing access control more than once.

• Locking the client into a particular technology is more likely to be a problem. If anapplication survives long enough, technology adjustments will occur. You mayinitially design your application as a rich client desktop application and then laterfind you need to move it to Silverlight. If you then designed your service toexchange DataSets, major surgery would be needed for the service and all existingclients.

Page 14: Data Layer Design

Anti-Pattern #3: Mishandled Concurrency

• Concurrency is a complex-but-important area that the DataSet handles well. Amistake with concurrency is the kind of problem that often only shows up once theapplication is in production. At its core, concurrency management is fairly simple:guarantee data integrity even if two clients try to modify the same data at roughlythe same time.

• For most applications, the concurrency management technique of choice isoptimistic concurrency. The number of times when the exact same entity is modifiedin conflicting ways is quite small.

• Detection is driven by one or more properties, collectively called the concurrencytoken, that change whenever any part of the entity changes. When the applicationupdates an entity back to the database, it first checks to make sure that the valueof the concurrency token in the database is still the same as it was when the entitywas originally read.

• The Entity Framework supports optimistic concurrency by transparently tracking theoriginal value of concurrency tokens when entities are queried and checking forconflicts prior to database updates.

• The correct update pattern is either to make a copy of the entity on the client andsend back both the original version unmodified and the modified version or to writethe client in such a way that it does not modify the concurrency token. If theconcurrency token is updated by a server trigger or automatically because it is arow version number (probably the best plan anyway), then there is no reason tomodify it on the client.

• To make this approach work, when the mid-tier receives the entity from client, youneed to attach it to the context and then go over its properties, manually markingthem as modified. In either case, though, you will fix both of the problems with theanti-pattern at once. You will no longer query the database twice, and theconcurrency check will be based on the correct value of the token (from the initialquery) rather than some later value.

Anti-Pattern #4: Stateful Services

• The next anti-pattern comes up when developers try to simplify things by keepingthe context around across multiple service calls.

• Managing the context lifetime can get tricky quickly. When you have multiple clientscalling the services, you have to maintain a separate context for each client or riskcollisions between them. And even if you solve those issues, you will end up withmajor scalability problems.

• These scalability problems are not only the result of tying up server resources forevery client. In addition you will have to guard against the possibility that a clientmight start a unit of work, but never complete it, by creating an expiration scheme.Further, if you decide that you need to scale your solution out by introducing a farmwith multiple mid-tier server, then you will have to maintain session affinity to keepa client associated with the same server where the unit of work began.

• The best solution is to avoid them altogether by keeping your mid-tier serviceimplementations stateless. If some information needs to be maintained for a unit ofwork that extends across multiple service calls, then that information should bemaintained by the client.

Page 15: Data Layer Design

Anti-Pattern #5: Two Tiers Pretending to be Three

• "Why can't you make the Entity Framework serialize queries across tiers?" "Oh, andwhile you are at it, can you support initiating updates from another tier as well?"

• If you could create an Entity Framework ObjectContext on the client tier, executeany Entity Framework query to load entities into that context, modify those entities,and then have SaveChanges push an update from the client through the mid-tier tothe database server—if you could do all that, then why have the mid-tier at all? Whynot just expose the database directly?

Anti-Pattern #6: Undervaluing Simplicity

• In the name of avoiding all the anti-patterns discussed previously, it is easy todecide that you need to create the most carefully architected, multi-tier, fullyseparated, re-validating, super design that you can come up with.

• It is important to think over your goals and consider whether you are going to needthe investment n-tier requires. Simple is good. Sometimes a two-tier app is just thething.

• If you can make the problem simpler, do so.

N-Tier Application Patterns

Change Set

• The idea behind the change set pattern is to create a serializable container that cankeep the data needed for a unit of work together and, ideally, perform changetracking automatically on the client. This approach also tends to be quite full-featured and is easy to use on the mid-tier and on the client. DataSet is the mostcommon example of this pattern.

• Some of the downsides of this pattern:◦ The change set pattern places significant constraints on the client because

the wire format tends to be very specific to the change set and hard tomake interoperable.

◦ The wire format is usually quite inefficient. Change sets are designed tohandle arbitrary schemas, so overhead is required to track the instanceschema.

◦ The ease with which you can end up tightly coupling two or more of thetiers, which causes problems if you have different rates of change.

◦ Easy to abuse the change set.• Because it is so easy to put data into the change set, send it to the mid-tier, and

then persist, you can do so without verifying on the mid-tier that the changes youare persisting are only of the type that you expect.

• This pattern is best used in cases where you have full control over client deploymentso that you can address the coupling and technology requirement issues. It is alsothe right choice if you want to optimize for developer efficiency rather than runtimeefficiency. If you do adopt this pattern, be sure to validate any changes on the mid-tier rather than blindly persisting whatever changes arrive.

Page 16: Data Layer Design

DTOs

• The intent of the Data Transfer Objects (DTOs) pattern is to separate the client andthe mid-tier by using different types to hold the data on the mid-tier and the dataon the client and in the messages sent between them. The DTO approach requiresthe most effort to implement, but when implemented correctly, it can achieve themost architectural benefits.

• You can develop and evolve your mid-tier and your client on completely separateschedules because you can keep the data that travels between the two tiers in astable format regardless of changes made on either end. Naturally, at times you'llneed to add some functionality to both ends, but you can manage the rollout of thatfunctionality by building versioning plus backward and forward compatibility into thecode that maps the data to and from the transfer objects.

• Because you explicitly design the format of the data for when it transfers betweenthe tiers, you can use an approach that interoperates nicely with clients that usetechnologies other than .NET. You can use a format that is very efficient to sendacross the wire, or you can choose to exchange only a subset of an entity's data forsecurity reasons.

• The downside is the extra effort required to design three different sets of types foressentially the same data and to map the information between the types.

• For many projects you might be able to achieve your goals with a pattern thatrequires less effort.

Simple Entities

• The simple entities pattern reuses the mid-tier entity types on the client striving tokeep the complexity of the data structure to a minimum and passing entityinstances directly to service methods. Only allows simple property modification toentity instances on the client. More complex operations, such as changing therelationships or accomplishing a combination of inserts, updates, and deletes,should be represented in the structure of the service methods.

• No extra types are required and no effort has to be put into mapping data from onetype to another. If you can control deployment of the client, you can reuse the sameentity structures.

• The primary disadvantage is that more methods are usually required on the serviceif you need to accomplish complex scenarios that touch multiple entities. This leadsto either chatty network traffic, where the client has to make many service calls toaccomplish a scenario or special-purpose service methods with many arguments.

• The simple entities approach is especially effective when you have relatively simpleclients or when the scenarios are such that operations are homogenous. Then theservice methods are generally either queries for read-only data, modifications toone entity at a time without changing much in the way of relationships, or insertinga set of related entities all at once for a specific entity.

Self-Tracking Entities

• The self-tracking entities pattern is built on the simple entities pattern. It createssmart entity objects that keep track of their own changes and changes to relatedentities. To reduce constraints on the client, the entities are plain-old CLR objects(POCO) that are not tied to any particular persistence technology. They justrepresent the entities and some information about whether they are unchanged,modified, new, or marked for deletion.

Page 17: Data Layer Design

• Because the tracking information is built into the entities themselves and is specificto their schema, the wire format can be more efficient than with a change set.Because they are POCO, they make few demands on the client and interoperatewell. Because validation logic can be built into the entities themselves, you canmore easily remain disciplined about enforcing the intended operations for aparticular service method.

• There are two primary disadvantages for self-tracking entities compared to changesets:

◦ A change set implementation can allow multiple change sets to be merged ifthe client needs to call more than one service method to retrieve the data itneeds.

◦ The entity definitions are somewhat complicated because they include thetracking information directly instead of keeping that information in aseparate structure outside the entities.

• Self-tracking entities are not as thoroughly decoupled as DTOs, and there are timeswhen more efficient wire formats can be created with DTOs.

• Nothing prevents you from using a mix of DTOs and self-tracking entities.

Implementing N-Tier with the Entity Framework

• The EF provides a foundation for addressing persistence concerns:◦ Declarative mapping between the database and conceptual entities, which

decouples your mid-tier from the database structure.◦ Automatic concurrency checks on updates as long as appropriate change-

tracking information is supplied◦ Transparent change tracking on the mid-tier.

• The EF is a LINQ provider, which means that it is relatively easy to createsophisticated queries that can help with mapping entities to DTOs.

• The EF can be used to implement any of the four patterns described earlier◦ EF release in Visual Studio 2008 SP1/.NET 3.5 SP1 makes patterns other

than the simple entities pattern very difficult to implement.◦ EF release in Visual Studio 2010/.NET 4 makes implementing the other

patterns easier.

Concurrency Tokens

• The best option for concurrency token is to use a row version number. A row'sversion automatically changes whenever any part of the row changes in thedatabase.

• The next best option is to use something like a time stamp and add a trigger to thedatabase updating the time stamp whenever a row is modified.

• In the Entity Designer, select the property and set its Concurrency Mode to Fixed.You can have more than one property in the same entity with Concurrency Mode setto Fixed, but this is usually not necessary.

Serialization

• The EF automatically generates DataContract attributes on the types andDataMember attributes on the persistable properties of the entities so that theydirectly can be used in WCF. This includes navigation properties, which means thatif you retrieve a graph of related entities into memory, the whole graph is serialized

Page 18: Data Layer Design

automatically. The generated code supports binary serialization and XMLserialization (only to single entities, not graphs).

• The change-tracking information which is stored in the ObjectStateManager (part ofObjectContext) is not serialized. In the simple entities pattern, you typically retrieveunmodified entities from the database on the mid-tier and serialize them to theclient:

public Customer GetCustomerByID(string id){ using (var ctx = newNorthwindEntities()) { return ctx.Customers.Where(c => c.CustomerID== id).First(); } }

Working with the ObjectStateManager

• For two-tier persistence operations, the ObjectStateManager does its jobautomatically for the most part.

It keeps track of the existence of each entity under its control; its key value; an EntityState value,which can be unchanged, modified, added, or deleted; a list of modified properties; and the originalvalue of each modified property. When you retrieve an entity from the database, it is added to thelist of entities tracked by the state manager, and the entity and the state manager work together tomaintain the tracking information. If you set a property on the entity, the state of the entityautomatically changes to Modified, the property is added to the list of modified properties, and theoriginal value is saved. Similar information is tracked if you add or delete an entity. When you callSaveChanges on the ObjectContext, this tracking information is used to compute the updatestatements for the database. If the update completes successfully, deleted entities are removedfrom the context, and all other entities transition to the unchanged state so that the process canstart over again.

• When sending entities to another tier, the automatic change tracking process isinterrupted. To perform an update on the mid-tier by using information from theclient, you need two special methods of ObjectContext:

◦ The Attach method tells the state manager to start tracking an entity. Thereare two critical things about Attach to keep in mind:

▪ At the end of a successful call to Attach, the entity will always be inthe unchanged state. If you want to eventually get the entity intosome other state, such as modified or deleted, you need to takeadditional steps to transition the entity to that state. The value anentity's property has when you attach it will be considered theoriginal value for that property. The value of the concurrency tokenwhen you attach the entity will be used for concurrency checks.

▪ If you attach an entity that is part of a graph of related entities, theAttach method will walk the graph and attach each of the entities itfinds.

◦ The ApplyPropertyChanges method implements the other half of adisconnected entity modification scenario. It looks in theObjectStateManager for another entity with the same key as its argumentand compares each regular property of the two entities. When it finds aproperty that is different, it sets the property value on the entity in the statemanager to match the value from the entity passed as an argument to themethod. It is important to note that the method operates only on "regular"

Page 19: Data Layer Design

properties and not on navigation properties, so it affects only a single entity,not an entire graph. It was designed especially for the simple entitiespattern.

public void UpdateCustomer(Customer original, Customer modified) {using (var ctx = new NorthwindEntities()) { ctx.Attach(original);ctx.ApplyPropertyChanges(modified.EntityKey.EntitySetName,modified); ctx.SaveChanges(); }}

• Above mechanism adds some complication to the client which needs to copy theentity before modifying it. An altenative is to attach the modified entity and usesome lower-level APIs on the ObjectStateManager to tell it that the entity should bein the modified state and that every property is modified.

public void UpdateCustomer(Customer modified){ using (var ctx = newNorthwindEntities()) { ctx.Attach(modified); var stateEntry =ctx.ObjectStateManager.GetObjectStateEntry(modified); foreach (varpropertyName in stateEntry.CurrentValues.DataRecordInfo.FieldMetadata .Select(fm => fm.FieldType.Name)) {stateEntry.SetModifiedProperty(propertyName); } }ctx.SaveChanges();}

• ObjectStateManager mechanism can also be used for service methods to add anddelete entities.

public void AddCustomer(Customer customer){ using (var ctx = newNorthwindEntities()) { ctx.AddObject("Customers", customer);ctx.SaveChanges(); }}public void DeleteCustomer(Customer customer){ using (var ctx = newNorthwindEntities()) { ctx.Attach(customer);ctx.DeleteObject(customer); ctx.SaveChanges(); }}

• The approach can be extended to methods that change relationships betweenentities or perform other operations. The key concept is to get the state managerinto a state it would have been in if entities were queried from the database, thenmake changes to the entities and then call SaveChanges.

Patterns Other Than Simple Entities in .NET 3.5 SP1

• The change set pattern can be implemented. See the sample of this pattern writtenwith one of the prerelease betas of the EF. Consider creating an ObjectContext onthe client with only the conceptual model metadata and use that as a client-sidechange tracker.

• Implementing DTOs is not that much more difficult with the first release of the EFthan it will be in later releases. You have to write your own code or use anautomatic mapper to move data between your entities and the DTOs. Considerusing LINQ projections to copy data from queries directly into your DTOs.

Page 20: Data Layer Design

public List<CustomerDTO> GetCustomerDTOs(){ using (var ctx = newNorthwindEntities()) { var query = from c in ctx.Customers selectnew CustomerDTO() { Name = c.ContactName, Phone = c.Phone }; returnquery.ToList(); }}

• Self-tracking entities is the hardest pattern to implement in the SP1 release:◦ EF in .NET 3.5 SP1 does not support POCO, so self-tracking entities will have

a dependency on the 3.5 SP1 version of .NET, and the serialization formatwill not be as suitable for interoperability.

◦ Implementing a method on the mid-tier to handle a mixed graph is quitedifficult. One of the nice features of self-tracking entities is that you cancreate a single graph of related entities with a mix of operations: someentities can be modified, others new, and still others marked for deletion.

API Improvements in .NET 4

• The EF will support complete persistence ignorance for entity classes (POCO). Allowscreation of entities that have no dependencies on the EF or other persistence-related DLLs. A single entity class used for persisting data with the EF will also workon Silverlight or earlier versions of .NET. POCO helps isolate the business logic inyour entities from persistence concerns and makes it possible to create classes witha clean, interoperable serialization format.

• Working with the ObjectStateManager will be easier because the state transitionconstraints have been relaxed.

• Allow building a model in which an entity exposes a foreign key property that can bemanipulated directly.

• EF will use the T4 template engine to allow easy, complete control over the codethat is generated for entities. Allows Microsoft releasing templates that generatecode for a variety of scenarios and usage patterns, and allows customizing thosetemplates. One of the templates will produce classes that implement the self-tracking entities pattern with no custom coding required on your part.

Building N-Tier Apps with EF4

While Simple Entities is usually not the preferred pattern for n-tier applications, it is themost viable option in the first release of the EF. EF4 significantly changes the options for n-tier programming with the framework:

• New framework methods that support disconnected operations, such asChangeObjectState and ChangeRelationshipState, which change an entity orrelationship to a new state (added or modified, for example); ApplyOriginalValues,which lets you set the original values for an entity; and the new ObjectMaterializedevent, which fires whenever an entity is created by the framework.

• Support for Plain Old CLR Objects (POCO) and foreign key values on entities. Thesefeatures let you create entity classes that can be shared between the mid-tierservice implementation and other tiers, which may not have the same version of theEntity Framework (.NET 2.0 or Silverlight, for example). POCO objects with foreignkeys also have a straightforward serialization format that simplifies interoperabilitywith platforms like Java. The use of foreign keys also enables a much simplerconcurrency model for relationships.

Page 21: Data Layer Design

• T4 templates to customize code generation. These templates provide a way togenerate classes implementing the Self-Tracking Entities or DTOs patterns.

These features are used to implement the Self-Tracking Entities pattern in a template(making it more accessible) and while DTOs still require the most work during initialimplementation, this process is also easier with EF4 (see figure).

The right pattern for a particular situation depends on a lot of factors:• DTOs provide many architectural advantages at a high initial implementation cost.• DTOs are best choice as your application becomes larger and more complex or if

you have requirements that can’t be met by Self-Tracking Entities, like differentrates of change between the client and the server.

• Change Set exhibits few good architectural characteristics but is easy to implement(when available for a particular technology—for example, the DataSet in ADO.NET).

• Pragmatic/agile balance between these concerns by starting with Self-TrackingEntities and moving to DTOs if the situation warrants it.

• Self-Tracking Entities represents a much better trade-off than Change Set or SimpleEntities.

Self-Tracking Entities

Start by creating an Entity Data Model that represents the conceptual entities and map it toa database:

• Reverse engineer a model from an existing database• Create a model from scratch and then generate a database to match

Replace the default code generation template with the Self-Tracking Entities template:• Right-click the entity designer surface and choose Add Code Generation Item.• Choose the Self-Tracking Entities template from the list of installed templates.• Turns off default code generation and adds two templates: one generates the

ObjectContext, and the other generates entity classes. Separating into twotemplates makes it possible to split the code into separate assemblies, one forentity classes and one for context.

The main advantage is that you can have your entity classes in an assembly that has nodependencies on the Entity Framework. This way, the entity assembly and any businesslogic implemented there can be shared by the mid-tier and the client if you want.

The context is kept in an assembly that has dependencies on both the entities and the EF:• If the client is running .NET 4, you can just reference the entity assembly from the

client project.• If your client is running an earlier version of .NET or is running Silverlight, you can

add links from the client project to the generated files and recompile the entitysource in that project (targeting the appropriate CLR).

The generated entity classes are simple POCO classes:• Provide basic storage of entity properties.• Keep track of changes to the entities: overall state of an entity, changes to critical

properties such as concurrency tokens, and changes in relationships betweenentities.

• The extra tracking information is part of the DataContract definition for the entities.

Page 22: Data Layer Design

On the client of the service, changes to the entities are tracked automatically even thoughthe entities are not attached to any context. Each generated entity has code like thefollowing for each property. If you change a property value on an entity with the Unchangedstate, the state is changed to Modified:

[DataMember]public string ContactName{ get { return _contactName; }set { if (!Equals(_contactName, value)) { _contactName = value;OnPropertyChanged("ContactName"); } }} private string _contactName;

Similarly, if new entities are added to a graph or entities are deleted from a graph, thatinformation is tracked:

• Since the state of each entity is tracked on the entity itself, the tracking mechanismbehaves as you would expect even when you relate entities retrieved from morethan one service call.

• If you establish a new relationship, just that change is tracked: the entities involvedstay in the same state, as though they had all been retrieved from a single servicecall.

The context template adds the method ApplyChanges to the generated context. It attachesa graph of entities to the context and sets the information in the ObjectStateManager tomatch the information tracked on the entities. With the track information of the entitiestrack and ApplyChanges, the generated code handles both change tracking and concurrencyconcerns, two of the most difficult parts of correctly implementing an n-tier solution.

As a concrete example, following shows a simple ServiceContract with Self-Tracking Entitiesof an order submission system (based on Northwind):

[ServiceContract]public interface INorthwindSTEService{[OperationContract] IEnumerable<Product> GetProducts();[OperationContract] Customer GetCustomer(string id);[OperationContract] bool SubmitOrder(Order order);[OperationContract] bool UpdateProduct(Product product);}

The GetProducts service method is used to retrieve reference data on the client about theproduct catalog. It retrieves a customer and a list of that customer’s orders:

public Customer GetCustomer(string id){ using (var ctx = newNorthwindEntities()) { return ctx.Customers.Include("Orders").Where(c => c.CustomerID == id) .SingleOrDefault(); } }

To illustrate client usage of self-tracking entities, consider the creation of an order withappropriate order detail lines, updating parts of the customer entity with the latest contactinformation, and also deleting any orders that have a null OrderDate (system marksrejected orders that way):

var svc = new ChannelFactory<INorthwindSTEService>(

Page 23: Data Layer Design

"INorthwindSTEService").CreateChannel();

var products = new List<Product>(svc.GetProducts());

var customer = svc.GetCustomer("ALFKI");customer.ContactName = "Bill Gates";

foreach (var order in customer.Orders.Where(o => o.OrderDate == null).ToList())

{customer.Orders.Remove(order);

}

var newOrder = new Order();newOrder.Order_Details.Add(new Order_Detail()

{ProductID = products.Where(p => p.ProductName == "Chai")

.Single(),Quantity = 1

});customer.Orders.Add(newOrder);var success = svc.SubmitOrder(newOrder);

Note that when creating the order detail entity for the new order, just the ProductIDproperty is set rather than the Product entity itself. This is the new foreign key relationshipfeature in action. It reduces the amount of information that travels over the wire becauseyou serialize only the ProductID back to the mid-tier, not a copy of the product entity.

It’s in the implementation of the SubmitOrder service method that Self-Tracking Entitiesreally shines:

public bool SubmitOrder(Order newOrder){

using (var ctx = new NorthwindEntities()){

ctx.Orders.ApplyChanges(newOrder);ValidateNewOrderSubmission(ctx, newOrder);return ctx.SaveChanges() > 0;

}}

The call to ApplyChanges reads the change information from the entities and applies it tothe context in a way that makes the result the same as if those changes had beenperformed on entities attached to the context the whole time.

ValidateNewOrderSubmission, added to the service implementation, examines theObjectStateManager to make sure that only the kinds of changes we expect in a call toSubmitOrder are present. Validation is really important because ApplyChanges pushes

Page 24: Data Layer Design

whatever changes it finds in an entire graph of related objects into the context. Theexpectation that a client will only add new orders, update the customer and delete rejectedorders doesn’t mean that a buggy (or even malicious) client would not do something else.Regardless of the n-tier pattern that is used, it is a critical rule that changes are alwaysvalidated before saving them to the database.

A second critical design principle is that you should develop separate, specific servicemethods for each operation. Without these separate operations, you do not have a strongcontract representing what is and isn’t allowed between your two tiers, and properlyvalidating your changes can become impossible.

Data Transfer Objects

In DTOs, instead of sharing a single entity implementation between the mid-tier and theclient, you create a custom object that’s used only for transferring data over the service anddevelop separate entity implementations for the mid-tier and the client:

• It isolates your service contract from implementation issues on the mid-tier and theclient, allowing that contract to remain stable even if the implementation on thetiers changes.

• It allows you to control what data flows over the wire. You can avoid sendingunnecessary data or data the client is not allowed to access.

• The service contract is designed with the client scenarios in mind so that the datacan be reshaped between the mid-tier entities and the DTOs (maybe by combiningmultiple entities into one DTO).

• Benefits come at the price of having to create and maintain one or two more layersof objects and mapping.

Following code applies DTOs to the order submission example. Note the CustomerVersionfield which contains the row version information used for concurrency checks on thecustomer entity:

public class NewOrderDTO{

public string CustomerID { get; set; }public string ContactName { get; set; }public byte[] CustomerVersion { get; set; }public List<NewOrderLine> Lines { get; set; }

}public class NewOrderLine{

public int ProductID { get; set; }public short Quantity { get; set; }

}

The service method that accepts this DTO uses the same lower-level Entity Framework APIsthat the Self-Tracking Entities template uses to accomplish its tasks. First, you create agraph of customer, order and order detail entities based on the information in the DTO:

var customer = new Customer{

Page 25: Data Layer Design

CustomerID = newOrderDTO.CustomerID,ContactName = newOrderDTO.ContactName,Version = newOrderDTO.CustomerVersion,

};

var order = new Order{

Customer = customer,};

foreach (var line in newOrderDTO.Lines){

order.Order_Details.Add(new Order_Detail{

ProductID = line.ProductID,Quantity = line.Quantity,

});}

Then you attach the graph to the context and set the appropriate state information:

ctx.Customers.Attach(customer);var customerEntry =ctx.ObjectStateManager.GetObjectStateEntry(customer);customerEntry.SetModified();customerEntry.SetModifiedProperty("ContactName");

ctx.ObjectStateManager.ChangeObjectState(order, EntityState.Added);foreach (var order_detail in order.Order_Details){

ctx.ObjectStateManager.ChangeObjectState(order_detail,EntityState.Added);

}return ctx.SaveChanges() > 0;

Flow:• Attach the entire graph to the context: each entity is in the Unchanged state.• Tell the ObjectStateManager to put the customer entity in the Modified state with

only the ContactName property marked as modified (the only customer infoprovided by the DTO).

• Change the state of the order and each of its order details to Added.• Apply changes to customer and order with SaveChanges.

Because you have a very specific DTO for each scenario no change validations are required:you are interpreting the DTO object as you map the information from it into your entities.Nevertheless, in many cases additional validation of the values or other business rules isstill required.

One other consideration is properly handling concurrency exceptions using the versioninformation of the customer entity included in the DTO. You can either map this exception

Page 26: Data Layer Design

to a WCF fault for the client to resolve the conflict, or you can catch the exception and applysome sort of automatic policy for handling the conflict.

Tips

Some tips to watch out for:• Reuse the Self-Tracking Entity template’s generated entity code on your client. If

you use proxy code generated by Add Service Reference in Visual Studio, thingslook right, but the entities don’t actually keep track of their changes on the client.

• Create a new ObjectContext instance in a Using statement for each service methodso that it is disposed of before the method returns. This step is critical for scalabilityof your service (closing database connections across service calls, garbage collectingtemporary state used by a particular operation). The Entity Frameworkautomatically caches metadata and other information it needs in the app domain,and ADO.NET pools database connections, so re-creating the context each time is aquick operation.

• Use the new foreign key relationships feature whenever possible. It makeschanging relationships between entities much easier. The relationship is simply aproperty of the entity, and if the entity passes its concurrency check, no furthercheck is needed. You can change a relationship just by changing the foreign keyvalue.

• Be careful of EntityKey collisions when attaching a graph to an ObjectContext. If,for instance, you are using DTOs and parts of your graph represent newly addedentities for which the entity key values have not been set because they will begenerated in the database, you should call the AddObject method to add the wholegraph of entities first and then change entities not in the Added state to theirintended state (rather than calling the Attach method and then changing Addedentities to that state). Otherwise, when you first call Attach, the Entity Frameworkthinks that every entity should be put into the Unchanged state, which assumes thatthe entity key values are final. If more than one entity of a particular type has thesame key value (0, for example), the Entity Framework will throw an exception. Bystarting with an entity in the Added state, you avoid this problem because theframework does not expect Added entities to have unique key values.

• Turn off automatic lazy loading (new EF4 feature) when returning entities fromservice methods. If you don’t, the serializer will trigger lazy loading and try toretrieve additional entities from the database, which will cause more data than youintended to be returned. Self-Tracking Entities does not have lazy loading turned onby default, but if you are creating a DTOs solution, this is something to watch outfor.

Conclusion

The .NET 4 release of the Entity Framework makes the creation of architecturally sound n-tier applications much easier. For most applications, it is recommended starting with theSelf-Tracking Entities template, which simplifies the process and enables the most reuse. Ifyou have different rates of change between service and client, or if you need absolutecontrol over your wire format, you should move up to a Data Transfer Objectsimplementation. Regardless of which pattern you choose, always keep in mind the keyprinciples that the antipatterns and patterns represent and never forget to validate yourdata before saving.

Page 27: Data Layer Design

Figures

Data Access Technologies

Current Data Technologies

Native Data Technologies

Page 28: Data Layer Design

WCF Data Services

Future Data Technologies

Page 29: Data Layer Design

Entity Framework

Comparing N-Tier Patterns with EF4

References

Book References

Patterns of Enterprise Application Architecture

[PEAA, Ch.09]

Patterns of Enterprise Application Architecture, Chapter 9, Domain LogicPatterns

[PEAA, Ch.10]

Patterns of Enterprise Application Architecture, Chapter 10, Data SourceArchitectural Patterns

[PEAA, Ch.13]

Patterns of Enterprise Application Architecture, Chapter 13, Object-RelationalMetadata Mapping Patterns

[PEAA, Ch.15]

Patterns of Enterprise Application Architecture, Chapter 15, DistributionPatterns

[PEAA, Ch.16]

Patterns of Enterprise Application Architecture, Chapter 16, OfflineConcurrency Patterns

Web References

MSDN

[DDC] Data Developer Center

[DDTAG] Microsoft Data Development Technologies At-a-Glance

Page 30: Data Layer Design

[GDDP]

Guide to the Data Development Platform for .NET Developers"The ADO.NET Entity Framework should be considered thedevelopment API of choice for .NET SQL Server programmersgoing forward. The Entity Framework raises the abstractionlevel of data access from logical relational database-basedaccess to conceptual model-based access."

[IDDD] An Introduction To Domain-Driven Design

[APAN] Anti-Patterns To Avoid In N-Tier Applications

[NTAP] N-Tier Application Patterns

[BNTAE] Building N-Tier Apps with EF4

[EFFAQ] Entity Framework FAQ

MSDN Patterns & Practices

[DAAG] .NET Data Access Architecture Guide

[DDTC] Designing Data Tier Components and Passing Data Through Tiers

[ESPDN] Enterprise Solution Patterns Using Microsoft .NET

InfoQ

[DDDQ] Domain Driven Design Quickly

[DDDP] Domain Driven Design and Development In Practice

Blogs

[BASILRIA,Overview]

Business Apps Example for Silverlight 3 RTM and .NET RIA Services,Overview, Blog Brad Adams

[BDSEF] Blog Danny Simmons - Dev manager for the Entity Framework Team

[WSTEEF] Walkthrough: Self Tracking Entities for the Entity Framework, BlogADO.NET Team

[FKREF] Foreign Key Relationships in the Entity Framework, Blog ADO.NET Team