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

标签 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 文档中的某些内容,我可以在其中使用父实体更新子实体?

最佳答案

我建议您使用 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);
   }
}

这样你就不用担心管理 child 的状态。

如果你不想使用GraphDiff,那么你需要手动管理children的状态:

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

关于c# - 在 EF 6 中更新子实体的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29351401/

相关文章:

c# - 是否可以限制 Parallel.ForEach 的内核数?

c# - Windows 中的 64 位和 32 位注册表问题(在 C# 中编程)

c# - 如何在 Angular 2 中序列化/反序列化 .NET 类型的 JSON

entity-framework - EntityCommand.CommandText 值的格式必须为 'ContainerName.FunctionImportName'

c# - Nullable Field 和 SQL Is Null 问题

c# - 条件断点在 Visual Studio 2015 中不起作用

c# - 在运行时创建类和项目的属性

c# - EF Code First - 如何使用 Include 扩展方法过滤相关对象

c# - LINQ - 如何编写查询来设置变量 bool True 或 False

c# - .NET Core 依赖项的 Nuget 包恢复路径