ASP.NET N-Layered Applications - Implementing a Model (Part 4)

Note: this is part four in a series of ten. If you rather read this entire series off-line, you can buy the full series as a convenient PDF document that comes with the full source. Besides the convenience, buying the PDF will also make you feel good as it shows your appreciation for the articles and helps me pay the bills for my server and hosting so I can keep running imar.spaanjaars.com and continue to provide you with great content. For more details, check out this post that shows you how you can buy the entire series right now.

This is Part 4 in a series of 10 that show you how to build N-Layered applications using ASP.NET 4.5 and Entity Framework 5 Code First. In this part you’ll see how to build a model using POCO classes – Plain Old CLR Objects – that have no dependencies to external frameworks (such as a requirement to inherit from an Entity Framework base class). In addition, you will see how to create unit tests for your POCO classes as well as lay a foundation for validation of these classes.

If you haven’t read the earlier parts in this series yet, you’re encouraged to do so first. The following list has links to all articles in this series:

Introduction

In Part 1 of this article series you saw a brief overview of the functionality of the ContactManager application version 4.5. Most of the functionality is very similar to the design presented in the 2.0 and 3.5 versions of my N-Layered architecture articles.

Because the functionality is so similar, I’ll skip the “requirements gathering” phase. Normally, when you start a new project you don’t know up front how your application and model should look. To figure out the type of application, the underlying model and the functionality, you typically have workshops with your client to gather all the requirements. These requirements then drive the design of the application and the model, which is a representation of the objects in your domain that your application is going to work with. In the 2.0 version of this series I wrote about the requirements for the ContactManager application. You’re encouraged to check out the Design - Gathering Requirements section in the original article to find out more about the model for that application. In the new series, the model I use is pretty similar, as you’ll see in the following sections.

To learn more about how to gather requirements to design your applications and models, check out the following publications:

Based on the model from the previous article series, the application needs the following classes:

Class Name Description

Person

This class represents a contact person used to keep track of your contacts.

Address

This class represents a physical address that can be associated with a person.

EmailAddress

This class represents an e-mail address of a person.

PhoneNumber

This class represents a phone number of a person.


In addition to these classes, the model also needs the following types:

Type Name Type Description

PersonType

Enum

Defines the type of a person, such as Friend, Family or Colleague.

ContactType

Enum

Defines the type of the e-mail addresses and phone numbers, such as Business or Personal.

People
EmailAddresses
PhoneNumbers

Class

These classes are created to hold a collection of each of the main entities in the model. While you could use more generic collections such as List<T>, I prefer to create separate collections for each main type. You will see how to create these collections later.


The following diagram shows all of these types. Later sections of this article describe the various types in more detail, including their underlying code and place in the application.

Model classes in the architecture diagram
Figure 4-1 The Class Diagram for the Model project(click to enlarge)

If you look carefully at the list of types in the diagram, you’ll notice the collection class for Address is missing. The reason for this is that the current application doesn’t need it. The person class has two properties of type address called HomeAddress and WorkAddress respectively. This is a change from the original design where a contact person could have a collection of addresses as well. I’ve done this to show you the concept of Value Objects which are discussed next. Entity Framework (EF) doesn’t work well with collections of Value Objects and thus I decided to add the Address class as singular properties directly on the Person class.

Where Does the Model Fit In?

The classes defined in the Model layer flow between the concrete repositories and the user interface. The UI should preferably not know anything, or at least as little as possible about the concrete repositories and should work with the repository interfaces instead. If you think back about the architecture diagram from Part 1, the Model classes would be placed between the concrete repositories and the associated interfaces and between the repository interfaces and the UI. Figure 4-2 shows the updated diagram:

Model classes in the architecture diagram
Figure 4-2 Model Classes in the Architecture Diagram (click to enlarge)

Defining Your Types

Once you’ve identified the core types for your application, the next step is to place them in one of two groups: Entities or Value Objects, two terms that come from the Domain Driven Design language. A lot has been written about the differences between the two (see the links at the end of this section), so I won’t repeat the complete discussion here. Instead, I’ll summarize the differences and explain what the differences mean for the ContactManager application.

An Entity is an object that is identified by a unique ID, rather than by the value it represents. The canonical example is the Person class. If two Person instances have the same name, do you consider them to represent the same person? Most likely not, as the name would not uniquely identify the person, and there’s a high probability that even though these instances contain the same name they refer to two different people in the real world.

A Value Object on the other hand is identified by its properties and the values they contain. The canonical example here is Address: two instances of Address that contain the data “327 Washington Blvd Venice, California 90291” are most likely considered the same; they don’t have (or need) an identity on their own.

You can read more about the differences between Entities and Value Objects in the following articles:

To make the distinction in your code between these two types, it’s a good idea to create two base classes that your entities can inherit from. You see how to do this next.

Creating the Infrastructure

In this section you see how to implement the Infrastructure project by creating two base classes: one for an Entity and one for a Value Object.

Note: I’ll show the implementation of a number of types step by step. That means that the code you see may not be the final code in the project.

Creating Base Classes for Entities and Value Types

A base class for an Entity requires at least an identity property which is typically called Id, although, you’re free to make up another name. Since the base class should be reusable across multiple type definitions, it’s a good idea to make the type of this Id column generic so that classes that inherit this base class can determine the actual type (for example, an int or a Guid). The class could also have an IsTransient method that determines if the object is new (has not been assigned an ID by the underlying database) or not. To implement this base class, I added a new class file to the Spaanjaars.Infrastructure project, called it DomainEntity.cs and added the following code:

namespace Spaanjaars.Infrastructure
{
  public abstract class DomainEntity<T>
  {
    /// <summary> 
    /// Gets or sets the unique ID of the entity in the underlying data store. 
    /// </summary> 
    public T Id { get; set; }

    /// <summary> 
    /// Checks if the current domain entity has an identity. 
    /// </summary> 
    /// <returns>True if the domain entity is transient (i.e. has no identity yet),
    /// false otherwise.
    /// </returns> 
    public bool IsTransient()
    {
      return Id.Equals(default(T));
    }
  }
}

Here’s the class diagram for the complete base class from the sample project. I’ll discuss the members for comparison and validation later.

The DomainEntity<T> class
Figure 4-3 The DomainEntity<T> class

With the base class defined, I can now modify the Person class so it inherits DomainEntity and sets the type of Id to an int. To implement that change, I modified Person in the Model project as follows:

using Spaanjaars.Infrastructure;
namespace Spaanjaars.ContactManager45.Model
{
  public class Person : DomainEntity<int>
  {
  }
}

Notice how I used DomainEntity<int> to define the type of the Id property as an int. I also removed the Id property from the Person class as it now inherits that from the DomainEntity base class.

With the Person class done, I could now modify the NewPersonHasEmptyId test method so it now uses the IsTransient method instead of checking for a hard-coded value of zero:

[TestMethod]
public void NewPersonHasEmptyId()
{
  var person = new Person();
  person.IsTransient().Should().BeTrue();
}

In the sample project that comes with this article series you’ll also see implementation code for validation inside the DomainEntity<T> class. This is discussed later in the series.

Implementing a ValueObject base class is simpler as it doesn’t require an identity. I added the following class – called ValueObject – to the Spaanjaars.Infrastructure project:

public abstract class ValueObject<T> where T : ValueObject<T>
{
}

Note the constraint on this type using the where clause. Although it seems to state the obvious, or even may cause a circular reference, this code makes sure that a class that inherits ValueObject<T> can only pass itself for the T parameter. In other words, the following is valid:

public class Address : ValueObject<Address> 

because the Address type passed for the T parameter does inherit ValueObject<Address>.

The following is invalid because int does not inherit ValueObject<int>:

public class Address : ValueObject<int>

Here’s how the complete ValueObject class looks like:

The ValueObject<T> class
Figure 4-4 The ValueObject<T> class

I’ll explain the other members of this class in this and later parts in the series when I discuss modifying these classes to implement equality comparison and validation.

Adding Properties to the Person Class

With the base class done, it’s time to add a few basic properties to the Person class such as a name, a type and date of birth. Later in this article I’ll modify Person once more when I add properties for the various contact details.

Before I show you the new Person class, first take a look at the two enumerations that I introduced in the beginning of this article to define the type of a person and of a contact record. I added two new enums to a new Enums folder inside the Model project and completed them with the following code:

namespace Spaanjaars.ContactManager45.Model
{
 /// <summary> 
 /// Determines the type of a contact person. 
 /// </summary> 
 public enum PersonType 
 {
   /// <summary> 
   /// Indicates an unidentified value. 
   /// </summary> 
   None = 0,

   /// <summary> 
   /// Indicates a friend. 
   /// </summary> 
   Friend = 1,

    /// <summary> 
   /// Indicates a family member. 
   /// </summary> 
   Family = 2,

    /// <summary> 
   /// Indicates a coworker. 
   /// </summary> 
   Colleague = 3
 }
}

namespace Spaanjaars.ContactManager45.Model
{
 /// <summary> 
 /// Determines the type of a contact record. 
 /// </summary> 
 public enum ContactType 
 {
   /// <summary> 
   /// Indicates an unidentified value. 
   /// </summary> 
   None = 0,

    /// <summary> 
   /// Indicates a business contact record. 
   /// </summary> 
   Business = 1,

    /// <summary> 
   /// Indicates a personal contact record. 
   /// </summary> 
   Personal = 2
 }
}

Enum support for Entity Framework Code First has been added in version 5. It’s a very useful (and much needed) addition to the framework, as using enums is quite common. The cool thing about enums in EF is that it “just works.” You don’t have to define any special behaviors for your enums to roundtrip to the database correctly.

With the enums done, I completed the Person class as follows:

using System;
using Spaanjaars.Infrastructure;

namespace Spaanjaars.ContactManager45.Model
{
  public class Person : DomainEntity<int>
  {
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public PersonType Type { get; set; }
  }
}

Here's how its Class Diagram looks:

The Person class
Figure 4-5 The Person Class

NOTE: throughout the model classes you’ll find attributes on properties like this:

[Required]
public string FirstName { get; set; } 

This marks the first name of a person as being required. These attributes are supported by EF, but it also has an alternative available in the form of the Fluent API that enables you to configure your business rules like a required field, a maximum length and so on, at the DbContext level rather than at the entity level. This way you can centralize your business rules and keep the entity classes really clean. This is just a preference though; many of the validation rules set by the API can just as well be applied using data annotation attributes such as the Required attribute. Since the Fluent API requires a DbContext, you need to create one first. The sections “Building the Object Context” and “Configuring your model’s business rules” in Part 5 will have more details. I typically apply low level attributes like Required at the class level, and define database specific information (such as the length of a field) in the configuration of EF.

Notice how the name of the person consists of a first name and a last name. In many places in the application the full name of the user is displayed, so it makes sense to make a (read-only) property for that. Before I implemented the property, I first wrote the following unit tests in the PersonTests class in the Unit Tests project:

[TestMethod]
public void FirstAndLastNameResultsInFullName()
{
  var person = new Person() { FirstName= "Imar", LastName= "Spaanjaars" };
  person.FullName.Should().Be("Imar Spaanjaars");
}

[TestMethod]
public void EmptyFirstNameReturnsLastName()
{
  var person = new Person() { LastName = "Spaanjaars" };
  person.FullName.Should().Be("Spaanjaars");
}

[TestMethod]
public void EmptyLastNameReturnsFirstName()
{
  var person = new Person() { FirstName = "Imar" };
  person.FullName.Should().Be("Imar");
}

[TestMethod]
public void AllEmptyReturnsEmpty()
{
  var person = new Person();
  person.FullName.Should().Be(string.Empty);
} 

I did not write all tests before I added the FullName property. I initially wrote the first test, and then used my refactoring tool to implement the FullName property and have it throw a NotImplementedException. I then completed all the other tests and implemented the property. Finally, I ran all tests to make sure they ran successfully. I needed a few refactoring steps before the code was working as expected.

In your own projects, the order of tests and implementation may vary from topic to topic. I am not a strict test driven developer and sometimes write the implementation first, followed by a bunch of tests to validate my code works correctly. However, it can often be very beneficial to write tests before you write implementation, so you can focus on the What (the public API of your code) rather than on the How (the actual implementation).

These tests ensure that the FullName property returns logical data, even if one of the fields (or both) is missing. Since a completely empty name doesn’t make a lot of sense, you’ll want to make one of these (or both) a required field. You’ll see later how it is done in Part 5 of this series.

With the unit tests done, I implemented the property as follows:

public string FullName
{
  get 
  {
    string temp = FirstName ?? string.Empty;
    if (!string.IsNullOrEmpty(LastName))
    {
      if (temp.Length > 0)
      {
        temp += " ";
      }
      temp += LastName;
    }
    return temp;
  }
}

Since this is a read-only property, EF will ignore it and it won’t be persisted in the database.
With the basics of the Person class done, the next step is to add classes for the contact detail records. Once those are done, I’ll revisit the Person class again and add properties for addresses, phone numbers and e-mail addresses.

Adding the Contact Detail Classes

As you saw earlier in this article, the Person class has a few properties that contain contact information. For the contact data, the project needs the following three classes:

  • Address
  • PhoneNumber
  • EmailAddress

For this article series, I implemented Address as a ValueObject and the other two as entities. You could argue that PhoneNumber and EmailAddress are great candidates for Value Objects and I would fully agree. However, I want to implement these types as collections (so you can have multiple instances of each attached to a contact person). To implement this one to many relationship in EF, the other end (i.e. the PhoneNumber and the EmailAddress) needs to have its own identity (e.g. an Id property). That conflicts with the absence of an identity in a ValueObject, and as such PhoneNumber and EmailAddress are implemented as entities. For these three classes, the sample project contains the following code:

// PhoneNumber
using Spaanjaars.Infrastructure;

namespace Spaanjaars.ContactManager45.Model
{
  public class PhoneNumber : DomainEntity<int>
  {
    [Required]
    public string Number { get; set; }
    public ContactType Type { get; set; }
    public Person Owner { get; set; }
    public int OwnerId { get; set; }
  }
}

// EmailAddress
using Spaanjaars.Infrastructure;

namespace Spaanjaars.ContactManager45.Model
{
  public class EmailAddress : DomainEntity<int>
  {
    [Required]
    [EmailAddressAttribute]
    public string EmailAddressText { get; set; }
    public ContactType Type { get; set; }
    public Person Owner { get; set; }
    public int OwnerId { get; set; }
  }
}

// Address
using Spaanjaars.Infrastructure;

namespace Spaanjaars.ContactManager45.Model
{
  public class Address : ValueObject<Address>, IValidatableObject 
  {
    private Address() { }

    public Address(string street, string city, string zipCode, 
                    string country, ContactType contactType)
    {
      Street = street;
      City = city;
      ZipCode = zipCode;
      Country = country;
      ContactType = contactType;
    }

    public string Street { get; private set; }
    public string ZipCode { get; private set; }
    public string City { get; private set; }
    public string Country { get; private set; }
    public ContactType { get; private set; }

    public bool IsNull
    {
      get 
      {
        return (string.IsNullOrEmpty(Street) && string.IsNullOrEmpty(ZipCode) 
                && string.IsNullOrEmpty(City) && string.IsNullOrEmpty(Country));
      }
    }
  }
}

EmailAddress and PhoneNumber participate in a one to many relationship: one Person can have zero to many instances of type EmailAddress and PhoneNumber. To create the relationship, I added the Owner property to these two classes. This way you can assign a person to these classes and link back to the Person from an EmailAddress or PhoneNumber. Besides the Owner property, I also added an OwnerId property of type int. EF supports "foreign key properties" which let you assign one entity to another simply by using its ID. So for example, rather than doing this:

var emailAddress = new EmailAddress { ... };
emailAddress.Owner = _personRepository.FindById(123); 

you can assign the ID directly like this:

var emailAddress = new EmailAddress { ... };
emailAddress.OwnerId = 123; 

This could save you from an additional call to the database when you only have the person's ID available (for example, when creating a new EmailAddress in a Web Form where the ID of the person is passed in the query string).

Obviously, you can still assign the Owner property a value if you happen to have a valid instance of Person.

The class diagram for the three classes with contact details looks as follows:

The Address, EmailAddress and PhoneNumber Classes
Figure 4-6 The Address, EmailAddress and PhoneNumber classes

Note: The IHasOwner interface and Validate methods are discussed later in this article.

EmailAddress and PhoneNumber inherit DomainEntity<int> which gives them an Id property of type int. Address inherits ValueObject<Address> which makes it a value object. For value objects, it’s a good practice to make them immutable. That means that once you’ve created an instance of an object and filled it with data through the constructor, you shouldn’t be able to change it anymore. This is easily accomplished with a constructor that has parameters for all properties of the class, like this:

public Address(string street, string city, string zipCode, 
                 string country, ContactType contactType)
{
  Street = street;
  City = city;
  ZipCode = zipCode;
  Country = country;
  ContactType = contactType;
}

In addition, the setters of the properties have been marked private so they are only accessible from within the class:

public string Street { get; private set; } 

And finally, in order for the Entity Framework to create instances of Address, it needs a parameterless constructor. This breaks the POCO requirements somewhat as you must implement this constructor to support EF. However, the constructor can be made private, so it’s not accessible by regular external code.

private Address() { }

Personally, I am fine with this requirement as I feel it doesn’t break my model design.

Dealing with Collections

When dealing with collections and Entity Framework, there’s something to be aware off. When you add entities to a collection that is tracked by Entity Framework (for example, because the parent of the collection has been added to the context) they are automatically added to the context and thus to the database. Consider this example:

var person = new Person();
person.EmailAddresses.Add(new EmailAddress { EmailAddressText = "imar@spaanjaars.com" });
myContext.People.Add(person);
myContext.SaveChanges();

When this code executes, EF inserts two new records: one in the Person table and one in the EmailAddresses table. The row in the EmailAddresses table will have a foreign key pointing to the Person table (if this is all new to you, don’t worry yet; I’ll dig deeper into this in Part 5).
However, if you try to remove an EmailAddress, things work a bit differently. Consider this code:

var person = myContext.People.First(x => x.Id = id);
person.EmailAddresses.Clear();
myContext.SaveChanges();

This code retrieves an existing person, clears the EmailAddresses collection and then saves the changes. What you might expect to happen is that the e-mail addresses that were previously assigned to the person are actually deleted from the database. This is, however, not the case. The only thing that happens is that EF clears the foreign key that points to the person. In other words, the e-mail address itself is not deleted from the database; it just no longer points to the Person row.

