A model .NET web service based on Domain Driven Design Part 6: the concrete Repository continued

Introduction

In the previous post we laid the foundation for the concrete domain-specific repositories. We implemented the IUnitOfWork and IUnitOfWorkRepository interfaces and created an abstract Repository class. It’s time to see how we can implement the Customer repository. We’ll continue where we left off in the previous post.

The concrete Customer repository

Add a new folder called Repositories in the Repository.Memory data access layer. Add a new class called CustomerRepository with the following stub:

public class CustomerRepository : Repository<Customer, int, DatabaseCustomer>, ICustomerRepository
{
         public CustomerRepository(IUnitOfWork unitOfWork, IObjectContextFactory objectContextFactory) :  base(unitOfWork, objectContextFactory)
	{}

	public override Customer FindBy(int id)
	{
		throw new NotImplementedException();
	}

	public override DatabaseCustomer ConvertToDatabaseType(Customer domainType)
	{
		throw new NotImplementedException();
	}

	public IEnumerable<Customer> FindAll()
	{
		throw new NotImplementedException();
	}
}

You’ll need to add a reference to the Domain layer for this to compile.

We derive from the abstract Repository class and declare that the object is represented by the Customer class in the domain layer and by the DatabaseCustomer in the data storage layer and has an id type int. We inherit the FindBy, the ConvertToDatabaseType and the FindAll methods. FindAll() is coming indirectly from the IReadOnlyRepository interface which is implemented by IRepository which in turn is implemented by ICustomerRepository. And where are the three methods of IRepository? Remember, that the Update, Insert and Delete methods have already been implemented in the Repository class so we don’t need to worry about them. Any time we create a new domain-specific repository, those methods have been taken care of.

Let’s implement the methods one by one. In the FindBy(int id) method we’ll need to consult the DatabaseCustomers collection first and get the DatabaseCustomer object with the incoming id. Then we’ll populate the Customer domain object from its database representation. The DatabaseCustomers collection can be retrieved using the IObjectContextFactory dependency of the base class. However, its backing field is private, so let’s add the following read-only property to Repository.cs:

public IObjectContextFactory ObjectContextFactory
{
	get
	{
		return _objectContextFactory;
	}
}

The FindBy(int id) method can be implemented as follows:

public override Customer FindBy(int id)
{
	DatabaseCustomer databaseCustomer = (from dc in ObjectContextFactory.Create().DatabaseCustomers
										 where dc.Id == id
										 select dc).FirstOrDefault();
	Customer customer = new Customer()
	{
		Id = databaseCustomer.Id
		,Name = databaseCustomer.CustomerName
		,CustomerAddress = new Address()
		{
			AddressLine1 = databaseCustomer.Address
			,AddressLine2 = string.Empty
			,City = databaseCustomer.City
			,PostalCode = "N/A"
		}
	};
	return customer;
}

So we populate the Customer object based on the properties of the DatabaseCustomer object. We don’t store the postal code or address line 2 in the DB so they are not populated. In a real life scenario we’d probably need to rectify this by extending the DatabaseCustomer table, but for now we don’t care. This example shows again the advantage of having complete freedom over the database and domain representations of a domain. You have the freedom of populating the domain object from its underlying database representation. You can even consult other database objects if needed as the domain object properties may be dispersed across 2-3 or even more database tables. The domain object won’t be concerned with such details. The domain and the database are completely detached so you don’t have to worry about changing either the DB or the domain representation.

Let’s factor out the population process to a separate method as it will be needed later:

private Customer ConvertToDomain(DatabaseCustomer databaseCustomer)
{
	Customer customer = new Customer()
	{
		Id = databaseCustomer.Id
		,Name = databaseCustomer.CustomerName
		,CustomerAddress = new Address()
		{
			AddressLine1 = databaseCustomer.Address
			,AddressLine2 = string.Empty
			,City = databaseCustomer.City
			,PostalCode = "N/A"
		}
	};
	return customer;
}

The update version of FindBy(int id) looks as follows:

public override Customer FindBy(int id)
{
	DatabaseCustomer databaseCustomer = (from dc in ObjectContextFactory.Create().DatabaseCustomers
										 where dc.Id == id
										 select dc).FirstOrDefault();
	if (databaseCustomer != null)
	{
		return ConvertToDomain(databaseCustomer);
	}
	return null;
}

The ConvertToDatabaseType(Customer domainType) method will be used when inserting and modifying domain objects:

public override DatabaseCustomer ConvertToDatabaseType(Customer domainType)
{
	return new DatabaseCustomer()
	{
		Address = domainType.CustomerAddress.AddressLine1
		,City = domainType.CustomerAddress.City
		,Country = "N/A"
		,CustomerName = domainType.Name
		,Id = domainType.Id
		,Telephone = "N/A"
	};
}

Nothing fancy here I suppose.

Finally FindAll simply retrieves all customers from the database and converts each to a domain type:

public IEnumerable<Customer> FindAll()
{
	List<Customer> allCustomers = new List<Customer>();
	List<DatabaseCustomer> allDatabaseCustomers = (from dc in ObjectContextFactory.Create().DatabaseCustomers
						   select dc).ToList();
	foreach (DatabaseCustomer dc in allDatabaseCustomers)
	{
		allCustomers.Add(ConvertToDomain(dc));
	}
	return allCustomers;
}

That’s it, there’s at present nothing more to add the CustomerRepository class. If you add any specialised queries in the ICustomerRepository interface they will need to be implemented here.

I’ll finish this post with a couple of remarks on EntityFramework.

Entity Framework

There is a way to implement the Unit of Work pattern in conjunction with the EntityFramework in a different, more simplified way. The database type is completely omitted from the structure leading to the following Repository abstract class declaration:

public abstract class Repository<DomainType, IdType> : IUnitOfWorkRepository where DomainType : IAggregateRoot

So there’s no trace of how the domain is represented in the database. There is a way in the EF designer to map the columns of a table to the properties of an object. You can specify the namespace of the objects created by EF – the .edmx file – like this:

1. Remove the code generation tool from the edmx file properties:

Remove EF code generation tool

2. Change the namespace of the project by right-clicking anywhere on the EF diagram and selecting Properties:

Change namespace in entity framework

Change that value to the namespace of your domain objects.

3. If the ID of a domain must be auto-generated by the database then you’ll need to set the StoreGeneratedPattern to Identity on that field:

EF identity generation

You can fine-tune the mapping by opening the .edmx file in a text editor. It is standard XML so you can edit it as long as you know what you are doing.

This way we don’t need to declare the domain type and the database type, we can work with only one type because it will be common to EF and the domain model. It is reasonable to follow down this path as it simplifies certain things, e.g. you don’t need the conversions between DB and domain types. However, there are some things to keep in mind I believe.

We inherently couple the domain object to its database counterpart. It may work with simple domain objects, but not with more complex objects where the database representation can be spread out in different tables. We may even face a different scenario: say we made a design mistake in the database structuring phase and built a table that represents more than one domain object. We may not have the possibility of rebuilding that table as it contains millions of rows and is deployed in a production environment. How do we then map 2 or more domain objects to the same database table in the EF designer? It won’t work, at least I don’t know any way how this can be solved. Also, mapping stored procedures to domain objects or domain object rules can be problematic. What’s more, you’ll need to mark those properties of your domains virtual where you want to allow lazy loading by the ORM framework like this:

public class Book
{
    public int Id { get; set; }
    public virtual Title Title { get; set; }
}

I think this breaks the persistence ignorance (PI) feature of proper POCO classes. We’re modifying the domain to give way for a persistence technology.

However, you may be OK with these limitations. Your philosophy may well differ from my rigid PI and POCO approach. It is certainly desirable that the database tables and domains are as close as possible, but you don’t always have this luxury with large legacy databases. If you start off with a completely empty database with no tables then EF and the code-first approach – where the data tables will be created for you based on your self-written object context implementation – can simplify the repository development process. However, keep in mind that database tables are a lot more rigid and resistant to change than your loosely coupled and layered code. Once the database has been put into production and you want to change the structure of a domain object you may run into difficulties as the corresponding database table may not be modified that easily.

In the next post we’ll discuss the application services layer.

View the list of posts on Architecture and Patterns here.

Advertisement

About Andras Nemes
I'm a .NET/Java developer living and working in Stockholm, Sweden.

