Models and patterns

Download Report

Transcript Models and patterns

.NET Database
Technologies:
Data Models and
Patterns
Evolution of Data Models
Hierarchical Databases
• Data organised in a tree

a parent can have many children

a child can have only one parent
• Records described by entity types
• 1:N (one-to-many) relationships
• Query by path navigation
• Examples

File system

LDAP

Windows Registry and Active Directory

XML documents and XQuery
Network Databases
• Data organised in graph (lattice)

a parent can have many children

a child can have many parents
• Query by graph navigation
• Examples

CODASYL
Relational Databases
• Data organised as tuples in relations
• Link between data tuples

primary and foreign keys
• Relational algebra

project, select, join
• Relational normal forms
• Declarative language

data definition, consistency, manipulation and querying
• Examples

Microsoft SQL Server, Oracle, MySQL...
Relational Databases
• Relational model is very simple

only basic concepts → references need to be simulated

restricted type system → no user-defined types
• Lack of semantic modelling

complex data, versioning, roles
• Little support for data and schema evolution
• Object-relational impedance mismatch
Object-Relational Impedance Mismatch
• A set of conceptual and technical difficulties that are often
encountered when a relational database management
system is being used by a program written in an objectoriented programming language
• Object-oriented application development and relational
data management results in clash of two incompatible
models
• Code to map between models represents considerable
overhead, costly and hard to maintain
Solutions to the Impedance Mismatch
• Object-Oriented Databases

data represented as objects

object identity, references, relationships, associations

user-defined types, abstract data types, inheritance
• Object-Relational Databases

relational model extended with nested relations, references,
sets, row types, abstract types, functions

commingling of models
• Object-Relational Mapping

most widely-adopted solution due to dominance of relational
databases

overhead can be mitigated by use of frameworks such as
Entity Framework, NHibernate
Characteristics of Relational Model
• Philosophy

Efficiency, data integrity, mathematical basis (relational
algebra/calculus)
• Identity

Primary key column(s)
• Associations

Foreign Keys - enforce referential integrity

One-to-many or one-to-one

Many-to-many associations require association table
• Navigation

Associations are not directional

find related entities by JOIN expression in query
Relational Model Example
Characteristics of Object Model
• Philosophy

Rich domain model
• Identity

Each object has unique identifier

Not a property of the object
• Associations

Single object or object set references

Can model many-to-many with object set references in both
classes
• Navigation

Associations can be navigated in one or both directions
depending on references

Navigate through object graph by following references
Object Model Example
Customer
Order
-dateReceived : Date
-ordNumber
-CalcDiscPrice()
+CalcPrice()
*
1
-lastName : string
-firstName : string
-discount : float
+GetDiscount()
1
*
-orderLines
Product
-product
OrderLine
-quantity : int
+GetLinePrice()
1
1
-name : string
-productID : string
-price : decimal
+GetPrice()
Characteristics of Object Model
• Behaviour

Methods can implement business logic in object, e.g.
Validation
• Integrity and consistency

Integrity not enforced but supported by use of references

Many need to write code to maintain consistent associations

Particularly true when association is bi-directional
• Inheritance
• Interfaces
• Composition/aggregation of objects
Options for Dealing with the Mismatch
• Work in your application with objects which closely mimic
the structure of your database

ADO.NET Datasets, DataTables, etc
• Work in your application with objects and map their
properties and associations to database table columns

Object-Relational Mapping (ORM)

Can use rich domain model

Store mapped properties in database for persistence

Reconstruct domain objects from data in database

Depending on complexity of model, may need to deal with a
range of issues which arise from the mismatch
Patterns Relating to ORM
• A design pattern is a general reusable solution to a
commonly occurring problem in software design
• Gang of Four (GoF) patterns are the most famous and can
be applied in many situations
• Fowler’s Patterns of Enterprise Application Architecture
(PoEAA) includes patterns which are useful in ORM
• Patterns are not specific code solutions

General approaches to solving problems

Establish a vocabulary for describing solutions

Many variations and specific implementations may
be found for a given pattern

Fowlers illustrative examples are largely in Java but
examples in C# can be found
Patterns Relating to ORM
• The following descriptions are mainly taken from PoEAA

Brief summaries are at: http://martinfowler.com/eaaCatalog/

