【发布时间】:2012-01-13 09:49:31
【问题描述】:
场景:
我有 3 个表,它们形成了多对多关系:
Agent (AgentID (PK), AgentName)
AgentChannel (AgentID (PK), ChannelID (PK))
Channel (ChannelID (PK), ChannelName)
我不想在 Agent 和 Channel 表中添加/删除任何记录,而只想修改 AgentChannel 表。
我正在使用 EF 4.1、POCO 和自我跟踪实体。所有处理数据库的代码都包含在 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 无法继续,因为对象的键值与 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;
}
然后我收到异常消息:
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:
我希望我说清楚。这是我现在面临的唯一问题,我没有想法。
非常感谢。
-
-
更新 - 回答
根据 Ladislav 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
【问题讨论】:
标签: entity-framework-4.1 many-to-many ef-code-first