2017-12-03 318 views
2

我使用實體框架來處理數據庫,我也自參照模型如下:如何使用實體框架更新自引用圖?

public class PhysicalObject 
{ 
    public PhysicalObject() 
    { 
     SubPhysicalObjects = new HashSet<PhysicalObject>(); 
    } 

    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 

    public int? ParentId { get; set; } 

    [StringLength(150)] 
    public string Title { get; set; } 

    public virtual PhysicalObject Parent { get; set; } 

    public virtual ICollection<PhysicalObject> SubPhysicalObjects { get; set; } 

} 

我用GraphDiff庫更新斷開的繪圖,但似乎它不支持自我更新引用圖。

我的問題是:什麼是更新使用實體框架的自我參照圖的最佳方式:

  • 刪除/更新現有physicalObjects

  • 插入不存在physicalObjects

回答

0

假設我有兩個實體,如下所示:

public class PhysicalObject 
{ 

    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 

    public int? ParentId { get; set; } 

    public int StorageRequestId { get; set; } 

    public string Title { get; set; } 

    public virtual PhysicalObject Parent { get; set; } 

    public virtual ICollection<PhysicalObject> SubPhysicalObjects { get; set; } 

    public virtual StorageRequest StorageRequest { get; set; } 

} 

public class StorageRequest 
{ 
    public StorageRequest() 
    { 
     PhysicalObjects = new HashSet<PhysicalObject>(); 
    } 

    [Key] 
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)] 
    public int Id { get; set; } 

    public string Title { get; set; } 

    public virtual ICollection<PhysicalObject> PhysicalObjects { get; set; } 
} 

請注意,PhysicalObject是自引用表。

var oldPhysicalObjects = dbContext.PhysicalObjects.Where(x => x.StorageRequestId== storageRequestId).ToList(); 

var existingIds = new HashSet<int>(); 
foreach (var item in newGraphDto.PhysicalObjects.ToList()) 
    { 
    updateGraph(item, oldPhysicalObjects, dbContext, storageRequestId,existingIds); 
    } 
var posToDelete = oldPhysicalObjects.Where(x => existingIds.All(e => e != x.Id)).ToList(); 
dbContext.PhysicalObjects.RemoveRange(posToDelete); 
dbContext.SaveChanges(); 

updateGraph方法將更新PhysicalObjects遞歸的每一棵樹,它看起來像:

private void updateGraph(PhysicalObjectDto physicalObjectDto, IList<PhysicalObject> oldPhysicalObjects, MyDbContext dbContext, int storageRequestId, HashSet<int> existingIds, PhysicalObject parent = null) 
    { 
     if (physicalObjectAddEditDto.Id == 0) 
     { 
      PhysicalObject po = new PhysicalObject 
      { 
       Id = physicalObjectAddEditDto.Id, 
       Title = physicalObjectAddEditDto.Title, 
       StorageRequestId = storageRequestId, 
       Parent=parent 

      }; 

      dbContext.PhysicalObjects.Add(po); 

      parent = po; 
     } 
     else 
     { 
      var po = oldPhysicalObjects.FirstOrDefault(x => x.Id == physicalObjectAddEditDto.Id); 
      po.Title = physicalObjectAddEditDto.Title; 
      po.StorageRequestId = storageRequestId; 
      po.Parent = parent; 
      dbContext.Entry(po).CurrentValues.SetValues(po); 

      parent = po; 
     } 


     existingIds.Add(parent.Id); 
     foreach (var subPhysicalObject in physicalObjectAddEditDto.SubPhysicalObjects) 
     { 
      updateGraph(subPhysicalObject, oldPhysicalObjects, dbContext, mailRoomRequestId, existingIds, parent); 
     } 

    } 

我希望我的代碼將幫助別人知道如何使用實體框架

不是讓我們更新圖表更新自引用表格的圖形樹