简体   繁体   中英

Initialization in a Parameterless Constructor (Entity Framework)

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. =*(

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM