且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

为Entity Framework导航属性设置默认对象

更新时间:2023-12-05 12:03:22

使用 ObjectContext.ObjectMaterialized Event 。



在实现后,每个正在加载到上下文中的实体引发此事件。



在您的上下文的构造函数中,订阅此事件。在事件处理程序中,检查实体类型是否为 Person ,如果是,请为该人员创建新的配置文件。这是一个代码示例:

  public class Context:DbContext 
{
private readonly ObjectContext m_ObjectContext;

public DbSet< Person>人{get;组; }
public DbSet< Profile>个人资料{get;组; }

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人= e.Entity为人;

if(person == null)
return;

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

}
}

请注意,如果您提交更改,新配置文件将被保存回数据库。


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.

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.