If you Google for this problem you find many solutions that show you how to mark the EmailAddress objects as deleted by setting their EntityState property to Deleted. However, as you’ll see later, you won’t have direct access to the EF data context from the locations where you’re removing e-mail addresses from the Person’s EmailAddresses collection. This is, however, relatively easy to fix in the DbContext itself as you’ll see in Part 5. In order for the DbContext to understand which objects it should remove, you can let these entities implement a custom interface that you can detect in the DbContext and take the appropriate action. Again, Part 5 shows how to implement the code in the DbContext so for now I’ll just show you the interface that the removable objects implement:

public interface IHasOwner 
{
  /// <summary> 
  /// The Person instance this object belongs to. 
  /// </summary> 
  Person Owner { get; set; }
} 
EmailAddress and PhoneNumber then implement this interface:
public class EmailAddress : DomainEntity<int>, IHasOwner 
{
}

public class PhoneNumber : DomainEntity<int>, IHasOwner 
{
}

The interface is implemented by the Owner property (shown earlier) in each of the two classes. You’ll see this interface again in Part 5.

If you look in the sample code that comes with this article series, you’ll notice that these classes contain more code. Most of that code is related to validation, which is discussed in Part 5.

With the classes added to the project, I could write a few simple unit tests that demonstrate I can instantiate these classes and set their properties. However, most of that would come down to testing the .NET framework (do property getters and setters work for example) rather than testing my own code. I’ll write unit and integration tests for these classes later to test concepts like validation, which should implicitly cover instantiating and using these objects. Therefore, I am not adding any more tests for now.

Implementing Equality Comparison

When working with a model, you’re going to need the ability to compare two instances of a class in your model with each other. You could have an instance of a Person that you want to compare with an existing instance that is being submitted to your application using a WCF service for example. Or you may want to see if a person’s personal address is the same has her business address.

The default implementation for comparison of classes in .NET is to use reference equality; in other words, .NET checks if two references are pointing to the same object. Consider this example (which you find in the PersonTests class inside the Unit Tests project):

[TestMethod]
public void TwoPeopleWithSameIdAreTheSame()
{
  var person1 = new Person { Id = 1, FirstName = "Imar", LastName = "Spaanjaars" };
  var person2 = new Person { Id = 1, FirstName = "Imar", LastName = "Spaanjaars" };
  (person1 == person2).Should().BeTrue();
}

When you run this test now, it fails. The variables person1 and person2 are referring to two different instances of Person. This means that the equality check (==) returns false.

However, it would make perfect sense if the check returned true since Person is an Entity whose identity and uniqueness is defined by the Id property. Both Person instances have the same ID, so from an application perspective, they should be considered the same.

In contrast, two Addresses (implemented as Value Types) should be considered the same when the values for all of their properties match. Consider this test (that I added to the AddressTests class inside the Unit Tests project):

[TestMethod]
public void TwoIdenticalAddressesShouldBeTheSame()
{
  var address1 = new Address("Street", "City", "ZipCode", "Country", ContactType.Business);
  var address2 = new Address("Street", "City", "ZipCode", "Country", ContactType.Business);
    (address1 == address2).Should().BeTrue();
}

Again, when you run this test it would fail. The variables address1 and address2 each refer to a different instance. The default of the == operator for objects is to check reference equality, and so these two objects are not considered the same.

To fix these issues, and have .NET consider your entities to be the same if they have the same ID and consider your Value Objects to be the same when all of their properties match, you need to override Equals and the equality and inequality operators (== and !=).

