的情況下刪除:實體框架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
謝謝,它現在的工作!我想我錯過了來自母公司實體的測試!我會在我的問題中更新我的發現。再次感謝 ! – tzuhsun 2012-01-16 01:56:16