什么是使用EF更新Master-Detail的正确方法

时间:2015-09-21 11:40:10

标签: c# entity-framework dbcontext master-detail

我正在使用离线 Master-Detail,如下所示:

enter image description here

目前我正在删除集合,然后再次添加它们。即使并非该系​​列的所有项目都已修改

这是进行更新的正确方法吗?

修改:

根据评论添加了代码和一些修改:

  CreateMasterFromView(){
       Master aMaster = new Master();
       aMaster.MasterId = View.Id  // I set Id because I'm editing this master
       aMaster.MasterValue = "Some value";

       foreach (var detail in View.Details)
       {
         Detail aDetail = new Detail();
         aDetail.DetailValue = View.DetailValue;
         aDetail.MasterId = View.Id // 
         aMaster.Details.add(aDetail);
       }    
        Save(aMaster);
    }

Save (Master aMaster){
    if (aMaster.MasterId != 0)
    {                  
        var oldDetails = Dba.Details.Where(detail=> detail.MasterId == aMaster.Id);
        foreach (var oldDetail  in oldDetails )
                    {
                       Dba.Details.Remove(oldDetail);
                    }
        foreach (var detail in aMaster.Details)
                    {
                        Dba.Entry(detail).State = EntityState.Added;
                    }
    }
    Dba.Entry(aMaster).State = EntityState.Modified;
    Dba.SaveChanges();
}

3 个答案:

答案 0 :(得分:2)

我不是100%肯定,但这应该有效:

Master.Details.Clear();
Dba.SaveChanges();

EF会对其实体进行大量跟踪,在您使用SQL时不要尝试使用EF。

答案 1 :(得分:1)

当您的实体处于非连接状态时(以下是多层应用中的域外),以下示例非常有用:

public class Master
{
    public long MasterId { get; set; }
    public object MasterValue { get; set; }
    public virtual ICollection<Detail> Details { get; set; }
}

public class Detail
{
    public long DetailId { get; set; }
    public long MasterId { get; set; }
    public object DetailValue { get; set; }
    public Master Master { get; set; }
}

public class YourContext : DbContext
{
    public DbSet<Master> Master { get; set; }
    public DbSet<Detail> Detail { get; set; }
}

public class Test
{
    public void ChangeMasterValue(Master master, object newValue)
    {
        using (var context = new YourContext())
        {
            context.Master.Attach(master);
            master.MasterValue = newValue;
            context.SaveChanges();
        }
    }

    public void DeleteAllDetailsFromMaster(Master master)
    {
        using (var context = new YourContext())
        {
            context.Master.Attach(master);
            master.Details.Clear();
            context.SaveChanges();
        }
    }

    public void AddDetailToMaster(Master master, Detail newDetail)
    {
        using (var context = new YourContext())
        {
            context.Master.Attach(master);
            master.Details.Add(newDetail);
            context.SaveChanges();
        }
    }

    public void DeleteDetailFromMaster(Master master, Detail detailToDelete)
    {
        using (var context = new YourContext())
        {
            context.Master.Attach(master);
            master.Details.Remove(detailToDelete);
            context.SaveChanges();
        }
    }

    public void UpdateMaster(Master master)
    {
        using (var context = new YourContext())
        {
            context.Master.Attach(master);
            context.Entry(master).State=EntityState.Modified;
            context.SaveChanges();
        }
    }
}

答案 2 :(得分:1)

有两种方法可以更新实体:

  1. 从db获取旧实体,然后更新已更改的属性 呼叫保存更改。
  2. 直接将新实体附加到db并调用保存更改。 (无需从db获取旧实体)
  3. 在你的情况下,它可以是这样的:

    if (Master.MasterId != 0)
    {
         var oldDetails = Dba.Detail.Where(det => det.MasterId == Master.MasterId);
         foreach (var olddetail in oldDetails)
         {
               // don't call remove here just update new values in those properties which are changed like this   
         }
         //no need to set modified state because this olddetail is in current request
    }
    Dba.SaveChanges();}
    

    或第二种方式:

    if (Master.MasterId != 0)
    {
        Dba.Entry(Master).State = EntityState.Modified;
    }
    Dba.SaveChanges();