For both implementations, I borrowed code from the Domain Oriented N-Layered .NET 4.0 Sample App (formerly at http://microsoftnlayerapp.codeplex.com/ but now unpublished as Microsoft considers the application as outdated; you can read more about it here.), a sample application and reference guide for implementing N-Layered applications in .NET. While there is some overlap between this guide and mine, you’ll find the Microsoft version is more complex and extensive, and much more geared towards large enterprise-scale applications.

Their sample application contains an implementation to compare Value Objects that uses reflection if necessary. Implementing their code into my ValueObject<T> class results in the following code:

public abstract class ValueObject<T> : 
               IEquatable<T> where T : ValueObject<T>, IValidatableObject 
{
  public abstract IEnumerable<ValidationResult> Validate(
               ValidationContext validationContext);

  public IEnumerable<ValidationResult> Validate()
  {
    var validationErrors = new List<ValidationResult>();
    var ctx = new ValidationContext(this, null, null);
    Validator.TryValidateObject(this, ctx, validationErrors, true);
    return validationErrors;
  }

  private bool CheckValue(PropertyInfo p, T other)
  {
    var left = p.GetValue(this, null);
    var right = p.GetValue(other, null);
    if (left == null || right == null)
    {
      return false;
    }

    if (typeof(T).IsAssignableFrom(left.GetType()))
    {
      return ReferenceEquals(left, right);
    }
    return left.Equals(right);
  }

  public bool Equals(T other)
  {
    if ((object)other == null)
    {
      return false;
    }

    if (ReferenceEquals(this, other))
    {
      return true;
    }

    //compare all public properties 
    PropertyInfo[] publicProperties = GetType().GetProperties();

    if (publicProperties.Any())
    {
      return publicProperties.All(p => CheckValue(p, other));
    }
    return true;
  }

  public override bool Equals(object obj)
  {
    if ((object)obj == null)
    {
      return false;
    }

    if (ReferenceEquals(this, obj))
    {
      return true;

    }
    var item = obj as ValueObject<T>;

    if ((object)item != null)
    {
      return Equals((T)item);
    }
    return false;
  }

  public override int GetHashCode()
  {
    int hashCode = 31;
    bool changeMultiplier = false;
    int index = 1;

    PropertyInfo[] publicProperties = this.GetType().GetProperties();

    if (publicProperties.Any())
    {
      foreach (var item in publicProperties)
      {
        object value = item.GetValue(this, null);

        if ((object)value != null)
        {
          hashCode = hashCode * ((changeMultiplier) ? 59 : 114) + value.GetHashCode();
          changeMultiplier = !changeMultiplier;
        }
        else 
        {
          hashCode = hashCode ^ (index * 13);
                       //only for support {"a",null,null,"a"} <> {null,"a","a",null} 
        }
      }
    }
    return hashCode;
  }

  public static bool operator ==(ValueObject<T> left, ValueObject<T> right)
  {
    if (Equals(left, null))
    {
      return (Equals(right, null)) ? true : false;
    }
    return left.Equals(right);
  }

  public static bool operator !=(ValueObject<T> left, ValueObject<T> right)
  {
    return !(left == right);
  }
}

This code contains a version of Equals that checks if the value compared against is null. If it’s not, it then checks if both sides are referring to the same instance, and if that’s not the case, it uses reflection to compare each individual property. It also overrides the == (equals) and != (not equals) operators by calling the Equals method. Finally, it overrides GetHashCode to generate a value for the object used in hash tables, again using reflection.

If you don’t like the reflection implementation, you can always override Equals (object obj) in the Address class (or any other class that inherits ValueObject) and compare its properties directly.

The DomainEntity base class requires a slightly different approach: it only needs to compare the IDs of the two objects, taking nullability and a transient state into account as well. Here’s the full implementation of that class:

public abstract class DomainEntity<T> : IValidatableObject 
{
  public T Id { get; set; }

  public bool IsTransient()
  {
    return Id.Equals(default(T));
  }

  public override bool Equals(object obj)
  {
    if (obj == null || !(obj is DomainEntity<T>))
    {
      return false;
    }

    if (GetType() != obj.GetType())
    {
      return false;
    }

    if (ReferenceEquals(this, obj))
    {
      return true;
    }

    var item = (DomainEntity<T>)obj;

    if (item.IsTransient() || IsTransient())
    {
      return false;
    }
    return item.Id.Equals(Id);
  }

  public override int GetHashCode()
  {
    if (!IsTransient())
    {
      return Id.GetHashCode() ^ 31; 
    }
    return base.GetHashCode();
  }

  public static bool operator ==(DomainEntity<T> left, DomainEntity<T> right)
  {
    if (Equals(left, null))
      return (Equals(right, null)) ? true : false;
    else 
      return left.Equals(right);
  }

  public static bool operator !=(DomainEntity<T> left, DomainEntity<T> right)
  {
    return !(left == right);
  }

  public abstract IEnumerable<ValidationResult> Validate(
                          ValidationContext validationContext);

  public IEnumerable<ValidationResult> Validate()
  {
    var validationErrors = new List<ValidationResult>();
    var ctx = new ValidationContext(this, null, null);
    Validator.TryValidateObject(this, ctx, validationErrors, true);
    return validationErrors;
  }
}

Again, Equals checks if the other side is null or not a DomainObject<T> (in which case they should never be considered the same). It also checks if the two references are not actually the same instance. If that’s not the case, the code checks if one of the objects (or both) is in a transient state:

if (item.IsTransient() || IsTransient())
{
  return false;
}

If one of them (or both) is transient, the code assumes they are not equal. This is necessary when creating new objects. Without that check, all new objects that haven’t saved in the database would be considered equal which of course is not correct.

If none of the conditions above are met, the code checks the Id property of both objects. If they are the same, the objects are considered equal. Otherwise they are considered to be different.

The following set of Unit Tests demonstrate the behavior of this implementation. These are just a few samples to show the general concept; the code that comes with this article has other tests to cover additional scenarios.

The following piece of code shows some of the tests for the DomainEntity classes:

[TestClass]
public class DomainEntityTests 
{
  #region Nested helper classes

  internal class PersonWithIntAsId : DomainEntity<int>
  { }

  internal class PersonWithGuidAsId : DomainEntity<Guid>
  { }

  #endregion 

  [TestMethod]
  public void TransientLeftIsNotEqual()
  {
    var personLeft = new PersonWithIntAsId();
    var personRight = new PersonWithIntAsId { Id = 1 };
    personLeft.Equals(personRight).Should().BeFalse();
  }

  [TestMethod]
  public void TwoTransientsAreNotEqual()
  {
    var personLeft = new PersonWithIntAsId();
    var personRight = new PersonWithIntAsId();
    personLeft.Equals(personRight).Should().BeFalse();
  }

  [TestMethod]
  public void NewPersonWithIntAsIdIsTransient()
  {
    var person = new PersonWithIntAsId();
    person.IsTransient().Should().BeTrue();
  }

  [TestMethod]
  public void PersonWithIntAsIdWithValueIsNotTransient()
  {
    var person = new PersonWithIntAsId { Id = 4 };
    person.IsTransient().Should().BeFalse();
  }

  [TestMethod]
  public void NewPersonWithGuidAsIdIsTransient()
  {
    var person = new PersonWithGuidAsId();
    person.IsTransient().Should().BeTrue();
  }

  [TestMethod]
  public void PersonWithGuidAsIdWithValueIsNotTransient()
  {
    var person = new PersonWithGuidAsId { Id = Guid.NewGuid() };
    person.IsTransient().Should().BeFalse();
  }

  [TestMethod()]
  public void EntitiesWithSameIdentityShouldBeEqual()
  {
    var entityLeft = new PersonWithIntAsId { Id = 1 };
    var entityRight = new PersonWithIntAsId { Id = 1 };

    bool resultOnEquals = entityLeft.Equals(entityRight);
    bool resultOnOperator = entityLeft == entityRight;

    resultOnEquals.Should().BeTrue();
    resultOnOperator.Should().BeTrue();
  }
}

Similarly, I have tests for the ValueObject class. In the examples below, I use the Address class (that inherits ValueObject) but in the code download you find a few other tests as well.

[TestClass]
public class AddressTests 
{
  [TestMethod]
  public void TwoIdenticalAddressesShouldBeTheSame()
  {
    var address1 = new Address("Street", "City", "ZipCode", "Country", ContactType.Business);
    var address2 = new Address("Street", "City", "ZipCode", "Country", ContactType.Business);
   (address1 == address2).Should().BeTrue();
  }

  [TestMethod]
  public void DifferentAddressesShouldNotBeTheSame()
  {
    var address1 = new Address("Some other street", "City", "ZipCode", "Country", 
                      ContactType.Business);
    var address2 = new Address("Street", "City", "ZipCode", "Country", ContactType.Business);
   (address1 != address2).Should().BeTrue();
  }

  [TestMethod]
  public void InstanceOfValueObjectDoesNotEqualNull()
  {
    var address1 = new Address();
    address1.Equals(null).Should().BeFalse();
  }

  [TestMethod]
  public void ReferenceEqualsIsEqual()
  {
    var address1 = new Address("Street", "City", "ZipCode", "Country", ContactType.Business);
    Address address2 = address1;
    address1.Equals(address2).Should().BeTrue();
  }
}

With the tests added to the Unit Test project, the next step is modelling collections.

Creating Collections

When modelling collections, you have a few different options. For example, it’s quite common to use a List<T> class to store collections of objects. Using that class, you could give Person access to a collection of EmailAddress instances like this:

public class Person : DomainEntity<int>
{
  public string FirstName { get; set; }

  // Other properties here

  public List<EmailAddress> EmailAddresses { get; set; }
}

You can then add instances of EmailAddress to the EmailAddresses collection like this:

var person = new Person();
person.EmailAddresses.Add(new EmailAddress {ContactType = ContactType.Business, 
               EmailAddressText = "someone@example.com"});

While this works great, it’s generally not recommended to expose List<T> in the public API of a class. List<T> is designed for performance, and not meant for inheritance. This means you can’t override any of its members that change the way the class behaves when it comes to adding, finding and removing members. This makes it impossible to add specialized behavior to your collection; something you often want to do. More information about this guideline can be found here:http://msdn.microsoft.com/en-us/library/ms182142%28v=vs.110%29.aspx

It is recommended that you implement a class that inherits Collection<T> instead, which is what I have done in the sample project. The downside of inheriting that class is that you miss out on some of the useful functionality that List<T> has. For example, Collection<T> does not have a method to sort the data, or to quickly add a range. However, that behavior is easy to add to a base class, so the other collections in your project can get it for free. In the Spaanjaars.ContactManager application, I have added the following CollectionBase<T> class:

public abstract class CollectionBase<T> : Collection<T>, IList<T>
{
  protected CollectionBase() : base(new List<T>()) { }

  protected CollectionBase(IList<T> initialList) : base(initialList) { }

  protected CollectionBase(CollectionBase<T> initialList) : base(initialList) { }

  public void Sort(IComparer<T> comparer)
  {
    var list = Items as List<T>;
    if (list != null)
    {
      list.Sort(comparer);
    }
  }

  public void Sort()
  {
    var list = Items as List<T>;
    if (list != null)
    {
      list.Sort();
    }
  }

  public void AddRange(IEnumerable<T> collection)
  {
    if (collection == null)
    {
      throw new ArgumentNullException("collection", "Parameter collection is null.");
    }
    foreach (var item in collection)
    {
      Add(item);
    }
  }
}

The class is marked as abstract which means you can’t create instances of it directly. Its sole purpose is to serve as a base class for other collections. It inherits Collection<T> as per the recommendation which gives it virtual members such as InsertItem, RemoveItem, SetItem and ClearItems. Notice that Collection<T> implements the IList<T> interface so you can pass instances of classes that inherit Collection<T> to any member that expects an IList<T>.

The class has three constructors that all call the base constructor with an initial list. Notice how the default constructor calls the base constructor with a new instance of List<T>:

protected CollectionBase()
  : base(new List<T>())
{ }

Although you shouldn’t expose members of List<T> in your public API, it’s perfectly OK to use one internally.

Besides the constructors, the class exposes two methods to sort the underlying data and a method to add ranges of instances with a single call:

public void Sort(IComparer<T> comparer)
{
  var list = Items as List<T>;
  if (list != null)
  {
    list.Sort(comparer);
  }
}

public void Sort()
{
  var list = Items as List<T>;
  if (list != null)
  {
    list.Sort();
  }
}

public void AddRange(IEnumerable<T> collection)
{
  if (collection == null)
  {
    throw new ArgumentNullException("collection", "Parameter collection is null.");
  }
  foreach (var item in collection)
  {
    Add(item);
  }
}

This base class is used by all collections in the project: for People, EmailAddresses, and PhoneNumbers. Here’s an example of the EmailAddresses collection:

namespace Spaanjaars.ContactManager45.Model.Collections
{
  public class EmailAddresses : CollectionBase<EmailAddress>
  {
    public EmailAddresses() { }

    public EmailAddresses(IList<EmailAddress> initialList)
      : base(initialList)
    { }

    public EmailAddresses(CollectionBase<EmailAddress> initialList)
      : base(initialList)
    { }
  }
}

With this class in the project, the Person class can now be rewritten like this:

public class Person : DomainEntity<int>
{
  public Person()
  {
    EmailAddresses = new EmailAddresses();
  } 

  public string FirstName { get; set; }

  // Other properties here

  public EmailAddresses EmailAddresses { get; set; }
}

Notice how the code for the property now refers to EmailAddresses twice: the first reference is the collection’s type, the second one the name of the property. I also instantiate a new instance of this class in the Person's constructor so it's ready for use.

Adding instances of EmailAddress remains the same:

var person = new Person();
person.EmailAddresses.Add(new EmailAddress {ContactType = ContactType.Business, 
           EmailAddressText = "someone@example.com"});

What I like about this setup is that it’s now very easy to add specialized behavior to these collections. Rather than forcing users of your API to manually construct and initialize an EmailAddress, you could add a convenience method for Add on the EmailAddresses collection like this:

public void Add(string emailAddressText, ContactType contactType)
{
  Add(new EmailAddress { ContactType = contactType, EmailAddressText = emailAddressText });
}

Adding an e-mail address can now be as simple as this:

Person person = new Person();
person.EmailAddresses.Add("imar@spaanjaars.com", ContactType.Business);

Once I added the collection classes to the project, I was able to write tests like the following to verify the behavior of the AddRange and Sort methods:

using System;
using System.Collections.Generic;
using System.Linq;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Spaanjaars.ContactManager45.Model;
using Spaanjaars.ContactManager45.Model.Collections;

namespace Spaanjaars.ContactManager45.Tests.Unit
{
  [TestClass]
  public class CollectionBaseTests 
  {
    [TestMethod]
    public void NewCollectionUsingNewListsAddsValues()
    {
      var collection = new IntCollection(new List<int> { 1, 2, 3 });
      collection.Count.Should().Be(3);
    }

    [TestMethod]
    public void NewCollectionUsingExistingCollectionAddsValues()
    {
      var collection1 = new IntCollection(new List<int> { 1, 2, 3 });
      var collection2 = new IntCollection(collection1);
      collection2.Count.Should().Be(3);
    }

    [TestMethod]
    public void UsingAddRangeAddsValues()
    {
      var collection1 = new IntCollection(new List<int> { 1, 2, 3 });
      var collection2 = new IntCollection();
      collection2.AddRange(collection1);
      collection2.Count.Should().Be(3);
    }

    [TestMethod]
    public void SortPeopleWithSpecifiedComparerSortsCorrectly()
    {
      var people = new People();
      people.Add(new Person { FirstName = "John", LastName = "Doe" });
      people.Add(new Person { FirstName = "Imar", LastName = "Spaanjaars" });
      people.Add(new Person { FirstName = "Jane", LastName = "Doe" });

      people.Sort(new PersonComparer());

      people[0].FullName.Should().Be("Imar Spaanjaars");
      people[1].FullName.Should().Be("Jane Doe");
      people[2].FullName.Should().Be("John Doe");
    }

    [TestMethod]
    public void SortIntsSorts()
    {
      var ints = new IntCollection { 3, 2, 1 };
      ints.Sort();
      ints[0].Should().Be(1);
      ints[1].Should().Be(2);
      ints[2].Should().Be(3);
    }
  }

  internal class IntCollection : CollectionBase<int>
  {
    public IntCollection()
    { }

    public IntCollection(IList<int> initialList)
      : base(initialList)
    { }

    public IntCollection(CollectionBase<int> initialList)
      : base(initialList)
    { }
  }

  public class PersonComparer : IComparer<Person>
  {
    public int Compare(Person x, Person y)
    {
      return x.FullName.CompareTo(y.FullName);
    }
  }
}

Most of this is pretty straight forward, and by looking at the test name and implementation you should be able to see what the code is testing. I added a helper class called IntCollection to test the Sort behavior for classes that implement IComparable (which makes it possible to sort a collection of a type without specifying a special Comparer classes).

The thing that may be new to you is the PersonComparer, a class dedicated to defining how instances of Person should be sorted. In this implementation, they are sorted on their FullName property, but you could of course change that if you want by changing the implementation of the Compare method or by implementing a completely different Comparer class altogether. Using this implementation of PersonComparer, you can sort a collection of people like this:

var people = new People();
people.Add(new Person { FirstName = "John", LastName = "Doe" });
people.Add(new Person { FirstName = "Imar", LastName = "Spaanjaars" });
people.Add(new Person { FirstName = "Jane", LastName = "Doe" });
people.Sort(new PersonComparer());

After this code has run, the collection now contains the people ordered by their full name, which means my name is listed first, followed by Jane and Joe.

The final thing I like to implement in my model is the ability to automatically keep track of the date and time objects were created and modified. You’ll see how I implemented this in the model next, while the article on building an Entity Framework repository shows how to automatically update these dates and save them in the database.

Automatic Tracking of Creation and Modification Dates

It’s common that you want to keep track of the date and time an object was created and last modified. To this end, you could add two DateTime properties to each class that you want to track like this:

public class Person : DomainEntity<int>
{
  // Other properties here. 
  public DateTime DateCreated { get; set; }
  public DateTime DateModified { get; set; }
}

Then whenever you create a new instance of Person, you can fill in the DateCreated using a constructor:

public class Person : DomainEntity<int>, IDateTracking 
{
  public Person()
  {
    DateCreated = DateTime.Now;
  }
}

In addition, whenever you’re modifying an instance of Person, you can update the DateModified property:

myPerson.DateModified = DateTime.Now;

However, this gets repetitive and boring after a while and because you need to do this every time you make a change to a person, there’s a fair chance you forget to implement this code.

I prefer a different solution to the problem that works like this:

  1. I create an interface called IDateTracking that defines two read/write properties for the date and time an object was created and last modified.
  2. I let each of the objects I want to track implement this interface and add the two properties to the class to satisfy the contract specified by this interface.
  3. In my Entity Framework DbContext that saves new and modified objects to the database, I detect objects that implement this interface and then automatically update the correct properties with the current date and time.

Implementing step 1 and 2 is really easy; you’ll see how to do this next. Step 3 is discussed in the next article in this series when the EF DbContext is discussed.

Here’s the code for the interface I added to the Model project and namespace:

using System;

namespace Spaanjaars.ContactManager45.Model
{
  /// <summary> 
  /// Defines an interface for objects whose creation and modified 
  /// dates are kept track of automatically. 
  /// </summary> 
  public interface IDateTracking 
  {
    /// <summary> 
    /// Gets or sets the date the object was created. 
    /// </summary> 
    DateTime DateCreated { get; set; }

    /// <summary> 
    /// Gets or sets the date the object was last modified. 
    /// </summary> 
    DateTime DateModified { get; set; }
  }
}

This interface defines two read/write properties for the creation and modification dates. Implementing this interface in an entity is straightforward as well. Here’s the code for the Person class:

public class Person : DomainEntity<int>, IDateTracking 
{
  // Other code here

  public DateTime DateCreated { get; set; }
  public DateTime DateModified { get; set; }
} 

You can now assign DateCreated a value in the constructor to keep track of the date an object was created. When an existing data is retrieved from the database, that property is overwritten with the value from the database, giving you the correct date and time. You can now also manually set the DateModified property whenever you change the object. However, as you’ll see in the next article, you can let EF automatically manage these two properties for you.

Putting it All Together

So far you’ve seen the code for some simple classes that mostly consist of just a number of straightforward automatically implemented properties. However, in order to make the model more useful, you should create relationships between the various classes. For example, a Person should be given collection classes for the various contact details such as EmailAddress and PhoneNumber classes. Also, Person needs properties for address details such as HomeAddress and WorkAddress. To make the API easier to work with, all these properties should be instantiated in the constructor so you can access them immediately after you constructed a new Person.

Here’s the revised code for the Person class with the new properties and constructor code. Note: the code that comes with the article has full XML comments on all public members.

using System;
using System.Collections.Generic;
using Spaanjaars.ContactManager45.Model.Collections;
using Spaanjaars.Infrastructure;

namespace Spaanjaars.ContactManager45.Model
{
  public class Person : DomainEntity<int>, IDateTracking 
  {
    public Person()
    {
      EmailAddresses = new EmailAddresses();
      PhoneNumbers = new PhoneNumbers();
      HomeAddress = new Address(null, null, null, null, ContactType.Personal);
      WorkAddress = new Address(null, null, null, null, ContactType.Business);
    }

    [Required]
    public string FirstName { get; set; }
    [Required]
    public string LastName { get; set; }
    public DateTime DateOfBirth { get; set; }
    public PersonType Type { get; set; }
    public Address HomeAddress { get; set; }
    public Address WorkAddress { get; set; }
    public EmailAddresses EmailAddresses { get; set; }
    public PhoneNumbers PhoneNumbers { get; set; }

    public string FullName
    {
      get 
      {
        string temp = FirstName ?? string.Empty;
        if (!string.IsNullOrEmpty(LastName))
        {
          if (temp.Length > 0)
          {
            temp += " ";
          }
          temp += LastName;
        }
        return temp;
      }
    }
  }
}

With this setup, you can now write tests that confirm the properties have been set up correctly (and that demonstrate the usage of the API quite nicely):

[TestMethod]
public void CanAddEmailAddressToNewPerson()
{
  var person = new Person();
  person.EmailAddresses.Add(new EmailAddress());
  person.EmailAddresses.Count.Should().Be(1);
}

[TestMethod]
public void CanAddPhoneNumberToNewPerson()
{
  var person = new Person();
  person.PhoneNumbers.Add(new PhoneNumber());
  person.PhoneNumbers.Count.Should().Be(1);
}

[TestMethod]
public void NewPersonHasInstantiatedWorkAddress()
{
  var person = new Person();
  person.WorkAddress.Should().NotBeNull();
}

[TestMethod]
public void NewPersonHasInstantiatedHomeAddress()
{
  var person = new Person();
  person.HomeAddress.Should().NotBeNull();
}

Defining Repository Interfaces

The final code that needs to be added to the Model project is the definition of the interfaces for the repositories. In Part 1 of this series I briefly introduced the IRepository<T, K> interface that defines the contract that a repository class should implement to enable CRUD (Create, Read, Update and Delete) behavior. In my project, I placed the IRepository<T, K> in the Spaanjaars.Infrastructure project, so I can easily reuse it across multiple applications. I then added the following code;

using System;
using System.Linq;
using System.Linq.Expressions;

namespace Spaanjaars.Infrastructure
{
  public interface IRepository<T, K> where T : class 
  {
    T FindById(K id, params Expression<Func<T, object>>[] includeProperties);
    IQueryable<T> FindAll(params Expression<Func<T, object>>[] includeProperties);
    IEnumerable<T> FindAll(Expression<Func<T, bool>> predicate, 
                          params Expression<Func<T, object>>[] includeProperties);
    void Add(T entity);
    void Remove(T entity);
    void Remove(K id);
  }
}

Notice how this interface uses generics with two type parameters: T and K. T is used for the actual entity type (such as Person) while K is used for its key. The key is usually an int or a Guid. These types are then used in the interface members to define the parameter or return type of each method. You’ll see a more concrete example shortly.

The interface defines the following methods:

Member name Description

Add (returns void)

Adds an object to the underlying data source. How this is done depends on the underlying framework. The EF implementation adds it to the EF DbContext so it’s added to the SQL Server database whenever the changes are saved.

FindAll (returns an IQueryable of T or an IEnumerable of T)

Returns all requested objects in the underlying source. One of its overloads enables you to define a search expression. Both overloads accept a parameter to define which properties you want to eager load, as you’ll see later.

FindById (returns an instance of T)

Returns an instance of T by its unique ID in case it’s found, or null otherwise.

Remove (returns void)

Removes an object from the underlying data source. How this is done depends on the underlying framework. The EF implementation removes it from the EF DbContext so it’s also removed from the SQL Server database whenever the changes are saved.


By implementing the Add and Remove methods of this interface you can add and remove items from the underlying data source. The Remove method has an overload that accepts the unique ID of the object to make it easy to remove an entity without having a full instance at hand. Selecting is done using FindById (that returns a single instance) and FindAll (that returns a collection). Both methods accept a params array called includeProperties. This is used to dynamically include related entities (such as PhoneNumbers when accessing a person.) You see how this works in the next part in this series when the EF repository is explored. The overload of FindAll that returns an IEnumerable<T> has a parameter called predicate that looks like this: Expression<Func<Person, bool>>. Although it looks pretty scary with the nested generics, using it is pretty simple. As an example, here’s how you could search for all contact people of a specific type:

var colleagues = repository.FindAll(x => x.Type == PersonType.Colleague);

You can also use multiple criteria at the same time. For example:

var friendsNameMaryJane = repository.FindAll(
            x => x.FirstName == "Mary Jane" && x.Type == PersonType.Friend);

You’ll see more of the repository implementation later. For now all that’s important to realize is that the FindAll method lets you specify complex search criteria.

Finally, updating is done by retrieving one or more existing items, and then updating the object’s properties. When saving the changes using an EF DbContext, EF will automatically persist the changes into the database.

For the ContactManager application, I have one class that implements this interface: a PersonRepository to manage contact people. Rather than implementing this interface directly in my repositories, I created another interface that inherits IRepository<T, K>, like this:

public interface IPeopleRepository : IRepository<Person, int>
{
}

Although I haven’t added any members to this interface yet (other than those it inherits from the generic repository interface), it lays a nice foundation for future updates. Imagine I want to add a FindByLastName method to the PeopleRepository. I could add that member to IRepository instead, forcing my concrete implementations to implement this member as well. However, that method would have no meaning to other repositories you may add to your system. So by adding an intermediate interface you get the best of both worlds: IPeopleRepository can do anything IRepository can, but it’s still open to be expanded with methods that only make sense to a PeopleRepository.

My concrete PeopleRepository implements this interface as you’ll see in Part 5. Note that I am closing the generic type by explicitly specifying an int for the K type parameter. The Person class has been set up to use an int for the Id property as well (public class Person : DomainEntity<int>, IDateTracking) so it makes sense to make the repositories specific for an int as well.

With these interfaces, a method on an actual concrete repository to manage people in the system could look like this:

public Person FindById(int id, 
            params Expression<Func<Person, object>>[] includeProperties)
{
  // Implementation here 
}

The method accepts an int for the ID (as specified by the int type on the IPeopleRepository) and returns a Person because IPeopleRepository specifies Person as the type of the T type parameter which is used as the return type of the FindById method in the generic IRepository interface. As you’ll see in the next article, the actual implementation is slightly different because FindById is implemented in a generic repository.

The actual code (such as an MVC controller, a Web Forms page, or a Unit Test) would work with instances of the IPeopleRepository interface to get and update data in the database. Here’s an example of the Delete method of a controller in an MVC application that accepts the ID of the object and deletes it by calling Remove on the concrete repository:

[HttpDelete]
public ActionResult Delete(int id)
{
  using (_unitOfWorkFactory.Create())
  {
    _peopleRepository.Remove(id);
  }
  return RedirectToAction("Index");
}

Here, _peopleRepository is an object that implements the IPeopleRepository interface. In the MVC project, this instance is injected using StructureMap but you can of course also instantiate an object yourself.

The UnitOfWorkFactory code is explained in the next article in this series, and you’ll find full details on implementing an MVC frontend in Part 6 and details on a Web Forms implementation in Part 7 of this series.

Stuff I Like to Do

Just as in the previous article in this series, I’ll provide a quick list of things I like to do when building a model. Again, I won’t be providing a lot of detail, but instead mention a few items I like or consider best practices.

  • Implement a base class for collections. This way you can centralize the behavior for all your collections.
  • Let your custom collections inherit from the collection base class and don’t use List<T> in the public API of your object model.
  • Write extensive unit tests for your model classes. The Model project is now still relatively small, so you should be able to achieve great code coverage. Once you start expanding the model project it’ll be relatively easy to maintain a high code coverage. However, the lower the coverage, the less inclined you’ll be to catch up later.
  • Document the public members of your API using XML comments (http://msdn.microsoft.com/en-us/library/b2s063f7.aspx). For example, members in the various interfaces and classes should be documented to make it easier to work with them later in the project. You can force the compiler to generate an XML file with the comments as well as list all items you forgot to document as compilation warnings by checking off the XML documentation file checkbox on the Build category of the project’s Properties dialog, shown in Figure 4.7:

The Project Properties dialog
Figure 4-7 The Project Properties Dialog (click to enlarge)

I typically only do this for the release build so I am not cluttering the list with compile warnings too much during development.

Summary

In this article you saw how to build up the model for the application. If you’re familiar with previous versions of my N-Layer Design article series, you’ll recognize a lot of stuff. Even if you’re unfamiliar with those articles, the code in the Model project should be easy to follow: most of it comes down to simple POCO classes like Person, and a bunch of collection classes to support collections of the POCO classes. The most complex code is probably the equality comparer code in the two base classes in the Infrastructure project. However, this is plumbing code you only need to write once, and not maintain during normal development of your application.

In previous versions of this article series targeting .NET 2 and 3.5, the class design part of this setup was pretty easy to implement. All you had to do was creating the class and add the relevant properties for the types to them. However, it was the database part that was really hard to set up and required a lot of manually written code, stored procedures and testing. Fortunately, with EF Code First this is now really easy to implement as you’ll see in the next installment of this article series.

Downloads


Where to Next?

Wonder where to go next? You can read existing comments below or you can post a comment yourself on this article .


Consider making a donation
Please consider making a donation using PayPal. Your donation helps me to pay the bills so I can keep running Imar.Spaanjaars.Com, providing fresh content as often as possible.



Feedback by Other Visitors of Imar.Spaanjaars.Com

On Wednesday, August 14, 2013 11:17:59 AM Ahmad said:
such a great man , i will buy it after you finish it .
thanks man .
On Wednesday, August 14, 2013 11:46:57 AM Imar Spaanjaars said:
Why wait? You can get the entire series now for only $20....

Cheers,

Imar
On Friday, August 16, 2013 5:46:01 PM Ahmad said:
I just did :D
thanks man great series.
On Tuesday, August 20, 2013 4:29:39 PM Vladimir Kelman said:
I'm getting the following error:
The type or namespace name 'ModelConfiguration' does not exist in the namespace 'System.Data.Entity'

(I added a reference to System.Data.Entity)

Please advise
On Tuesday, August 20, 2013 5:43:04 PM Imar Spaanjaars said:
Hi Vladimir,

Where are you getting this error? In your code or in mine? If it's in yours, where do you get it? Also, did you add a reference to EntityFramework.dll (using NuGet as explained in part 5)? The EntityTypeConfiguration class is defined in that assembly.

Imar
On Friday, August 23, 2013 12:57:41 AM Vladimir Kelman said:
Imar, I started by writing my own code but then decided it's too much to type and it's a better idea to use your files. So, I got a mix... and yes, a reference to EF was missing in some projects. It's fixed now.
On Wednesday, September 11, 2013 10:22:22 AM Jonah said:
Hi Imar,

Can you please explain why you have made the Address type a ValueObject instead of a DomainEntity? I would have thought that this would be limiting the data model and making the DB design too rigid.

If you had the Address as a DomainEntity it allows for flexibility Using DomainEntity as a base if you added a third or fourth address to a person, it would just add more rows to the Addresses table. By using a ValueObject as a base, if you add another address to the person (delivery address for example), it would mean a schema change to the People table (DeliveryAddress_City, DeliveryAddress_Street ...). It's never a good thing to do a schema update on a production database if it can be avoided :)

Also, with using DomainEntity's, I end up with magic numbers in my DB for lookup values for Enumerations. This would be problematic for data analysis later on (data warehousing). Is there a way to force EntityFramework to create and populate lookup tables for these values?

Many thanks for yet another excellent series of articles.
On Thursday, September 12, 2013 9:49:08 AM Imar Spaanjaars said:
Hi Jonah,

Address is a ValueObject purely for demonstration purposes so you can see the differences.

If you don't want enums you could model another entity and use that.

Cheers,

Imar
On Wednesday, October 16, 2013 9:50:20 PM Laura said:
Hi Imar
Do you plan on releasing a VB version of this project, like you did the others?
Thank you, Laura
On Thursday, October 17, 2013 7:33:54 PM Imar Spaanjaars said:
Hi Laura,

It would be nice to eventually have a VB version but I don't have the time to create one. Maybe one day someone reading this series will create it, just as happened with the previous series.

Cheers,

Imar
On Thursday, October 17, 2013 11:19:07 PM Laura said:
I just might do that, Imar (create the VB version)!  I am finding that working through these tutorials is really beneficial to me.  I am currently working through Julia Lerman's DbContext "BreakAway" sample and converting it to VB (and learning a lot).

Cheers, Laura
On Saturday, October 19, 2013 1:11:46 PM Imar Spaanjaars said:
Hi Laura,

That would be really cool! I can host it here on my site if you want to share it with others. If you decide to do this, let me know when you need any help or have any questions.

Cheers,

Imar
On Saturday, December 14, 2013 11:59:10 AM whiteswan said:
Hi Imar ,
Thanks for nice explanation .I have some question and I would appreciate if you clear these up for me .

1- Don't you think we don't need repository for all non ValueObjects ? We could have IAggregate interface and make repository for all classes which implement IAggregate .

2- By Abstracting Repository 'T' in EF implementation , In every concrete repository we have All CRUD action on the fly which is nice , But how could we make a repository read only or just wanted to have update and not delete ?

3- I do agree with you about not exposing Generic lists , To me  , Making custom collection is not in high priority ,I prefer to spend my energy on some other patterns like specifications.

Thanks in advance
On Saturday, December 14, 2013 12:03:51 PM Imar Spaanjaars said:
Hi whiteswan,

1) Yes, that would certainly work

2) Abstract the read methods to a IReadOnlyRepository. Implement that interface on the current Repository and implement a base ReadOnlyRepository class implementing this interface.

