2011-04-03 77 views
3

我在我的數據庫中有3個相關的表。實體框架4 CRUD創建錯誤

農場----> FarmCrops < -----作物

我試圖更新作物的集合的一個農場實體,但我遇到了問題。我一直在努力,現在幾個小時沒有成功,所以任何幫助將不勝感激。

我收到的錯誤是這樣的:

的對象不能連接,因爲 它已經在目標範圍內。 對象只能在 處於未更改狀態時才能重新掛接。

我的更新邏輯如下(我對大量的代碼道歉我只是想盡可能清晰):

  bool isNew = false; 
      Farm farm; 

      // Insert or update logic. 
      if (viewModel.Farm.FarmId.Equals(Guid.Empty)) 
      { 
       farm = new Farm 
       { 
        FarmId = Guid.NewGuid(), 
        RatingSum = 3, 
        RatingVotes = 1 
       }; 
       isNew = true; 
      } 
      else 
      { 
       farm = this.ReadWriteSession 
         .Single<Farm>(x => x.FarmId == viewModel.Farm.FarmId); 

      } 

      // Edit/Add the properties. 
      farm.Name = viewModel.Farm.Name; 
      farm.Owner = viewModel.Farm.Owner; 
      farm.Address = viewModel.Farm.Address; 
      farm.City = viewModel.Farm.City; 
      farm.Zip = viewModel.Farm.Zip; 
      farm.WebAddress = viewModel.Farm.WebAddress; 
      farm.PhoneNumber = viewModel.Farm.PhoneNumber; 
      farm.Hostel = viewModel.Farm.Hostel; 
      farm.Details = viewModel.Farm.Details; 
      farm.Latitude = viewModel.Farm.Latitude; 
      farm.Longitude = viewModel.Farm.Longitude; 
      farm.Weather = viewModel.Farm.Weather; 

      // Add or update the crops. 
      string[] cropIds = Request.Form["crop-token-input"].Split(','); 
      List<Crop> allCrops = this.ReadWriteSession.All<Crop>().ToList(); 

      if (!isNew) 
      { 
       // Remove all previous crop/farm relationships. 
       farm.Crops.Clear(); 
      } 

      // Loop through and add any crops. 
      foreach (Crop crop in allCrops) 
      { 
       foreach (string id in cropIds) 
       { 
        Guid guid = Guid.Parse(id); 
        if (crop.CropId == guid) 
        { 
         farm.Crops.Add(crop); 
        } 
       } 
      } 

      if (isNew) 
      { 
       this.ReadWriteSession.Add<Farm>(farm); 
      } 
      else 
      { 
       this.ReadWriteSession.Update<Farm>(farm); 
      } 
      this.ReadWriteSession.CommitChanges(); 

的ReadWriteSession內我的更新代碼很簡單足夠(GetSetName<T>只返回從它的類型名稱是的PropertyInfo。):

/// <summary> 
    /// Updates an instance of the specified type. 
    /// </summary> 
    /// <param name="item">The instance of the given type to add.</param> 
    /// <typeparam name="T">The type of entity for which to provide the method.</typeparam> 
    public void Update<T>(T item) where T : class, new() 
    { 
     this.context.AttachTo(this.GetSetName<T>(), item); 
     this.context.ObjectStateManager.ChangeObjectState(item, EntityState.Modified); 
    } 

回答

4

你加入現有Crop對象(從allCrops列表)新Farm。當您將新實體連接到現有實體時,新實體會自動附加到上下文。因此,當您嘗試第二次將Farm附加到上下文時會出現錯誤。

在你的代碼的Add<Farm>(farm)聲明甚至沒有必要將Farm連接到環境中,如果您有從上下文加載現有Farm,它已經被附加到上下文。

您的整個if (isNew)聲明是不必要的。實體框架跟蹤對象狀態本身,所以你不需要設置修改後的狀態。

+0

大斯科特!你是對的!這太棒了!乾杯! – 2011-04-03 13:24:40

3

您不必在最後附加「農場」對象,因爲當您更改其某個屬性時,它已經作爲修改被附加。嘗試在除去末端else語句:

if (isNew) 
{ 
    this.ReadWriteSession.Add<Farm>(farm); 
} 

希望這有助於:)

+0

如果可以標記多個答案,我會。無論如何,我已經贊成你們了......我想你被毆打了大約30秒。謝謝! – 2011-04-03 13:26:02

+0

沒問題,很高興它爲你工作;) – AbdouMoumen 2011-04-03 13:27:54

2

的問題是在你的更新方法。您無法附加Farm實例,因爲您已從相同的上下文中加載該實例,因此它已連接,因此根本無需調用Update,因爲會自動跟蹤附加對象的更改。

+0

如果可以標記多個答案,我會。無論如何,我已經贊成你的......謝謝! – 2011-04-03 13:25:33