Entity Framework, Private Constructors and Private Setters

As I learn more and more from Domain Driven Design, my classes for DDD projects (those that are complex enough to need more than simple CRUD), are shifting from what are referred to as “anemic domain models” and more like “rich domain models”.

The term “anemic domain model” (which I still have an aversion to…the term, that is) refers to a class that doesn’t really do much at all. It has a bunch of properties and maybe some methods. To use them you instantiate or retrieve the object and then populate the properties at will. When working in DDD, the focus is on behaviors, not properties. So you would have methods to control what happens to  your objects and in doing so, constrain the properties so that they are not exposed to be set or modified “willy nilly”.

Here is an extremely simple pair of classes that are designed using some of the techniques I’m learning from DDD:

  public class AThingAsEntity
  {
    private AThingAsEntity(){}  //the private constructor

    public AThingAsEntity(string description, int anInt, string aString)
    {
      Description = description;
      SomeOtherThing = new SomeOtherThing(anInt, aString);
    }

    public int Id { get; private set; }
    public string Description { get; private set; }
    public SomeOtherThing SomeOtherThing { get; set; }

    public void TheOtherThingMustChange(int anInt, string aString)
    {
      SomeOtherThing = new SomeOtherThing(anInt, aString);
    }
  }
  public class SomeOtherThing:ValueObject<SomeOtherThing>
  {
    private int anInt;
    private string aString;

    private SomeOtherThing(){} //the private constructor 
   //this value object’s constructor is internal to prevent random instantiation
internal SomeOtherThing(int anInt, string aString) { AValue = anInt; AnotherValue = aString; } public int AValue { get; private set; } public string AnotherValue { get; private set; } }
 

I’m constraining the class so that anyone who instantiates it is required to pass in some values. And those values all have private setters. There’ s no way to write code like:

var thing=new AThingAsEntity();
thing.Description="oh i'll just put whatever I want in here. heh heh heh. Domain rules be damned";

 

That’s the way I want to write this class to represent my domain.

In the past week or so, I’ve been asked three separate times (by three different developers) if it’s possible to use this pattern of private setters with EF. The answer is “yes”. Here, let the Doctor confirm that:

And in case you’re curious, I’m doing this with EF5.

Entity Framework requires a parameterless constructor in order to materialize objects returned from queries (or loading). I  have made this concession in my class but notice that it is a private constructor. So I’m still protecting my class. Nobody can access it. But EF is still able to populate this class when I execute queries. And no, I’m not doing some magic to tell EF to use my public constructor. It really uses the private constructor.

I’ll use an integration test to demonstrate.

Note that my test is using an initializer called SeedMyThings to always drop and recreate the database and shove in this seed data:

      new AThingAsEntity("This is MY thing", 42, "That is the meaning of life")

My test sets that initializer so I can perform the test I’m interested which requires some seed data.

[TestClass]
  public class Tests
  {
    public Tests()
    {
      Database.SetInitializer(new SeedMyThings());
    }
    [TestMethod]
    public void EfCanPopulateObjectWithPrivateCtorAndSetters()
    {
      using (var context=new ThingieContext() )
      {
        var thing = context.Things.FirstOrDefault();
        Assert.IsInstanceOfType(thing,typeof(AThingAsEntity));
        Assert.AreNotEqual(0, thing.Id);
        Assert.IsFalse(string.IsNullOrEmpty(thing.Description));
        Assert.IsFalse(string.IsNullOrEmpty(thing.SomeOtherThing.AnotherValue));
      }
    }
  }

I know…all those Asserts…bad tester.  So shoot me. ;)

Anyhooooo…. the test passes. Even with my private ctor and private setters, EF is able to materialize the object and even it’s SomeOtherThing property which is a value object. (which also has a private ctor and private setters). Internally EF is reading the metadata of the model and using reflection to set the values of the properties.

I also want to point out that I had been using a protected constructor. In the past, I am sure I tried private and it didn’t work. (Maybe an earlier version of EF?) But Steve Smith asked me “if setters work as private, why not constructor?” So I tried it and voila, it worked too.

