在EF 6中更新子实体的正确方法是什么? [英] What is the proper way to update child entities in EF 6?

查看:115
本文介绍了在EF 6中更新子实体的正确方法是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在EF 6中必须有更好的方式来处理子级的保存/更新。当然,这种重复对我来说只是一个失败。

There has to be a better way to handle child Saving/Updating in EF 6. Surely this duplication is just a failure on my part.

实体

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文档中的某些可以与父实体更新子实体的东西?

I feel like I shouldn't have to duplicate this or write a generic method to handle both cases. Did I miss something in the EF docuemtation where I can update a child entity with the parent one?

推荐答案

我建议您使用< a href = http://blog.brentmckendrick.com/introducing-graphdiff-for-entity-framework-code-first-allowing-automated-updates-of-a-graph-of-detached-entities/ rel = nofollow> GraphDiff 。使用此您的更新方法将如下所示:

I recommend you use GraphDiff. With this library your Update method would be as I show below:

 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,则需要手动管理子状态:

If you don't want to use GraphDiff, then you need to manage the state of the children manually:

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

这篇关于在EF 6中更新子实体的正确方法是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