One of the four fundamentals of Object-Oriented Programing is Encapsulation which is defined as: “A language mechanism for restricting access to some of the object’s components”. This would help us separate the internal implementation from the publicly accessible surface of the object. The idea is to hide how the object actually work from the outside world, so that we can change the internal without breaking anything as the object still looks the same from the outside.

Sometimes we just ignore this and expose the object’s internal, this is true specially when we come up with a limitation such as serialization and persistence in the frameworks that we use.

Entity Framework as of version six, has some limitations that can be worked around, in this post, I’ll give you some hints on how to apply encapsulation and information hiding on your domain objects, while letting EntityFramework do its work.

Object Construction

EntityFramework needs a parameterless constructor to construct an object when it needs to instantiate the object before hydrating the object. You might think that you need a public parameterless constructor (a.k.a nullary constructor) but that’s not true. You can get away with private constructor. This helps with encapsulation as the object can only be constructed by user of the code (e.g. your application) correctly.

public class Product 
{
    private Product() 
    {
    }

    public Product(string name)
    {
        Name = name;
    }

    public string Name { get; private set;}
}

As you can see from the code, there’s no way you can create an invalid Product object. This class works perfectly fine in EntityFramework as well.

Collection Mapping

Your domain entities might have collection that need persistence, but when you expose your collection as IList or ICollection, entries can be added directly from the outside world to the collection. Although you can enforce proper construction of the object by using the right constructors, this still doesn’t make it right.

Let’s take the above Product class as an example. If you want to keep history of the name changes, how would you do that? Here’s one way of doing that:

public class Product 
{
    private Product() 
    {
        NameHistory = new List<ProductNameHistory>();
    }

    public Product(string name)
    {
        Name = name;
    }

    public string Name { get; private set;}

    public void ChangeName(string newName)
    {
        NameHistory.Add(new ProductNameHistory(Name, newName));
        Name = newName;
    }

    private IList<ProductNameHistory> NameHistory { get; set; }
}

public class ProductNameHistory
{
    private ProductNameHistory() 
    {
    }

    public ProductNameHistory(string oldName, string newName)
    {
        OldName = oldName;
        NewName = newName;
    }

    public string OldName { get; private set; }
    public string NewName { get; private set; }
}

Now this looks fine, except it does not work well with EntityFramework as it won’t store private collections/lists. A way to get around it is by creating EntityTypeConfiguration class for your entity, but because the HasMany method accepts an expression, it needs the collection to be public, which brings us back to where we were. As a workaround, you can move your EntityTypeConfiguration class to reside inside the entity, although not ideal, but that way you can access the private members to do the mapping.

Also if you still want to expose the collection for reading purposes, you can benefit from not-so-new readonly collection interfaces like IReadOnlyList<T> and expose your internal collection as readonly which makes it impossible to manipulate:

public class Product
{
    private Product()
    {
        NameHistory = new List<ProductNameHistory>();
    }

    public Product(string name)
    {
        Name = name;
    }

    public string Name { get; private set; }

    public void ChangeName(string newName)
    {
        NameHistory.Add(new ProductNameHistory(Name, newName));
        Name = newName;
    }

    private IList<ProductNameHistory> NameHistory { get; set; }

    public IReadOnlyList<ProductNameHistory> History
    {
        get { return new ReadOnlyCollection<ProductNameHistory>(NameHistory); }
    }

    public class ProductEntityTypeConfiguration : EntityTypeConfiguration<Product>
    {
        public ProductEntityTypeConfiguration()
        {
            HasMany(c => c.NameHistory);
        }
    }
}

Although encapsulation and OO design practices in general are key, there’s more than just that when it comes to properly designing a domain. Since this is more a DDD topic, I’ll keep it for another post.