And now, for my first EVER public Git repository. You can find my little sample solution at https://github.com/julielerman/EF_and_Private_CTORs_n_Setters. :)

18 thoughts on “Entity Framework, Private Constructors and Private Setters

  1. Thanks for that Julie. It’s as simple as it should be. The question I have is when did this change? I’m convinced that EF used to require a public default constructor and public setters on all propertites.

    By the way, great article in MSDN. DDD is something I’ve been trying to get the Transaction Script guys where I work to get into. Having somehting in print from you has worked wonders. Really looking forward to the 3 installment.

  2. Hi Julie, thanks for the article. Your post also helped us with our DDD and EF implementation.

    We have however noticed that lazy loading does not work with a private constructor. It seems EF cannot create a dynamic proxy in this case.

    Changing the constructor to protected however seems to get lazy loading to work again and still having some protection from public access on the constructor.

    1. Making the constructor protected instead of private helped fix a problem I was having with lazy loaded properties. Thanks!

  3. Hi Julie,

    I’m owning Asus VivoBook 15", it have perfect FullHD IPS screen, external videocard (GeForce 650M) and good storage – SSD 128 GB and HDD 500 GB. Of course it’s havier, around 2.1 kg, but much powerfull, Core i7-QM3820 (8 logical cores).

    Regarding Surface Pro 2, just found that Microsoft will give you for free 1 year of Skype Unlimited World subscription plan and 2 years of 200 GB SkyDrive, sounds good :)

  4. I love how it works but don’t these private settors and ctors create a leaky abstraction? Code for persistence is in your domain model. BTW, thanks for getting me started on a deep dive in to DDD.

  5. I was wondering if I could make a "virtual ICollection<childPoco>" protected and EF would still lazyload the collection? Any idea if that would work or not?

  6. If Entity Framework can populate our "rich" domain models through bypassing the constructor and setters, then surely our models aren't so rich after all? Who knows what important instantiation logic could be circumvented. Should we not have a separate set of entity models (which map to our database tables) and have these project into our domain models when returned from the relevant repositories? When I say "project" I mean through the legal route of constructors and setters.

  7. Thanks, Julie, these are the answers I needed.

    Does this make NHibernate completely obsolete?

    I'm so happy that people are moving towards DDD. I've been waiting 10 years for that. Imagine… I had to write a custom OR mapper 10 years ago!

  8. @Davenewza…don't you see populating entities from the database as already pre-vetted? You can make that same argument for any ORM that's used with DDD, so I think you're just picking on EF. ;)

  9. @Paul I might be wrong but I don't see this as creating a leaky abstraction at all – in fact, the opposite. We're not putting code for persistence into the domain model by making things private, and we shouldn't make things private just for the sake of it. If making constructors of properties private encriches the domain model (or just makes sense), then Julie is saying go ahead and do it and don't worry about Entity Framework because it supports it. For example, say we have an entity called Branch, and there are 5 branches in the persistence store but we shouldn't be allowed to add anymore (only retrieve existing ones). Couldn't this be accomplished simply by making the constructor for Branch private? That way, we can still retrieve existing Branches via EF, but new branches are uncreatable. We're doing this because it enriches the domain – it's not for the benefit of EF.

  10. @Julie: I am not picking on EF! I use EF broadly and it is fantastic (and I love your talks and articles on the matter as well). My argument is that rich domain models should be constructed through their public constructors and setters. This way you can ensure that your business rules cannot be violated. An example: an Order constructor could sum up the OrderLine amounts and set some internal field (say totalOrderAmount) for whatever purpose. This is a calculated field and is not represented in the database, and so it would not be populated by EF. Perhaps this isn’t an ideal example as you would likely provide a property to handle the calculation on request.

    1. @davenewza
      This would be true if the database is not considered as part of the long living scope of that object. In other words saving an object is not part of the business problem that the domain should solve. But part of a technical representation.

      Unless you don’t own the database and the database is considered as an interface to other systems. But then your domain modeller would have designed this in his model and have prepared use cases for this scenario. But as long as the database is just a way to persist a domain object you don’t need to go to a public constructor.

Leave a Reply

Your email address will not be published. Required fields are marked *


9 × nine =

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>