使用子实体和孙实体更新实体

时间:2015-08-28 08:49:27

标签: entity-framework entity-framework-5 entity-framework-6

我尝试在更新具有深层关系的实体时找到问题的最佳解决方案。因为我的实体太复杂而且关系更深,所以我简化了这个。

MainCategory - 类别具有一对多关系,而类别 - 子类别也具有一对多关系

public class MainCategory
{
    [Key]
    public int Id { get; set; }
    public string MainCategoryName { get; set; }

    public virtual ICollection<Category> Categories { get; set; }
}

public class Category
{
    [Key]
    public int Id { get; set; }
    public string CategoryName { get; set; }

    public virtual ICollection<SubCategory> SubCategories { get; set; }
}

public class SubCategory 
{
    [Key]
    public int Id { get; set; }
    public string SubCategoryName { get; set; }

    public Category Category { get; set; }
}

以下是我在更新时处理这种情况的方法,或者具有子孙记录的新MainCategory实体来自某个地方。

public void AddOrUpdateMainCategory()
{
    using (var ctx = new MyContext())
    {
        // Gets MainCategory domain object.
        // Domain object has no id property because it does not come from (ctx.MainCategories)
        var mainCategory = GetMainCategory();

        var mainCategoryFromDb = ctx.MainCategory.Include(x => x.Categories.Select(y => y.SubCategories)).FirstOrDefault(x => someCondition());

        if (mainCategoryFromDb == null)
        {
            ctx.ShopParameterPeriodItems.Add(mainCategory);
        }

        // If mainCategoryFromDb is not null, mainCategory object should map to mainCategoryFromDb.
        else
        {
            ctx.SubCategories.RemoveRange(mainCategoryFromDb.Categories.SelectMany(x => x.SubCategories));
            ctx.Categories.RemoveRange(mainCategoryFromDb.Categories);
            ctx.MainCategories.Remove(mainCategoryFromDb);

            ctx.MainCategories.Add(mainCategory);
         }

         ctx.SaveChanges();
    }
}

代码问题

  • 由于更新机制正在删除旧实体及其子孙实体并添加新实体,因此每次刷新数据库记录的Id值。如果来自不同表的 MainCategory Category SubCategory 存在任何外键,这将是一个大问题。
  • 第一个问题可以像那样解决

        foreach (var category in mainCategoryFromDb.Categories)
        {
             foreach (var subCategory in category.SubCategories)
             {
                  // Set subCategory properties
             }
    
             // Set category properties
        }
    
        // Set mainCategoryFromDb properties
    

    这解决了 Id loss 问题,但正如我所写,实体非常复杂。它很难维护,我们不知道,例如, mainCategory 的哪个类别将更新 mainCategoryFromDb 的类别,因为mainCategory及其子孙实体没有Id属性。

我正在寻找的是一种解决问题的方法。

1 个答案:

答案 0 :(得分:0)

您的问题是您正在使用断开连接的实体,因此DbContext不会监视它们的更改。因此,您需要做的是在被删除的方案中自己跟踪更改,稍后当您将它们附加回DbContext时,根据跟踪的更改为每个实体设置正确的状态。

没有用于跟踪更改的fiex解决方案,但是,要将更改发送到数据库,您只需将根对象附加到上下文,然后设置每个跟踪实体的状态。

请参阅How to use DBContext.Add/Attach (using EF CodeFirst 4.1) with nested opbjects。这显示了附加和设置状态的基本方式。然后,您只需设置不同的状态,Unchanged除外,此问答显示在此问答语中。