我一直在努力让EF4与MVC 2项目合作约六个月。这是一种折磨活动。尝试做任何非平凡的事情都需要玩杂耍的EntityKeys,做ObjectContext附加/分离舞蹈,并且,实际上,试图根据模糊的,几乎没有帮助的异常消息来实现必要的黑魔法。说它令人沮丧的是一个巨大而巨大的轻描淡写。
所以,放弃一边,这是我的问题:我有一个有点复杂的模型,我正在尝试通过表单创建/编辑。虽然大多数数据都是简单的标量,但也存在一些多对多数据。该网站将成为(如果我完成...)一个视频游戏评论网站。因此,多对多关系是游戏和它们可用的平台之间的关系(XBox 360,PS3等)。通过复选框选择平台,每个复选框与特定的平台ID相关联。
为了尝试以正确的方式做事,我在将数据传输到实际的Game和Platform实体之前绑定到编辑模型。传输数据后,我在我的存储库上调用我的Save方法,这实际上只是我的ObjectContext的包装器。
public void SaveGame(Game game)
{
_siteDB.Games.Attach(game);
if (game.GameID > 0)
{
_siteDB.ObjectStateManager.ChangeObjectState(game, System.Data.EntityState.Modified);
}
else
{
_siteDB.ObjectStateManager.ChangeObjectState(game, System.Data.EntityState.Added);
}
_siteDB.SaveChanges();
}
现在,我的Attach语句遇到了错误。离开它的地方,我得到一个异常,告诉我ObjectContext无法跟踪具有相同EntityKey的两个实体。如果我删除它,我会得到一个异常,告诉我游戏需要一个EntityKey。我尝试过使用ApplyCurrentValues
,但是在尝试添加平台时遇到了类似的问题。
最终,似乎有一种特定的模式可以用来使这样的东西起作用。我似乎可以发现它是什么,而且非常令人沮丧。我只是看不到一个解决方案,它不需要我炸毁我的UI和后端之间的分离。
有人能指出我正确的方向吗?是否有任何MVC / EF4教程可以处理比着名的demoware示例更复杂的事情?
编辑:在以下方面取得了一些进展:
public void SaveGame(Game game)
{
if (game.GameID > 0)
{
var editedGame = this.GetGame(game.GameID);
var eSet = editedGame.EntityKey.EntitySetName;
_siteDB.ApplyCurrentValues(eSet, game);
var existingPlats = editedGame.Platforms.ToArray();
foreach (var plat in existingPlats)
{
editedGame.Platforms.Remove(plat);
}
var newPlats = game.Platforms.ToArray();
foreach (var nPlat in newPlats)
{
editedGame.Platforms.Add(nPlat);
}
game = null;
_siteDB.ObjectStateManager.ChangeObjectState(editedGame, System.Data.EntityState.Modified);
}
else
{
_siteDB.Games.AddObject(game);
}
_siteDB.SaveChanges();
}
我现在唯一的问题是它将game
添加到ObjectContext,即使我将其设置为null。所以,我的现有实体更新正常,但我也将一个新的镜像实体插入到数据库中。
答案 0 :(得分:2)
问题是您在上下文中已经有Game
具有相同ID。您不能拥有两个具有相同ID的对象。
如何进入该状态首先是您未显示的代码功能。但是,让我们谈谈解决你当前的问题。您可以采取两种方法:
您可以选择适合您的那个,但这里的基本问题是您在内存中有两个不同的实例具有相同的GameID
值 ,那很糟糕。