在EF 6中更新子实体的正确方法是什么?

时间:2015-03-30 16:27:39

标签: c# entity-framework

必须有一种更好的方法来处理EF 6中的儿童保存/更新。当然,这种重复只是我的失败。

实体

public partial class MyParentType
{
    public MyParentType()
    {
        this.children = new HashSet<child>();
    }

    public int parentID { get; set; }

    public virtual ICollection<child> children { get; set; }
}

添加/更新

public class MyRepository : IMyRepository
{
    private readonly IErrorLogger _logger;
    private readonly CorporateEntities _context;

    public MyRepository(IErrorLogger logger)
    {
        _logger = logger;
        _context = new CorporateEntities();
    }

    public void Update(IEnumerable<MyParentType> parents)
    {
        try
        {
            Add(parents.Where(x => x.parentID == 0));
            var updatedData = parents.Where(x => x.parentID != 0);
            foreach (var parent in updatedData)
            {
                var original = _context.MyParentTypes.FirstOrDefault(x => x.parentID == parent.parentID);
                _context.Entry(original).CurrentValues.SetValues(parent);
                UpdateChildren(parent);
            }
            _context.SaveChanges();
        }
        catch (Exception exception)
        {
            _logger.Error(exception.Message, exception);
        }
    }

    public void Add(IEnumerable<MyParentType> parents)
    {
        if (parents == null)
            return;
        try
        {
            _context.MyParentTypes.AddRange(parents);
            _context.SaveChanges();
        }
        catch (Exception exception)
        {

            _logger.Error(exception.Message, exception);
        }
    }

    private void UpdateChildren(MyParentType parent)
    {
        try
        {
            AddChildren(parent.children.Where(x => x.childID == 0));
            var updatedData = parent.children.Where(x => x.childID != 0);
            foreach (var child in updatedData)
            {
                var original = _context.children.FirstOrDefault(x => x.childID == child.childID);
                _context.Entry(original).CurrentValues.SetValues(child);
            }
            _context.SaveChanges();
        }
        catch (Exception exception)
        {

            _logger.Error(exception.Message, exception);
        }
    }

    private void AddChildren(IEnumerable<child> references)
    {
        try
        {
            _context.children.AddRange(references);
            _context.SaveChanges();
        }
        catch (Exception exception)
        {

            _logger.Error(exception.Message, exception);
            throw;
        }
    }

}

我觉得我不应该复制这个或写一个通用的方法来处理这两种情况。我是否遗漏了EF docuemtation中的哪些内容,我可以用父代实体更新子实体?

1 个答案:

答案 0 :(得分:4)

我建议您使用GraphDiff。使用此library,您的Update方法将如下所示:

 public void Update(IEnumerable<MyParentType> parents)
 {
   try
   {
       Add(parents.Where(x => x.parentID == 0));
       var updatedData = parents.Where(x => x.parentID != 0);
       foreach (var parent in updatedData)
       {
          _context.UpdateGraph(parent, map => map.OwnedCollection(p => p.children));   
       }
       _context.SaveChanges();
   }
   catch (Exception exception)
   {
     _logger.Error(exception.Message, exception);
   }
}

这样您就不必担心管理孩子们的州。

如果您不想使用GraphDiff,则需要手动管理子项的状态:

 public void Update(IEnumerable<MyParentType> parents)
 {
   try
   {
       foreach (var parent in parents)
       {
         if(parent.Id==0)
         {
          _context.MyParentTypes.Add(parent);
         }
         else
         { 
            //When you change the state to Modified all the scalar properties of the entity will be marked as modified
           _context.Entry(parent).State = EntityState.Modified;

            foreach(var child in parent.children)
            {
               context.Entry(child).State =child.Id>0? EntityState.Modified:EntityState.Added;  
            }
         }
       }

       _context.SaveChanges();
   }
   catch (Exception exception)
   {
     _logger.Error(exception.Message, exception);
   }
}