我现在一直在编写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;
然而,这与我的存储库模式混淆。据我所知,我有三个选择:
我在这里缺少什么?有更好的方法吗?
答案 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;
}
}
}
每次都有效。