Full descriptions and illustrative code can be found in book
• They provide a useful summary of issues which must be
considered in implementing ORM
• Some are implemented by frameworks such as NHibernate
• Some are applicable in code which makes use of
frameworks
Domain Model
• An object model of the domain that incorporates both
behaviour and data
• At its worst business logic can be very complex
• Rules and logic describe many different cases and slants of
behaviour, and it's this complexity that objects were
designed to work with
• A Domain Model creates a web of interconnected objects,
where each object represents some meaningful individual,
whether as large as a corporation or as small as a single
line on an order form
Active Record
• An object that wraps a row in a database table or view,
encapsulates the database access, and adds domain logic
on that data
• Active Record uses the most obvious approach, putting
data access logic in the domain object
• This way all people know how to read and write their data
to and from the database
• Castle ActiveRecord and Ruby on Rails are well-known
implementations of this pattern
Data Mapper
• When you build an object model with a lot of business
logic the object schema and the relational schema often
don't match up.
• The Data Mapper is a layer of software that separates the
in-memory objects from the database.
• The in-memory objects needn't know even that there's a
database present; they need no SQL interface code, and
certainly no knowledge of the database schema
• Objects may be POCOs or may have to inherit from a
persistence base class
• NHibernate, LINQ to SQL, etc
What are POCOs?
• Plain Old CLR Objects
• POCOs are objects unencumbered with inheritance or
attributes needed for specific frameworks
• Sometimes called PONOs (Plain Old .NET Objects)
• Term derived from POJO, a term commonly used in the
Java world
Metadata Mapping
• Much of the code that deals with object-relational mapping
describes how fields in the database correspond to fields in
in-memory objects
• The resulting code tends to be tedious and repetitive to
write
• A Metadata Mapping allows developers to define the
mappings in a simple tabular form, which can then be
processed by generic code to carry out the details of
reading, inserting, and updating the data
• Metadata can be in classes, XML files, attributes or simply
naming conventions
Identity Field
• Relational databases tell one row from another by using
the primary key.
• Objects don't need such a key, as the object system
ensures the correct identity
• Reading data from a database is all very well, but in order
to write data back you need to tie the database to the inmemory object system
• Identity Field is simple - all you do is store the primary
key of the relational database table in the object's fields
Foreign Key Mapping
• Objects can refer to each other directly by object
references
• Even the simplest object-oriented system will contain a
objects connected to each other in all sorts of interesting
ways
• To save these objects to a database, it's vital to save
these references.
• Map an association between objects to a foreign key
reference between tables
Association Table Mapping
• Saves an association as a table with foreign keys to the
tables that are linked by the association
• Maps a many-to-many association in the object model to
two one-to-many associations in the database
Single-Table Inheritance
• Relational databases don't support inheritance, so when
mapping from objects to databases we have to consider
how to represent inheritance structures in relational tables
• When mapping to a relational database, we try to
minimize the joins that can quickly mount up when
processing an inheritance structure in multiple tables
• Single Table Inheritance maps all fields of all classes of an
inheritance structure into a single table
discriminator field
Class Table Inheritance
• You want database structures that map clearly to the
objects and allow links anywhere in the inheritance
structure
• Class Table Inheritance supports this by using one
database table per class in the inheritance structure
• Need to join tables to construct a single instance in
memory
Concrete Table Inheritance
• Thinking of tables from an object instance point of view, a
sensible route is to take each object in memory and map it
to a single database row
• This implies Concrete Table Inheritance, where there's a
table for each concrete class in the inheritance hierarchy
• Changes in schema may need to be replicated across
several tables
• NHibernate supports these inheritance mapping options
Repository
• A system with a complex domain model often benefits
from a layer, such as the one provided by Data Mapper
that isolates domain objects from details of the database
access code
• In such systems it can be worthwhile to build another
layer of abstraction over the mapping layer
• A Repository mediates between the domain and data
mapping layers, acting like an in-memory domain object
collection
• 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
• Can write a Repository which uses, e.g., NHibernate for
mapping
Unit of Work
• When you're pulling data in and out of a database, it's
important to keep track of what you've changed;
otherwise, that data won't be written back into the
database
• Similarly you have to insert new objects you create and
remove any objects you delete.
• You can change the database with each change to your
object model, but this can lead to lots of very small
database calls, which ends up being very slow.
• Furthermore it requires you to have a transaction open for
the whole interaction, which is impractical if you have a
business transaction that spans multiple requests
Unit of Work
• A Unit of Work keeps track of everything you do during a
business transaction that can affect the database
• When you're done, it figures out everything that needs to
be done to alter the database as a result of your work
• Examples of “ready-made” UoW:

ITransaction in Nhibernate

DataContext in LINQ to SQL

ObjectContext in EF

DataSet(!)
Identity Map
• If you aren't careful you can load the data from the same
database record into two different objects
• Can cause problems writing updates back to database
• If you load the same data more than once you're incurring
an expensive cost in remote calls
• An Identity Map keeps a record of all objects that have
been read from the database in a single transaction
• Whenever you want an object, you check the Identity Map
first to see if you already have it
• e.g. LINQ to SQL
DataContext maintains an
“identity cache”
Lazy Load
• For loading data from a database into memory it's handy
to design things so that as you load an object of interest
you also load the objects that are related to it
• No need to load all the objects he needs explicitly
• However, if you take this to its logical conclusion, you
reach the point where loading one object can have the
effect of loading a huge object graph
• A Lazy Load leaves a marker in the object structure so
that if data is needed it can be loaded only when it is used
• Can configure lazy/eager loading
in NHibernate
Lab – O/R Mapping Scenario
• Task 1. Map a given object model to a database schema
• Task 2. Implement the database and a Data Mapper class