130 likes | 253 Views
Data Access Technologies and Patterns. Earlier DA Methods. DAO RDO ADO ADO.net (Datasets). Entity Framework 4 A new lease of easier life. Programming Against a Model, Not the Database - frees you from being concerned with the structure of your database
E N D
Earlier DA Methods • DAO • RDO • ADO • ADO.net (Datasets)
Entity Framework 4A new lease of easier life • Programming Against a Model, Not the Database - frees you from being concerned with the structure of your database • In a nutshell - Entity Framework can remove the pain of having not only to interact with the database, but also to translate the tabular data into objects.
Repository Pattern • A Repository mediates between the domain and data mapping layers, acting like an in-memory domain object collection. • Client objects construct query specifications declaratively and submit them to Repository for satisfaction. • Objects can be added to and removed from the Repository, as they can from a simple collection of objects, and the mapping code encapsulated by the Repository will carry out the appropriate operations behind the scenes. • Conceptually, a Repository encapsulates the set of objects persisted in a data store and the operations performed over them, providing a more object-oriented view of the persistence layer. Repository also supports the objective of achieving a clean separation and one-way dependency between the domain and data mapping layers.
Repository Pattern • The Repository only accepts domain objects and returns domain objects but not any data specific infrastructure objects such as the DataSet, DataRow, DataReader and etc. • The repository itself provides an in-memory like collection interface for accessing domain objects. The repository itself provide a clean separation of concern by abstracting the Create, Update, Read and Delete operations performed to the data stores in a transparent manner through translating the operations into the data access calls relevant to the data store.
Repository Pattern • The effect, the domain model is decoupled from the need of storing objects and accessing the underlying persistence infrastructure. • Domain Driven Design, as it name implies, we are designing our applications from the point of view of the Domain based on the feedback and requirement gathering. There is no database involves in this case and by bringing the elements of database into the picture, we would risk compromising the purity of the domain model just to support the persistence concern we have chosen.
Specification pattern • The Specification pattern helps in formalizing and declaring condition as set of specification that encapsulate business logic. • With specification, we split the logic of how a selection is made from the objects we are selecting. By having this piece of small logic sit on its own give us huge advantages over the traditional query pattern. • Every time there is a new criterion or criteria change, we need only to add new type of concrete specification or change the existing specification type without the need to modify or add Get/Find methods to the repository which increase the number of Get/Find permutations.
Implications of direct coupling • If the business layer is taking a direct concrete references to the data layer, then it would be impossible to test the business layer in isolation because all the real dependencies of the data layer such as the database and other states have to be ready at the time when the business layer needed to be unit tested. • This incurs high cost for practicing Test Driven Development as all the concrete dependencies need to be in a known state such as the database initial data and time spent in running the tests would be significant as accessing external resources such as file and database takes times. Since we are using the real dependencies during the tests, then those failing tests are hard to be diagnosed as the failure in the business layer may be related to the problem in the lower data layer. • Diagnosing the root cause is time-consuming and tedious as testing the business layer alone has to take care of the errors and problems in the lower data layer. Other problem would be the ease of maintenance of the codes. Changes in the lower layer will force the immediate layer above it to be modified in some way due to the implicit and explicit dependencies that the upper layer has on the lower layer.
Dependency Injection (DI) pattern • Loosely coupled design. The architecture will be much more flexible and open to change • DI helps the application to interact with the different components it relies on through the component interfaces instead of the component's concrete dependencies • DI helps to test different layers. Each layer has single responsibility principle. Each layer being aware of the layer beneath it but the current layer is unaware of the layer above it
Dependency Injection Container Helps • DI is process of supplying an external dependency to a software component • Dependency Injection container returns the concrete implementations. • The container centralizes the objects creation for the dependencies and also provides the flexibility to switch among different implementations of the same interface/abstraction without having the client code knowing about it.
DI Containers • Hypothetically, a business component makes calls to a service component by instantiating an object of the callee component and it is the responsibility of the business component to take care of the whole life cycle of the instance • With DI - The business component will no longer create the instance of the callee but requests it from the container.
DI Container • The container itself knows how to orchestrate the dependent and manage its life cycle. All the boilerplate codes of handling all these are being built into the container itself and the consumer simply request the references. We are using Unity Container from Microsoft. • The types mapping registration is done in the container initialization during run time or through some form of XML file configuration during the design time. Other mean will be through some form of attribute decoration for the type member that need dependency injection. So, the container knows what and how to return the reference to the implementation instance of the requested/target type.