【问题标题】:Setting a default object for Entity Framework navigation property为实体框架导航属性设置默认对象
【发布时间】:2015-11-09 11:21:53
【问题描述】:

是否可以为实体设置默认对象?

假设我有一个 Person 实体,它最初不需要 Profile

现在我需要Profile - 但现有实体目前没有Profile

有没有一种方法可以在将来加载这些实体时为它们提供默认对象,因此使用Person 实体的任何人都可以假设Profile 永远不会为空并且总是有一个值 - 即使它是一个默认值。

您可以在下面看到我尝试过的内容 - 它确实创建了一个默认值 - 但即使数据库中有某些内容,它也总是返回默认对象。

  • 如果Profilenull 我想返回一个默认的初始化对象
  • 如果Profile 不是 null 我想从数据库中返回对象

另外 - 将“默认”对象附加到我的 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
}

我知道您可以初始化集合以使其不为空,但我也想初始化单个对象。

【问题讨论】:

  • 当您加载一个在数据库中没有配置文件的Person 对象然后更新其上的某些属性并将其保存回来时,您希望发生什么? EF 是否应该在数据库中为此类人员创建个人资料?
  • @YacoubMassad 我想要一个没有ProfilePerson 有一个Profile 的实例化实例-除非调用SaveChanges(),否则它不必保存-但我目前不那么担心这部分 - 我只想实例化一个 Profile 如果它为空,如果它不为空,则正常从数据库加载。
  • 这是什么User 类?它是Person 的基类吗?
  • @YacoubMassad 抱歉 - 我调整了我的实际代码以使问题更容易理解,但我忘记将 User 类重命名为 Person - 它实际上应该是 Person - 我'已经编辑了我的问题以反映这一点。
  • 这听起来很奇怪。你的用例是什么?

标签: c# entity-framework entity-framework-6


【解决方案1】:

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

    }
}

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

【讨论】:

  • 这很整洁。我能够利用它使 Kendo Grid 在非平面视图模型上运行,这使我能够保持性能(相对于内存中的过滤和排序)。一般来说,这样做有什么缺点吗?
  • 我在测试 Profile 不为空的场景时,已经有一个打开的 DataReader 与此命令关联
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多