使用存储库模式更新Entity Framework中的集合的导航属性

时间:2014-05-08 22:41:58

标签: c# entity-framework repository-pattern

我现在一直在编写C#,我通常使用Entity Framework并实现存储库模式。存储库模式告诉我们通常只应维护和访问聚合根的存储库。请考虑以下示例,其中Person是根:

public class Person
{
    public int ID { get; set; }
    public string Name { get; set; }
    public virtual ICollection<Pet> Pets { get; set; }
}

public class Pet 
{
    public int ID { get; set; }
    public string Name { get; set; }
}

上述模型意味着我们通常应该通过PersonRepository访问宠物。但是,如果我想修改或添加一个人的宠物,我从来没有找到一个优雅的方法来做到这一点。

为了正确识别要更新的内容,我需要致电

DbContext.Entry(myPet).State = EntityState.Modified;

然而,这与我的存储库模式混淆。据我所知,我有三个选择:

  1. 创建PersonRepository.AttachPet(宠物宠物)方法。使用复杂且更深入的嵌套模型,这很快变得麻烦。
  2. 直接获取DbContext以准备宠物进行修改或添加。但是,我实现了一个不直接访问DbContext的存储库。
  3. 修改PersonRepository.Update(人员)以自动更新基础宠物的状态。也不是很优雅,也可能是一项大任务。
  4. 我在这里缺少什么?有更好的方法吗?

1 个答案:

答案 0 :(得分:1)

是的,有更好的方法。对于新人,请使用:

_context.People.Add(myPerson); //myPerson can have Pets attached

这将遍历所有子对象并将其标记为NEW。 更新人员时,在调用上述代码后,您需要设置修改/删除哪些宠物对象。

我在Pluralsight课程Entity Framework in the Enterprise中学到了这一点。在其中,朱莉为宠物增加了一个额外的领域。

public enum ObjectState
{
    Unchanged,
    Added,
    Deleted,
    Modified
}

public interface IObjectWithState
{
    [NotMapped]
    [JsonIgnore]
    ObjectState ObjectState { get; set; }
}

public class Pet : IObjectWithState
{
    public int ID { get; set; }
    public string Name { get; set; }
}

您可能希望在所有数据库实体上使用此功能。

在您的资源库中

public void InsertOrUpdateGraph(Person entity)
{
    _context.People.Add(entity);
    if (entity.ID != default(int)) _context.ApplyStateChanges();
}

部分扩展程序

public static class ContextExtension
{
    public static void ApplyStateChanges(this DbContext context)
    {
        foreach (var entry in context.ChangeTracker.Entries<IObjectWithState>())
        {
            IObjectWithState stateInfo = entry.Entity;
            entry.State = stateInfo.ObjectState.ConvertState();
        }
    }

    public static EntityState ConvertState(this ObjectState state)
    {
        switch (state)
        {
            case ObjectState.Modified:
                return EntityState.Modified;
            case ObjectState.Added:
                return EntityState.Added;
            case ObjectState.Deleted:
                return EntityState.Deleted;
            default:
                return EntityState.Unchanged;
        }
    }
}

每次都有效。