0

考慮下面的表格(在截圖FK從位置到客戶是不可見的,但它的存在,只是沒有刷新...):實體框架:遞歸更新父子給我複製

DB

我的映射:

protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 
     modelBuilder.Entity<Customer>().ToTable("CUSTOMERS"); 
     modelBuilder.Entity<Customer>().HasKey(c => c.Id).Property(c => c.Id).HasColumnName("CUSTNO"); 
     modelBuilder.Entity<Customer>().Property(c => c.Name).HasColumnName("NAME"); 
     modelBuilder.Entity<Customer>().HasMany(c => c.AllLocations).WithRequired(l => l.Customer).Map(x => x.MapKey("CUSTNO")); 
     modelBuilder.Entity<Customer>().Ignore(c => c.RootLocations); 

     modelBuilder.Entity<Location>().ToTable("LOCATIONS"); 
     modelBuilder.Entity<Location>().HasKey(c => c.Id); 
     modelBuilder.Entity<Location>().Property(c => c.Id).HasColumnName("ID"); 
     modelBuilder.Entity<Location>().Property(c => c.LocationCode).HasColumnName("LOCATION_CODE"); 
     modelBuilder.Entity<Location>().HasMany(l => l.Children).WithOptional(ch => ch.Parent).Map(x => x.MapKey("PARENT_ID")); 


     modelBuilder.Entity<Product>().ToTable("PRODUCTS"); 
     modelBuilder.Entity<Product>().HasKey(p => new { p.Partno, p.LocationId, p.Quantity, p.SellUnit }); 
     modelBuilder.Entity<Product>().Property(p => p.Partno).HasColumnName("PARTNO"); 
     modelBuilder.Entity<Product>().Property(p => p.LocationId).HasColumnName("LOCATION_ID"); 
     modelBuilder.Entity<Product>().Property(p => p.PartDescription).HasColumnName("PART_DESCRIPTION"); 
     modelBuilder.Entity<Product>().Property(p => p.Quantity).HasColumnName("QUANTITY"); 
     modelBuilder.Entity<Product>().Property(p => p.SellUnit).HasColumnName("SELL_UNIT"); 
     modelBuilder.Entity<Product>().HasRequired(p => p.Location).WithMany(l => l.Products).HasForeignKey(p => p.LocationId); 
    } 

而且我的更新代碼:

public void UpdateLocations(string customerId, IEnumerable<Location> locations) 
    { 
     using (var context = new CustomerWarehouseContext(connectionString)) 
     { 
      foreach (var location in locations) 
       RecursiveUpdate(location, context); 
      context.SaveChanges(); 
     } 
    } 

    private void RecursiveUpdate(Location location, CustomerWarehouseContext context) 
    { 
     if (location != null) 
     { 
      bool locationIsNew = location.Id.Equals(Guid.Empty); 
      if (locationIsNew) 
      { 
       location.Id = Guid.NewGuid(); 
       context.Locations.Add(location); 
      } 
      else 
      { 
       context.Entry(context.Locations.Single(l => l.Id.Equals(location.Id))).CurrentValues.SetValues(location); 
      } 
      if (location.Children != null) 
      { 
       foreach (var childLocation in location.Children) 
       { 
        childLocation.Parent = location; 
        RecursiveUpdate(childLocation, context); 
       } 
      } 
      if (location.Products != null) 
      { 

       foreach (var product in location.Products) 
       { 
        if (locationIsNew) 
        { 
         location.Products.Add(product); 
        } 
        else 
        { 
         //How to update product when key is changed? I cannot use contex.Entry here? 
        } 
       } 
      } 
     } 
    } 

我執行下面的代碼:

 Customer customer = null; 
     using (var context = new AwesomeContext("myAwesomeConnectionString")) 
     { 
      customer = (from c in context.Customers.Include(c => c.AllLocations.Select(l => l.Products)) 
         where c.Id.Equals("100100") 
         select c).FirstOrDefault(); 
     } 


     Location locationToUpdate = customer.RootLocations.Single(l => l.Id.Equals(Guid.Parse("1a2ad52e-84cc-bf4c-b14d-dc57b6d229a6"))); 
     locationToUpdate.LocationCode = "Parent " + DateTime.Now.Millisecond; //Goes OK 
     locationToUpdate.Children[0].LocationCode = "Child " + DateTime.Now.Millisecond; //Goes OK 
     locationToUpdate.Children[0].Products[0].Quantity = 200; 
     locationToUpdate.Children.Add(new Location() { LocationCode = "XXX", Customer = customer, Parent = locationToUpdate }); //Creates duplicates? 
     UpdateLocations(customer.Id, newList); 

所以,我改變了家長和孩子的位置代碼,在孩子的位置更新產品的產品數量。數量是產品表的關鍵部分。 另外,我正在向父級添加一個新位置。

問題:

  • 我如何更新我的產品?因爲我改變了部分關鍵字,所以我無法使用context.Entry(...)來檢索舊的。
  • 爲什麼在添加第二個子位置後,我的上下文中有重複的客戶/位置?我最終有5個地點和2個客戶,而不是3個地點和1個客戶,所以它給了我一個PK例外。不知怎的,它在將一個孩子添加到某個位置後創建了一個新客戶。所以它有一個擁有2個位置的客戶實體,以及一個擁有3個位置的實體。爲什麼???

回答

2

如何更新我的產品?因爲我更改了部分密鑰,所以我不能使用context.Entry(...)來檢索舊密鑰。

您無法使用Entity Framework更改或更新實體的密鑰。 添加第二個孩子位置之後爲什麼我在我的上下文中的重複客戶/地點

context.Database.ExecuteSqlCommand("UPDATE..."); 

:如果你需要做到這一點,你必須使用手寫SQL命令?

您將分離的對象圖傳入您的UpdateLocations。如果將圖的任何節點添加到上下文中,那麼可以將該節點的導航屬性可訪問的所有其他分離實體添加到上下文中,並且它們都具有EntityState Added。如果您撥打SaveChanges,實體將被插入到數據庫中。這發生在這裏例如:

context.Locations.Add(location); 

因爲你的新位置有給客戶的客戶將投入Added狀態以及一個參考,這將複製數據庫中的客戶。您可以通過首先將客戶附加到上下文來避免這種情況。調用Attach將把實體進入狀態Unchanged,避免客戶的重複:

context.Customers.Attach(location.Customer); 
context.Locations.Add(location); 
+0

那麼這個作品,但它也標誌着我所有更新的位置爲不變。此外,當一個客戶的財產已經改變它不會更新這個:-( –