3) Agreed. However, it's only a few lines of code so it's not a big problem to me.

Cheers,

Imar
On Saturday, December 14, 2013 1:11:13 PM whiteswan said:
Thanks for the answer ,
Could you please explain a bit more about why we need comparison ? You made two example ,But Is there any pattern or best practices in which uses comparison ?

Thanks
On Saturday, December 14, 2013 1:13:48 PM Imar Spaanjaars said:
Comparison is used a lot with collections to determine whether an item exists and for ordering. Just put a breakpoint on the various Equals methods and run the applications to see what I mean.

Cheers,

Imar
On Friday, December 20, 2013 8:46:48 AM Lester said:
Hi Imar,

Can this:

return (FirstName + " " + LastName).trim()

replace the get of FullName property

or could it be an issue eventually?

Thank you,

Lester
On Friday, December 20, 2013 9:32:18 AM Imar Spaanjaars said:
Hi Lester,

Yes, that code has an issue. When either FirstName or LastName is null, this code would crash immediately. I would implement the Trim behavior on the FirstName and LastName properties so when accessed they return the correct value.

Cheers,

Imar
On Saturday, December 21, 2013 12:43:53 AM Lester said:
Hello Imar,

That's correct. I can make both fields with a default value of empty string too right? By setting it to a default value, that would not lead to a different issue right? I am trying avoid checks to gain performance.

