2015-11-09 96 views
1

是否可以为实体设置默认对象?为实体框架导航属性设置默认对象

说我有一个Person实体,最初没有要求Profile

现在我需要一个Profile - 但有一些现有的实体目前没有Profile

有没有一种方法,我可以提供,当他们在未来会加载这些实体默认的对象,因此,使用Person实体任何人都可以假定Profile永远不能为null,总是有一个值 - 即使它是一个默认值。

下面你可以看到我已经尝试过 - 哪些会创建一个默认值 - 但即使数据库中有某些东西,它总是会返回默认对象。

  • 如果Profilenull我想回到默认initialzied对象
  • 如果Profilenull我想从数据库中

此外返回对象 - 这将是将“default”对象附加到我的dbcontext最明智的方法是什么?

我怎样才能达到这个理想的行为?

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 
} 

我知道你可以初始化集合,使它们不为null,但我也想初始化一个对象。

+0

当你在数据库中加载没有配置文件的'Person'对象时,你想要发生什么,然后更新它的一些属性并保存回去? EF应该为数据库中的这个人创建一个配置文件吗? –

+0

@YacoubMassad我希望没有'Profile'的'Person'拥有'Profile'的实例化实例 - 除非调用SaveChanges()',否则不必保存 - 但我并不担心这个问题部分 - 我只是想实例化一个'Profile',如果它是空的,如果它不为空,就像正常情况下从数据库加载。 – Alex

+0

这是什么'User'类?它是'Person'的基类吗? –

回答

-1

是的。

您只需要实施IdProfile'get'属性,其中必须设置配置文件ID。

让我试着告诉你用流利的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); 
} 
+0

对不起,我可能不够清楚。 “默认”配置文件不是通过多个“Person”共享的,它只是'Profile'的初始化实例。 – Alex

3

使用ObjectContext.ObjectMaterialized Event

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

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

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}; 

    } 
} 

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

+0

这是一种整洁。我能够利用这个技术使Kendo Grid运行在非扁平视图模型上,这使我能够保持性能(与内存中的过滤和排序相比)。一般来说,这样做有什么缺点吗? – Charles