2

My questions are:

  1. Is it possible to initialize dependent objects within a parameterless constructor with the EF?
  2. If so, what is the proper way to do this? If not, where should dependent objects be initialized if not in the constructor?

In testing out my code it appears that I cannot initialize objects within a parameterless constructor; if I do, the Entity Framework will not properly load them.

When loading the object, this code loads properly

abstract public class Channel
{
    public long ID { get; protected set; }
    public Verification Verification { get; protected set; }

    public Channel() { }
}

Whereas this code does not load properly

abstract public class Channel
{
    public long ID { get; protected set; }
    public Verification Verification { get; protected set; }

    public Channel()
    {
        Verification = new Verification();
    }
}

Note: In the examples above I am working from data that already has been stored in the database, I am not recreating the data and then loading it for each example (I'm not aware that it makes any difference).

Here is the concrete derived class:

public class Email : Channel
{
    public string Address { get; protected set; }

    public Email(string address)
    {
        Address = address;
    }

    public Email() : this(string.Empty) { }
}

For clarification, this is how I create, save, and load my entity:

// Creating / saving
using (Context context = new Context())
{
    Email email = new Email("person@blah.com");
    // Do some stuff with the Verification object

    context.Channels.Add(email);
    context.SaveChanges(); // EF assigns an ID of 1
}

// Loading
using (Context context = new Context())
{
    Email email = context.Find(1); // Using the value of 1 from above
}

When loaded with the 'loads properly' constructor above, the Verification object is correctly loaded- it is the one I created / saved. When the 'does not load properly' constructor is used (the one with some initialization), the Verification object is just a 'newed' version (no proxy with an ID of 0).

Every page but one I see says that object initialization within parameterless constructors is fine, because the EF will properly identify them as unmodified despite the initialization, and override the values with those pulled from the database. The only page I see which says you can't do this is here, although I don't see any suggestion about how to initialize objects within a parameterless constructor.

I want to have parameterless constructors when they are warranted without having to create a useless parameterized constructor to bypass the inner workings of the EF. Such "simplicity" is killing me. The further I go with EF, the more any object-oriented code deteriorates before my eyes. =*(

Community
  • 1
  • 1
  • What do you mean by "does not load properly"? What code are you running to see that? – jjj Sep 19 '15 at 05:44
  • @jjjI I edited my question to clarify that information. – Justin Laughland Sep 20 '15 at 19:01
  • Just don't initialize reference navigation properties. I think I've demonstrated sufficiently that this has many adverse effects. The EF class model just can't adhere to all OO principles, it's tailored to data access first and foremost. – Gert Arnold Sep 20 '15 at 21:28
  • @Gert Sorry, I took another look at your question and still don't understand how you are supposed to initialize objects. Let's say that I want to create an 'Email' object as above with a dependent Verification class (relationship established with the fluent API). When should the initialization of the Verification object take place? Who is responsible for that- me or the EF? When I call 'new Email(...)' the Verification object is null even after SaveChanges() so the only way I can see initializing it is by doing it myself. – Justin Laughland Sep 22 '15 at 05:54
  • *...is by doing it myself*. That's the idea. But let me reopen the question and maybe you can edit it to point it more explicitly to the question when to initialize dependent objects, given the fact that the constructor is not the best place for this. – Gert Arnold Sep 22 '15 at 06:41
  • @Gert I updated the question to explicitly point to dependent objects and asked what the correct way to initialize them is if not in the constructor. As to your statement 'the constructor is not the best place for this'... I assume that your statement is referring exclusively to the purpose of the constructor in the EF, correct? The entire point of a constructor in general is to initialize an object which is what has me so confused. =/ – Justin Laughland Sep 22 '15 at 19:06

1 Answers1

0

As said in my answer you refer to, in an Entity Framework class model, as opposed to a true domain model, it's bad practice to initialize reference navigation properties in an entity's constructor.

But yeah... we have to initialize reference navigation properties somewhere. So what's the best place? I think the message is: keep it simple. I think it should be possible to hack EF into replacing a default object by an object it has materialized itself, but that wouldn't be trivial. And it would be a possible source of unexpected bugs.

So basically there are two options:

  • Don't initialize them, set primitive foreign key properties:

    var channel = new Channel { VerificationId = someId };
    

    This probably hurts the eyes of domain-driven adepts even more, but working with foreign key associations (a combination of a reference and a primitive property) is officially recommended by EF because it has many advantages.

  • Initialize them by simply newing them up when necessary.

An EF class model only remotely resembles a domain-driven model. Many DDD principles can't be applied to it, because the EF model is "just" a data access layer. Better to accept this than trying to fight it.

Community
  • 1
  • 1
Gert Arnold
  • 105,341
  • 31
  • 202
  • 291