Setting a default object for Entity Framework navigation property

a 夏天 提交于 2020-01-15 08:24:14

问题


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.


回答1:


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.




回答2:


Yes.

You just need to implement the IdProfile 'get' property in person, where the profile ID must be setted.

Let me try to show you using fluent API:

public class Person
{
    public int Id {get; set;}
    private int _idProfile;
    public int IdProfile {
        get{
            return _idProfile == 0 ? DEFAULT_PROFILE_ID : _idProfile;
        }
        set{
            _idProfile  = value;
        }
    }

    public virtual Profile @Profile;
}

public class Profile
{
    public int Id {get; set;}
    public virtual ICollection<Person> Persons { get; set; }
}

/* MAPPING */

public class PersonMap : EntityTypeConfiguration<Person>
{
    this.HasRequired(t => t.Profile)
            .WithMany(t => t.Persons)
            .HasForeignKey(d => d.IdProfile);
}


来源:https://stackoverflow.com/questions/33600799/setting-a-default-object-for-entity-framework-navigation-property

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!