Thank you,

Lester
On Saturday, December 21, 2013 12:27:43 PM Imar Spaanjaars said:
Hi Lester,

You could still have an issue when null gets assigned to the FirstName of LastName properties. I wouldn't worry about performance; checking for null or an empty string has no negative impact on performance, especially not compared to other operations such as database access.

Cheers,

Imar
On Saturday, December 21, 2013 7:32:31 PM Lester said:
You're right. Thanks for the tips Imar.
On Friday, January 17, 2014 12:55:08 PM Daniel said:
The IsTransient() Method does not work for DomainEntity with T = string.

BTW:  Much thanks for the very good series!
On Friday, January 17, 2014 1:03:40 PM Imar Spaanjaars said:
Hi Daniel,

Yes, you're right. But you could rewrite it to take null into account. Something like this should work:

public bool IsTransient()
{
  return object.Equals(default(T), Id);
}

Cheers,

Imar
On Tuesday, January 28, 2014 4:46:34 PM Arno said:
Hi Imar,

First of all thank you for all the work you've done for the articles, I am a big fan since the first series.

I need to design a client/server architecture and I am trying to use what you have described here. That works for the server side, but I am wondering how I could transfer my business entities to the Winforms client. It isn't possible to send a generic Repository of T via WCF as WCF doesn't work with generics. I have looked into REST services but I don't get the full picture.

