很难看到如何在MVC2 / EF4中使用多对多关系

时间:2010-11-10 20:21:56

标签: asp.net-mvc-2 entity-framework-4 many-to-many

我已经写过这几次了,但是我仍然很难看到如何使用EF4在MVC2中处理多对多关系,特别是在创建和编辑功能方面。我认为我的问题的一部分是我决定创建我的数据库表,使得数据透视表在模型本身中不可见。

我的桌子,再一次:

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数据透视表中添加条目,因为我只是想将我评论的游戏链接到现有的平台。在OOP级别处理它让我感到困惑,因为我一直在想我正在添加到平台,当我真正想要做的就是将游戏的ID链接到各种平台ID。

所以,我不想从传入的HTTP-Post数据创建一个新的平台。我只是希望能够获取表单数据并创建新游戏,新评论内容,并根据所选复选框将新游戏链接到现有平台。

我理解如何执行前两个任务。这是我似乎无法掌握的联系。

抱怨继续竖起这个,但这实际上是阻止我取得重大进展的一件事。

1 个答案:

答案 0 :(得分:1)

假设您已在实体框架中正确映射此对象并且您的Game对象具有Platforms集合,则将现有平台分配给游戏应该就像将这些平台的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 * FROM TABLE WHERE ID IN(1,2,3,4,5,...)的SQL的好方法。