2011-04-03 79 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