2012-01-13 59 views
0

的情況下刪除:實體框架4.1 - 在錯誤很多,一對多的關係數據時插入數據以前

3個表我有形成許多一對多的關係:

Agent (AgentID (PK), AgentName) 
AgentChannel (AgentID (PK), ChannelID (PK)) 
Channel (ChannelID (PK), ChannelName) 

我不想在代理和通道表中添加/刪除任何記錄,但只修改AgentChannel表。

我使用EF 4.1,POCO和Self-Tracking Entity。所有處理數據庫的代碼都包含在WCF層中,我稱之爲服務器端代碼,並且我只能控制客戶端代碼中記錄的添加/刪除。

例如: 我有一個代理記錄,有多個通道記錄。我能現有的渠道以這種方式鏈接到代理:

var channel = new Channel { ChannelID = 1 }; 
channel.MarkAsUnchanged(); 
agent.Channels.Add(channel); 
// This will add new entry to AgentChannel table, but no change on Agent and Channel tables 

我也可以刪除通道的聯動代理這樣:

var tempChannels = agent.Channels.ToList(); 
var channelToDelete = tempChannels.FirstOrDefault(c => c.ChannelID == 3); 
agent.Channels.Remove(channelToDelete); 
// This will remove the entry in AgentChannel, but no change on Agent and Channel tables. 



我的問題:
如果我刪除了一個頻道,並將具有與先前刪除的頻道相同的ChannelID的新頻道添加到agent.Channels集合中,我將得到此錯誤:

AcceptChanges cannot continue because the object’s key values conflict with another object in the ObjectStateManager.

示例代碼演示功能:

 // 
     // I not able to call ObjectContext here because it was reside in server side. 
     // 

     // 
     // This is client side code 
     // 
     var tempChannels = agent.Channels.ToList(); 
     var channelToDelete = tempChannels.FirstOrDefault(c => c.ChannelID == 3); 

     // remove channel 3 
     agent.Channels.Remove(channelToDelete); 

     var channel = new Channel { ChannelID = 3 }; 
     channel.MarkAsUnchanged(); 

     // Add back channel 3 
     agent.Channels.Add(channel); 

     // 
     // This is server side code (WCF layer) 
     // 
     try 
     { 
      using (var ctx = new testEntities()) 
      { 
       ctx.ApplyChanges("Agents", agent); // <-- ERROR happen here 
       ctx.SaveChanges(); 
      } 
     } 
     catch (Exception) 
     { 
      throw; 
     } 

後來我thie異常消息:

System.InvalidOperationException was unhandled 
    Message=AcceptChanges cannot continue because the object's key values conflict with another object in the ObjectStateManager. Make sure that the key values are unique before calling AcceptChanges. 
    Source=System.Data.Entity 
    StackTrace: 
     at System.Data.Objects.ObjectStateManager.FixupKey(EntityEntry entry) 
     at System.Data.Objects.EntityEntry.AcceptChanges() 
     at System.Data.Objects.EntityEntry.ChangeObjectState(EntityState requestedState) 
     at System.Data.Objects.ObjectStateManager.ChangeObjectState(Object entity, EntityState entityState) 
     at TestManyToMany.SelfTrackingEntitiesContextExtensions.ChangeEntityStateBasedOnObjectState(ObjectContext context, IObjectWithChangeTracker entity) in F:\MyFile\Development\Temp\TestManyToMany\TestManyToMany\Model1.Context.Extensions.cs:line 728 
     at TestManyToMany.SelfTrackingEntitiesContextExtensions.HandleEntity(ObjectContext context, EntityIndex entityIndex, RelationshipSet allRelationships, IObjectWithChangeTracker entity) in F:\MyFile\Development\Temp\TestManyToMany\TestManyToMany\Model1.Context.Extensions.cs:line 596 
     at TestManyToMany.SelfTrackingEntitiesContextExtensions.ApplyChanges[TEntity](ObjectContext context, String entitySetName, TEntity entity) in F:\MyFile\Development\Temp\TestManyToMany\TestManyToMany\Model1.Context.Extensions.cs:line 84 
     at TestManyToMany.Program.Main(String[] args) in F:\MyFile\Development\Temp\TestManyToMany\TestManyToMany\Program.cs:line 53 
     at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 
     at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 
     at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
     at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
     at System.Threading.ThreadHelper.ThreadStart() 
    InnerException: 

我希望我說清楚了。這是我現在面臨的唯一問題,我用完了主意。

非常感謝。

-


-

更新 - 回答

我得到了答案做根據從拉吉斯拉夫Mrnka評論的測試後。

基本上你需要添加回到先前刪除的同一個實體,沒有其他實體,因爲這會給你上面的同樣的錯誤。

這裏是客戶端上的示例代碼,不改變服務器側需要:

 int channelId = 1; 

     var tempChannels = agent.Channels.ToList(); 
     var channelToDelete = tempChannels.FirstOrDefault(c => c.ChannelID == channelId); 

     // remove channel 1 
     agent.Channels.Remove(channelToDelete); 


     //var channel = _allChannels.First(c => c.ChannelID == channelId); 
     //agent.Channels.Add(channel);   <-- This line will give you ERROR because the channel entity is from _allChannels, but not from agent.Channels 

     // Add back channel 1 
     agent.Channels.Add(channelToDelete); // <-- This is CORRECT 

回答

0

即是不允許的操作。如果您刪除了頻道並且想要再次添加頻道,則不得創建新的實例。你必須使用舊的,只改變它的狀態。主要規則是每個具有唯一鍵的實體只能聲明一次。您的代碼導致出現兩個具有相同key =錯誤的實例。

+0

謝謝,它現在的工作!我想我錯過了來自母公司實體的測試!我會在我的問題中更新我的發現。再次感謝 ! – tzuhsun 2012-01-16 01:56:16