Трудно понять, как работать с отношениями «многие ко многим» в MVC2 / EF4 - PullRequest
3 голосов
/ 10 ноября 2010

Я писал об этом несколько раз, но до сих пор не могу понять, как работать со связями «многие ко многим» в MVC2 с EF4, особенно когда речь идет о функциональности «Создание и редактирование».Я думаю, что часть моей проблемы заключается в том, что я решил создать свои таблицы базы данных таким образом, чтобы сводные таблицы не были видны в самой модели.

Мои таблицы, еще раз:

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, так как я просто пытаюсь связать игру, которую я просмотрел, с уже существующими платформами.Работа с ним на уровне ООП сбивает меня с толку, поскольку я продолжаю думать, что добавляю в Платформы, когда все, что я действительно хочу сделать, это связать идентификатор Игр с различными идентификаторами Платформ.

Так что я нехочу создать новую платформу из входящих данных HTTP-Post.Я просто хочу иметь возможность взять данные формы и создать новую игру, новый обзор содержимого и связать новую игру с существующими платформами на основе выбранных флажков.

Я понимаю, как выполнять первые две задачи.Это связь, которую я не могу понять.

Извиняюсь за то, что продолжаю говорить об этом, но на самом деле это единственное, что удерживает меня от значительного прогресса.

1 Ответ

1 голос
/ 10 ноября 2010

Если вы правильно сопоставили это в структуре сущностей, и у вашего игрового объекта есть коллекция платформ, то назначение существующих платформ игре должно быть таким же простым, как передача идентификаторов этих платформ в действие добавления / редактирования игры.

В вашей форме вы можете использовать серию флажков с атрибутом значения PlatformID и одним общим именем, например «platformids». Обратите внимание, что Html.CheckBox() HtmlHelper не имеет параметра для «значения», поэтому вам придется указать его с помощью объекта 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() выше - это просто хороший способ создать SQL-эквивалент SELECT * FROM TABLE WHERE ID IN(1,2,3,4,5,...).

...