Asp.net mvc 2 在MVC2/EF4中难以理解如何处理多对多关系
关于这一点我已经写过几次了,但是我仍然很难理解如何在MVC2和EF4中处理多对多关系,特别是在创建和编辑功能时。我认为我的问题的一部分是,我决定以这样一种方式创建数据库表,即透视表在模型本身中不可见 我的桌子,再一次:Asp.net mvc 2 在MVC2/EF4中难以理解如何处理多对多关系,asp.net-mvc-2,entity-framework-4,many-to-many,Asp.net Mvc 2,Entity Framework 4,Many To Many,关于这一点我已经写过几次了,但是我仍然很难理解如何在MVC2和EF4中处理多对多关系,特别是在创建和编辑功能时。我认为我的问题的一部分是,我决定以这样一种方式创建数据库表,即透视表在模型本身中不可见 我的桌子,再一次: Games: int GameID (primary key, auto-incr) string GameTitle string ReviewTitle int Score int ReviewContentID (foreign key fro
Games:
int GameID (primary key, auto-incr)
string GameTitle
string ReviewTitle
int Score
int ReviewContentID (foreign key from Content - News, Articles, and Game reviews all have similar content requirements)
int GenreID (foreign key from Genres)
Platforms:
int PlatformID (primary key, auto-incr)
string Name
GamePlatform (not visible in model):
int GameID (foreign key from Games)
int PlatformID (foreign key from Platforms)
当我创建一个新的评论时,我真的只想在GamePlatform透视表中添加条目,因为我只是试图将我评论的游戏链接到现有的平台。在面向对象的层次上处理它让我感到困惑,因为我一直认为我在添加平台,而我真正想做的就是将游戏id链接到各种平台id
因此,我不想从传入的HTTPPOST数据创建新的平台。我只希望能够获取表单数据,创建新游戏、新评论内容,并根据选中的复选框将新游戏链接到现有平台
我了解如何执行前两项任务。这是我似乎无法理解的联系
抱歉继续唠叨这个,但这确实是阻碍我取得重大进展的一件事。假设您已在实体框架中正确映射此内容,并且您的游戏对象具有平台集合,则将现有平台分配给游戏应该非常简单,只需将这些平台的ID传递给您的游戏添加/编辑操作即可 在表单中,您可以使用一系列复选框,这些复选框的值属性为PlatformID,并使用一个通用名称,例如“platformids”。注意,Html.CheckBox HtmlHelper没有“value”的参数,因此您必须通过htmlAttributes对象来指定它。MVC的默认模型绑定器将通过向接收操作添加匹配参数,自动将表单中的“platformid”值集合分组到单个类型的IEnumerable中 以下是一些让您开始学习的代码:
// games controller
public action AddGame(Game newGame, int[] platformIds) {
Platforms[] platforms;
if(platFormIds != null && platformIds.Any()) {
platforms = ObjectContext.Platforms.Where(ExpressionExtensions.BuildOrExpression<Platform, int>(p => p.PlatformID, platformIds)).ToList();
}
if(ModelState.IsValid()) {
game.Platforms.AddRange(platforms);
ObjectContext.AddToGames(game);
ObjectContext.SaveChanges();
}
}
// helper class
public static Expression<Func<TElement, bool>> BuildOrExpression<TElement, TValue>(Expression<Func<TElement, TValue>> valueSelector, IEnumerable<TValue> values) {
if (valueSelector == null) throw new ArgumentNullException("valueSelector");
if (values == null) throw new ArgumentNullException("values");
ParameterExpression p = valueSelector.Parameters.Single();
if (!values.Any())
return e => false;
IEnumerable<Expression> equals = values.Select(value => (Expression)Expression.Equal(valueSelector.Body, Expression.Constant(value, typeof(TValue))));
Expression body = equals.Aggregate(Expression.Or);
return Expression.Lambda<Func<TElement, bool>>(body, p);
}
注意:上面的BuildOrExpression只是一种很好的方法,可以创建相当于SELECT*的SQL,从表中,ID为1,2,3,4,5,…。Wow,不错!有点超出了我目前的C/MVC技能水平,但我想我看到了你的发展方向。对于编辑,是否有可能删除现有链接的方法?比如说我不小心把一款游戏标为DS游戏而不是Wii游戏,我想纠正这个错误。如果有必要,是否有办法删除现有链接?当然,当您创建平台列表以从预检已分配的平台中进行选择时,请使用与上述相同的逻辑。当控制器处理表单时,从游戏对象中清除所有现有平台,并为所有选中的平台创建新平台。我通常处理这个问题的方法是使用while循环:whilegame.Platforms.Any{game.Platforms.Removegame.Platforms.First;}。根据我的经验,调用EntityCollection.Clear会导致集合清空,但实际上不会从数据存储中删除关联的实体。非常感谢!这已经让我发疯好几天了,所以如此突然地接近一个有效的解决方案是难以置信的。再次感谢!