Modeling domains with The Entity Data Model

Published: 31 Oct 2008
By: Patrik Löwendahl

Patrick Loewendahl talks about modeling domains with the Entity Data Model.

Contents [hide]

Introduction

With Visual Studio 2008 SP1, Microsoft released it long awaited-for Entity Framework and Entity Data Model. The Entity Data Model lets developers create an object oriented model of the data their applications need and Object Oriented Programming really becomes a first class citizen in the Microsoft data access technology stack.

The Entity Data Model (EDM) is a powerful modeling tool and as usual; with great power comes great responsibilities and we as developers need some initial guidelines and best practices to lead our way into this new object oriented data access modeling.

I for one look a lot to Eric Evans Domain Driven Design [Evans] and the ideas that he has put forward in how to model a domain effectively. How one can create models based on Evans’ ideas is what this article will be about. We will examine a couple Domain Driven concepts and look at how the EDM supports (or doesn’t support) them and we’ll also try to derive some EDM modeling best practices from his conclusions.

Model boundaries – the aggregate

One of the most frequently asked questions I see when I hover the forums on EDM topics is - “my model is slow when I drag my 150 tables into the designer”. For these developers I would like to share a first advice of best practices: “Avoid huge models in the first place”.

Huge models have a tough disadvantage, it’s really hard to tell where the scope of a transaction starts and ends. With interconnected relationships and lots of classes in a hierarchy, how can you be certain that you actually have set the right boundaries for the current transaction? How can you be sure that you aren’t touching more than you need?

When you create a model what you should strive for is to capture a well defined and limited concept that you know will fit into a business transaction of the case you are currently trying to solve. In modeling terms what you want is an Aggregate [Evans] with a root entity and a boundary. What I’ve found is that an EDM never should be larger than one, maybe two closely related, such aggregates to be maintainable. So instead of one huge EDM, go for several smaller ones that each capture a specific concept of your application.

Figure 1: An aggregate

An aggregate

An added benefit is that the model will be easier to grasp and you’ll be able to understand and focus on single concepts much quicker.

Figure 2: Picture of Small conceptual EDM’s in a Solution tree

Picture of 

Small conceptual EDM’s in a Solution tree

Another common mistake that I see developers do is to assume that every sub-part of a project looks at a model the same way but the fact in the matter is that most don’t. The shipping sub system of your application might use and need an Order, but more often than not it’s a slightly different Order than the same concept in the Order management part of your applications. It’s the same data, agreed, but it’s often looked upon in a different way.

The shipping subsystem might need the order address and what products that it should send, but it’s not necessarily interested in billing information or financial information. Re-using the order model in both subsystems clearly violates the “Interface Segregation Principle” that says: “Clients should not be forced to depend upon interfaces that they do not use”. (http://www.objectmentor.com/resources/articles/isp.pdf ). Evans also recognizes this and in the part “Strategic design” of his book he extensively talks about “Bounded context”.

A bounded context is a boundary for a model that applies for a certain context or concept. So when building our model we should not chase after re-use to in extreme. If a concept looks at a piece of data differently than another concept, chances are that you will be better of creating two separate models than trying to squeeze in as much of both concepts as possible into a single model.

Normalizing the model

When we work with databases we usually closely follow normalization rules that are there, amongst other reasons, to minimize structural and data duplication. When we create Object Oriented models we should try to normalize for maximum reuse as well. The current version of the EDM supports two such modeling techniques - value objects and inheritance - but unfortunately the designer doesn’t.

So to be able to get to the more advanced modeling we need to fire up the good old XML editor and write the EDM conceptual, structural and mapping files by hand.

Value objects

One way to normalize an object oriented model is to re-use classes. In the domain driven world this is called a “Value object” and in the Entity Framework it is called a “Complex type”. The idea is simple; you got a concept that doesn’t have its own ID and a concept that is shared through multiple models; a classic such example is an Address. Address should probably be handled, as a concept, in the same manner for an Order shipping address as for a Customer billing address. The basics are the same: You got a street, zip code and country; and validation is probably the same as well. So why spend time in writing several address representations? Why not just reuse the one you already got?

As mentioned, in Entity Framework you utilize this with the notion of a “Complex type”, like the following example:

Listing 1: A complex type mapping

Which results in something like:

Figure 3: Reusing a Value Type

Reusing a Value Type

What we see in figure 3 is the possibility to have one conceptual address and the reuse it in multiple aggregates. The benefit of this is that now I can reuse my validation logic for all addresses in my application.

Summary

What we’ve seen is that the conceptual model in Entity Framework really is, and should be, a separate model from the storage ditto. It enables advanced object oriented design and lets you model your application code in a way that best suites you.

About Patrik Löwendahl

Patrik works as a Mentor, Coach and Instructor at Cornerstone in Sweden. He spends his days helping teams, projects and developers excel in the .NET space with a focus on architecture, code design, and the backend bits of the .NET world like WCF, NHibernate, LINQ to *. He is a MVP, member of Microso...

View complete profile

Top Articles in this category

SqlBulkCopy in ADO.NET 2.0
SqlBulkCopy is a new feature in ADO.NET 2.0 that lets you to perform copy operation for a large amount of data between a source data store and a destination data table. In this article Keyvan introduces this new feature in .NET 2.0 and shows a sample application in action.

Managing Transactions using TransactionScope
A transaction is a unit of work. You use transactions to ensure the consistency and integrity of a database. If a transaction is successful, all of the data modifications performed during the transaction are committed and made permanent. If an error occurs during a transaction, you can roll back the transaction to undo the data modifications that occurred during the transaction.

Two-way data binding in 3-Tier web application
In this article I would like to examine two-way data-binding in 3-tier web application and how using XLib library can substantially decrease the amount of data-binding code without compromising the amount of control you have over it. I start by describing the ways data flow has been handled in 3-tier applications and how XLib improves upon it.

Mapping DataSet to XML and backwards
This article illustrates the translation to and from an ADO .NET DataSet and XML.

Bulk Operations Using Oracle Data Provider for .NET (ODP.NET)
Chinh Do describes techniques to improve application performance with bulk operations using ODP.NET.

Top
 
 
 

Please login to rate or to leave a comment.

Product Spotlight