Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Setting a default object for Entity Framework navigation property

Is it possible to set a default object for an Entity?

Say I have a Person entity that originally did not have a requirement for a Profile.

Now I require a Profile - but there are existing entities that do not currently have a Profile.

Is there a way I can provide a default object for these Entities when they're loaded in future, so anyone using the Person Entity can assume that Profile is never null and always has a value - even if it's a default.

Below you can see what I've tried - which does create a default value - but even when there is something in the database it always return the default object.

  • If the Profile is null I want to return a default initialzied object
  • If the Profile is not null I want to return the object from the database

Additionally - what would be the most sensible way to attach the "default" object to my dbcontext?

How can I achieve this desired behavior?

public class Person
{
    [Key]
    public int Id {get; set;}

    private Profile _profile;
    public virtual Profile Profile
    {
        get
        {
            return _profile ?? (_profile= new Profile
            {
                Person = this,
                PersonId = Id
            });
        }
        set
        {
            _profile = value;
        }

        // properties
    }
}

public class Profile
{
    [Key, ForeignKey("Person")]
    public int PersonId {get; set;}

    [ForeignKey("PersonId")]
    public virtual Person Person{ get; set; }

    // properties
}

I know you can initialize collections so that they're not null, but I'd like to initialize a single object too.

like image 483
Alex Avatar asked Nov 26 '25 13:11

Alex


1 Answers

Use the ObjectContext.ObjectMaterialized Event.

This event is raised for each entity that is being loaded into context after materialization.

In the constructor for your context, subscribe to this event. And in the event handler, check if the entity type is Person, and if so, create the new profile for the person. Here is a code sample:

public class Context : DbContext
{
    private readonly ObjectContext m_ObjectContext;

    public DbSet<Person> People { get; set; }
    public DbSet<Profile> Profiles { get; set; }

    public Context()
    {
        var m_ObjectContext = ((IObjectContextAdapter)this).ObjectContext;

        m_ObjectContext.ObjectMaterialized += context_ObjectMaterialized;

    }

    void context_ObjectMaterialized(object sender, System.Data.Entity.Core.Objects.ObjectMaterializedEventArgs e)
    {

        var person = e.Entity as Person;

        if (person == null)
            return;

        if (person.Profile == null)
            person.Profile = new Profile() {Person = person};

    }
}

Please note that if you commit changes, the new profiles will be saved back to the database.

like image 68
Yacoub Massad Avatar answered Nov 28 '25 03:11

Yacoub Massad



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!