My question might be out of scope but I hoped you could give some pointers.

Thanks!
Arno
On Tuesday, January 28, 2014 7:58:00 PM Imar Spaanjaars said:
Hi Arno,

Did you see part 8? http://imar.spaanjaars.com/580/aspnet-n-layered-applications-implementing-a-wcf-45-frontend-part-8

That describes how to expose your data over WCF with additional view models in between.

Cheers,

Imar
On Wednesday, January 29, 2014 3:54:20 PM Arno said:
Hi Imar,

Thank you I'm looking into it.

All the best,
Arno
On Thursday, March 13, 2014 12:23:49 AM Ricardo Gomez said:
Hi Imar.
Is the Structuremap use for simplicity and for demonstration purposes, or is it the one you use on your large projects and the one you recommend?

Greetings from The Mayan Land, Yucatan Mexico. Gods salut you ;)
On Sunday, March 16, 2014 6:55:34 PM Imar Spaanjaars said:
Hi Ricardo,

Structuremap is a fine product and I use it in many projects I build.

I recommend you check it out, but also check out some alternatives, to see which one you like best.

Cheers,

Imar
On Monday, June 02, 2014 5:34:43 PM Carlos said:
Hi Imar,

First I would like to thank you for all your work, I'm learning a lot.

I have a project that the Database is done. I'm using Code First with Existing Database to create my Models. I'm having problem to adapt DDD to this structure because some classes have composite keys. If I don't use the DomainEntity and ValueObject, would you know what could be the most generic way to override equals and make the validations?
On Monday, June 02, 2014 8:03:51 PM Imar Spaanjaars said:
Hi Carlos,

You can still implement Equals in each class directly and look at the properties that make up the composite key. Validation should also still just work. You can could still inherit from a common base class but get rid of the generics and the Id property (which will them be implemented as composite keys in each class).

Cheers,

Imar
On Sunday, June 08, 2014 7:41:44 PM Carlos said:
Hi Imar,

Thanks a lot. I did as you said. I had to leave the generics and the id part. Make all classes a CommonClass instead of using ValueObject and DomainObject.
On Thursday, June 19, 2014 7:19:34 PM Marcus said:
Hey Imaar, I am a really big fan of this architecture. I had a quick question, hopefully you can help me. How could I make IHasOwner more flexible. For example if IHasOwner would be in the Infrastructure project, would it be possible to make it more "generic" rather than tied to using People it would use "T". Any assistance would be awesome, thanks in advance!
On Friday, June 20, 2014 9:41:50 AM Imar Spaanjaars said:
Hi Maarcus,

I haven't tried it yet but I think you can make it generic indeed. Have the interface accept a T parameter, change person to T and on EmailAddress etc pass it the type of Person.

You'll then need to modify some code in SaveChanges that checks for the correct type.

Cheers,

Imar
On Friday, June 20, 2014 1:54:00 PM Marcus said:
Thanks Imar, I got it to work :-)
On Friday, June 20, 2014 1:59:22 PM Imar Spaanjaars said:
Hi Marcus,

For other readers, would you mind sharing how?


Imar
On Wednesday, July 16, 2014 1:27:14 PM Matej Trubar said:
I think your implementation of DomainEntity[T].Equals() is flawed, since if two different entity types E1 and E2 have DomainEntity[T].Id of same type, then two instances ( of types E1 and E2 ) with same Id value will be considered equal.

Any ideas how to fix this ( we could fix this by either making sure no two entity types have Id of same type or have each entity implement Equals() directly ... but I don't consider that to be a good solution )?

cheers mate
On Wednesday, July 16, 2014 2:20:27 PM Imar Spaanjaars said:
Hi there,

If I understand you correctly, it's not flawed, but it's by design. Two domain entities are considered equal when they are of the same type and have the same ID. Whether their contents are the same is irrelevant.

Cheers,

Imar
On Wednesday, July 16, 2014 4:58:12 PM Trubar said:
hi

What I'm saying is that with the design you have now two domain entities with same ID are considered equal even if they are of different types:


            /* both Person and EmailAddress derive from DomainEntity[int] */

            var person = new Person();
            person.Id = 1;

            var email = new EmailAddress();
            email.Id = 1;

            Console.WriteLine(person.Id == email.Id); // true

As far as I know, no instance of EmailAddress should ever be considered as being equal to any instance of type Person?!
On Wednesday, July 16, 2014 5:49:01 PM Imar Spaanjaars said:
Hi Trubar.

I see. It's flawed indeed ;-) In earlier versions I had a check for the type but somehow that has disappeared. In the code for Equals, right after the null check for obj, add this to resolve the issue:

if (GetType() != obj.GetType())
{
  return false;
}

Thanks for catching this.

Imar
On Wednesday, July 16, 2014 6:07:44 PM Trubar said:
thank you mate for great series
On Sunday, November 23, 2014 3:20:45 AM Ahmad said:
Hey Imaar, I am making my own implementation for a specific project along with this tutorial, the problem is I've got a many to many relationship between say for example, Products,Suppliers, and Suppliers_Products.
and unfortunately the tutorial lacks this many to many relation ship.
On Sunday, November 23, 2014 7:28:57 PM Imar Spaanjaars said:
Hi Ahmad,

EF supports many to many relationships. You can implement them in my model quite easily. Just Google for something like "ef many to many code first" and you'll find lots of examples.

Cheers,

Imar
On Friday, January 30, 2015 10:26:59 AM Robert said:
Jello IMar,

I suppose the comment on the

public void Sort()

method of the CollectionBase abstract class:

/// Sorts the collection based on the specified comparer

should be amended as I do not find any specified comparer.

Am I right or I'm missing something ?

Thank you.

Robert
On Friday, January 30, 2015 10:48:35 AM Imar Spaanjaars said:
Hi Robert,

Yes, you're correct. Looks like a copy and paste error from the overloaded Sort method.

Cheers,

Imar
On Sunday, February 01, 2015 8:47:39 PM Robert said:
Hello Imar,

in the Address class, the IsNull property returns true when four properties of the address contain null (Street, ZipCode, City, Country).

Why is the ContactType property not taken into consideration when its value is None ?

Thank you
Robert
On Sunday, February 01, 2015 9:28:31 PM Imar Spaanjaars said:
Good catch. That should / could have been included.

Cheers,

Imar
On Monday, February 02, 2015 8:53:43 PM Robert said:
Hello Imar,

the abstract class CollectionBase inherits the Collection class and implements the IList interface.

As the Collection class itself implements - among other interfaces - Ilist, why do you need to specify that CollectionBase implements IList ?

Thank you
Robert
On Tuesday, February 03, 2015 12:01:44 AM Imar Spaanjaars said:
You could leave it out as it is indeed already defined.

Cheers,

Imar
On Tuesday, February 10, 2015 9:51:01 AM Murat said:
Hi,

What if an Entity has owner other than Person? What if it has two owners (or can it be)? This is the only problem i'm issuing with your design. Any idea?

Thanks
On Saturday, February 14, 2015 8:39:17 PM Imar Spaanjaars said:
Hi Murat,

I haven't tried it but you could try to make IOwner a generic interface and specify the type of the owner.

When you have multiple owners you need code - for example in SavingCanges - and detect if another owner still has a reference to this resource.

Cheers,

Imar
On Friday, February 27, 2015 3:54:30 PM Robert said:
PeopleRepository is a concrete repository which inherits the abstract class Repository.

Why is this abstract class in the same project of the concrete repository ?

Couldn't we put it in the Infrastructure project ?

Thanks for your help.
On Sunday, March 01, 2015 6:09:19 PM Imar Spaanjaars said:
Hi Robert,

Yes, you could put it in the infrastructure too. I like to have it my application specific project so I can make changes to it that apply to the entire project.

Cheers,

Imar
On Sunday, March 29, 2015 6:54:32 PM Robert said:
Hello Imar,

why do you configure the MyDropCreateDatabaseIfModelChanges to be used as the database initializer during development in the web.config of the MVC project only and not in the web.config of the WebForms project too ?

Thank you
On Sunday, March 29, 2015 7:11:48 PM Imar Spaanjaars said:
No reason, other than that I developed the model and the MVC app first so recreating the database was convenient.

Imar
On Wednesday, April 08, 2015 4:48:40 PM Mike said:
I'm using Code First Migrations with your model and notice something peculiar when doing a Person.AddOrUpdate() on the migrations seed method, which I realize is a newer feature of EF.

When the seed method runs, I get a System.Data.Entity.Infrastructure.DbUpdateException. In the inner exception, it says "The conversion of a datetime2 data type to a datetime data type resulted in an out-of-range value." When debugging, it was because DateCreated was coming back as 1/1/0001.

I can prevent it by specifying a DateCreated in my seed method, but would be curious if you could elaborate as to why it happens this way.

Thanks!
Mike
On Thursday, April 09, 2015 7:05:58 AM Imar Spaanjaars said:
Hi Mike,

This happens because the default value for a DateTime in .net (1/1/0001) doesn't fit in a datetime column in SQL Server (where the smallest allowed value starts in 1753: https://msdn.microsoft.com/en-us/library/ms187819.aspx)

If you don't want to supply a default value, you can make the DateTime property nullable so it becomes nullable in the database as well. Alternatively, you should be able to configure EF to generate a datetime2 instead which has a wider range: https://msdn.microsoft.com/en-us/library/bb677335.aspx

Hope this helps,

Imar
On Friday, July 17, 2015 9:49:19 AM Morteza said:
Hello Imar,
You’ve added a method for Add on the EmailAddresses collection like this:
public void Add(string emailAddressText, ContactType contactType)
{
  Add(new EmailAddress { ContactType = contactType, EmailAddressText = emailAddressText });
}
Now how can make the Add method on the BaseCollection class or even Collection class itself hidden from the caller code? I mean the code who wants to add an email address to that collection only can see the custom Add method on the EmailAddresses class. I want this behavior to force some conditions on my Add method so collections can be added based on some specific criteria that I can control.
On Tuesday, November 17, 2015 5:59:14 PM Alan said:
I'm just curious. Why did you not add the OwerId property to the IHasOwner interface?
On Tuesday, November 17, 2015 6:06:47 PM Imar Spaanjaars said:
Hi Alan,

I didn't add it as I didn't need it for the implementation, but obviously you can easily add it.

Cheers,

Imar
On Monday, November 23, 2015 8:30:53 PM Jakob Jensen said:
Hi
Quickdoc 576
Fantastic article. Just what i needed.
Just have a question. I want to use this architecture with WCF, and on another server have my MVC project. If i should implement a service layer for wrapping up the repositories, how should i do that? Thinking about the DI and the service layer? Regards jakob
On Monday, November 23, 2015 10:38:11 PM Imar Spaanjaars said:
Hi Jakob,

Looks like you haven't read the entire series yet. Part 8 deals with this:
http://imar.spaanjaars.com/580/aspnet-n-layered-applications-implementing-a-wcf-45-frontend-part-8

Cheers,

Imar
On Friday, February 05, 2016 5:21:33 PM Mike said:
Any reason you wouldn't include the DateTracking properties in the DomainEntity base class rather than an interface?
On Saturday, February 06, 2016 4:28:47 AM Imar Spaanjaars said:
Hi Mike,

You could, if you want all of your entities to have this behavior. By separating it out to a separate interface, you can opt in for this behavior for only the entities for which you want to track this.

Cheers,

Imar
On Tuesday, February 23, 2016 2:59:25 PM Cristian said:
Hello Imar. Thanks for this great series!

I'm trying to follow this for a personal proyect using vb.net. I've hit an issue with IsTransient that I haven't been able to solve so far.

    public bool IsTransient()
    {
      return Id.Equals(default(T));
    }

In vb.net it is something like:

    Public Function IsTransient() As Boolean
           Return Id.Equals(Nothing)
    End Function

When doing the debug and I evaluate "Id.Equals(Nothing)" in the watch windows I see the correct result: True if the object was not initializated. However, when looking at the value return by the funcion is returns false (always).
Do you have any idea what I'm missing?

So far, to solve this issue I've to check for all particular Type implementations doing a cast. For example:

Public Function IsTransient() As Boolean
        If TypeOf Id Is Integer Then
            Dim temp As Integer = CType(TryCast(m_Id, Object), Integer)
            Return temp.Equals(Nothing)
        End If
End Function

This works as expected. However, by this way I need to contemplate each possible type and doesn't seems like something optimal to do.

Thanks,
Cristian
On Tuesday, February 23, 2016 7:53:28 PM Imar Spaanjaars said:
Hi Cristian,

It looks like you're currently comparing temp with Nothing (null) which will always return false.

What you probably want is:

Return temp.Equals(CType(Nothing, T))

which should (according to the article below) give you the proper defaults even for value types like an Integer.

http://stackoverflow.com/questions/833791/vb-equivalent-for-cs-defaultt

Haven't tried it yet, but I will if this doesn't fix it for you.

Cheers,

Imar

On Saturday, February 27, 2016 8:31:00 PM pepitolanda said:
Hi Imar,

Many thanks! Seems to work as expected with your solution!
It was so simple!. I'm sorry for bother you with that :).

Cheers,
Cristian

Talk Back! Comment on Imar.Spaanjaars.Com

I am interested in what you have to say about this article. Feel free to post any comments, remarks or questions you may have about this article. The Talk Back feature is not meant for technical questions that are not directly related to this article. So, a post like "Hey, can you tell me how I can upload files to a MySQL database in PHP?" is likely to be removed. Also spam and unrealistic job offers will be deleted immediately.

When you post a comment, you have to provide your name and the comment. Your e-mail address is optional and you only need to provide it if you want me to contact you. It will not be displayed along with your comment. I got sick and tired of the comment spam I was receiving, so I have protected this page with a simple calculation exercise. This means that if you want to leave a comment, you'll need to complete the calculation before you hit the Post Comment button.

If you want to object to a comment made by another visitor, be sure to contact me and I'll look into it ASAP. Don't forget to mention the page link, or the QuickDocId of the document.

For more information about the Talk Back feature, check out this news item.