9 Responses to A model .NET web service based on Domain Driven Design Part 6: the concrete Repository continued

  1. codezyc says:

    Thank you for sharing this,keep going.

  2. tafs7 says:

    this is good, and slightly addresses my comment from the previous part 5 post. i still would like to hear your opinions on my question: EF Code First can rely on the mapping (Fluent API) to take your domains and convert to DbSets without an extra set of Database entities.

  3. Brandon says:

    Hi, first off nice series. Just a question on the code covered in this page. If the _objectContextFactory in the base class is private, how can it be accessed from the derived classes get accessor?

    • Andras Nemes says:

      Hello, through the public getter of the base base class:

      [sourcode language=”csharp”]
      public IObjectContextFactory ObjectContextFactory
      {
      get
      {
      return _objectContextFactory;
      }
      }
      [/sourcecode]

      //Andras

  4. raghnor says:

    Ciao Andras, thanks for this series of posts and for all the other architectural topics you’re covering in this blog. They’re inspiring me on a proposal to design a new architecture for an enterprise application I’m working on.

    Unfortunately I’m not such an experienced architect so I’m having difficulties to adapt your physics implementation (the InMemory project) to use Entity Framework context.

    Here’s my ideas. First of all I’d like to use the first version of the IUnitOfWork interface, avoiding the split between IUniiOfWork and IUnitOfWorkRepository.

    Then in the implementation project I’d implement an EF Context using the singleton pattern, together with the abstract factory pattern (as you did in your project).

    I’d create the UnitOfWork class that:
    – implements the IUoW
    – it has a constructor with the EF Context Factory parameter
    – the Register*() methods are empty (I leverage the EF Context on this part)
    – the Commit() method calls the EF Context SaveChanges() method

    I’d create then a GenericRepository class that implements the IRepository, with a constructor that takes a UoW as parameter (this would allow it to access the context in the UoF).

    Finally, for each aggregate root I’d define a specific repository that derives from the GenericRepository class.

    Your opinion on this? Thanks for any feedback you’ll be able to share with me and sorry about my far from perfect english.

    There would be other questions on this topic but they can wait 🙂

    • Andras Nemes says:

      Hi Raghnor,

      I’m not some world-renowned architect either, so don’t worry 🙂 Otherwise this model would be flawless which it clearly isn’t.
      Adapting the presented repository-related interfaces to EF can be tricky. Things to consider:

      • In retrospect I may have made a mistake in applying the singleton approach to retrieve the ObjectContext object. It is good for this in-memory repository and possibly in several other scenarios but it can create unexpected issues in ORM technologies such as EF with their complex built-in context mechanisms: the context will be the same for all repository instances and data in the context will become stale. You’d need to refresh the object context to get the latest changes in all concrete repository instances but since you’re always getting the same context from the singleton this will be difficult to achieve. I’ll try to squeeze in a post on a different implementation that’s more suitable for EF to store the object context
      • Another commenter mentioned the Fluent API to map database objects and domain objects. In the presented model the abstract Repository object allows us to define the DB and the Domain representations of the domain. If you can let EF map the domain objects to their DB counterparts then you can simplify the Repository class to only have a single representation: Repository of DomainType and IdType instead of Repository of DomainType, DatabaseType and IdType. I’m not an expert of the Fluent API so I’m not sure how well it works for complex mappings. E.g. your clean domain object might be represented across different tables in the database. Or vice versa: a single catch-all DB table can represent multiple domain objects. These situations can arise if you’d like to take on DDD but you’re working with an old and rigid database structure full of data that you cannot take out of production to make changes to it. In case your database cleanly maps to your domain objects then letting EF do the mapping for you is something to consider.
      • The above solution may have its own disadvantages: e.g. you are inherently letting a technology layer enter your domain. I’m not sure it it’s still the case with EF6 but earlier you had to mark the domain objects with the ‘virtual’ keyword to let EF populate the object properties. Also, you’ll be tied to the capabilities of SQL Server to represent an object hierarchy: superclass, derived classes, value objects, aggregate roots etc., how can DB tables handle all those? How can an automatic mapper handle all those cases? On the other hand you can argue that keeping the domain and database objects as close as possible to each other is a good idea. You may pay for this by giving more weight to a technology than normal, but it can be worth it in the long term – your approach will depend on the complexity of your domain model.
      • On the other hand if you go with the separate DbObject/Domain object representations in the Repository then you’ll have to deal with the challenge of object references. Consider the scenario of saving a DomainCustomer with EF using the model in this blog: the service calls ICustomerRepository.Add and then UoW.SaveChanges. When calling Add, the EF repo will add the DatabaseCustomer to the object context in the concrete Repo layer. Then when you call SaveChanges then the DatabaseCustomer object will be committed and will also get its ID returned from the EF context. Then back in the service layer say you’d like to read the ID of the new DomainCustomer. It will be 0 as EF is working with its own set of objects and has not magically populated the ID of the domain object. A possible solution is to follow the above single-representation model so that the EF layer and the domain layer work with the same object references. Then when you call SaveChanges EF will populate the ID of the domain object and you can extract it in the service layer. In case you’re going with the separate model representation solution then you’ll need to introduce some mechanism in the EF layer to transfer the ID of the saved database object to the domain object after calling SaveChanges.

      So that’s some food for thought as far as EF is concerned. My personal opinion is that EF and similar ORM technologies are difficult to employ with DDD. They are almost too powerful and developers easily give control to them. However, as long as you manage to keep all EF-related objects isolated within the concrete repository layer you’ll be fine.

      //Andras

  5. Pingback: Architecture and patterns | Michael's Excerpts

Leave a Reply to Andras Nemes Cancel reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

Elliot Balynn's Blog

A directory of wonderful thoughts

Software Engineering

Web development

Disparate Opinions

Various tidbits

chsakell's Blog

WEB APPLICATION DEVELOPMENT TUTORIALS WITH OPEN-SOURCE PROJECTS

Once Upon a Camayoc

Bite-size insight on Cyber Security for the not too technical.

%d bloggers like this: