2010-11-10 41 views
3

我已經寫了幾次工作,但我仍然有困難,看到如何在MVC2與EF4許多一對多的關係的工作特別是當涉及到創建和編輯功能時。我認爲我的問題的一部分是,我決定創建我的數據庫表,使數據透視表在模型本身中不可見。有困難看到如何在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透視表,因爲我只是要連結的比賽,我要檢討已經存在的平臺。在OOP級別處理它讓我感到困惑,因爲我一直認爲自己正在添加到平臺,而當我真正想要做的就是將遊戲的ID與各種Platform ID相關聯。

所以,我不希望創建從傳入的HTTP-POST數據的新平臺。我只是希望能夠獲取表單數據並創建新遊戲,新評論內容,並根據選定的複選框將新遊戲鏈接到現有平臺。

我明白瞭如何執行前兩項任務。這是我無法理解的聯繫。

道歉繼續喋喋不休這一點,但它是真正的一件事情拖我作出顯著的進展。

回答

1

假設你已經在正確的實體框架映射這和你的遊戲對象有一個平臺集合,然後分配現有平臺的遊戲應儘可能通過這些平臺的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()只是創建SQL相當於SELECT * FROM TABLE WHERE ID IN(1,2,3,4,5,...)一個很好的方式。

+0

哇,真好!有點超出了我目前C#/ MVC技能的水平,但我想我知道你要去哪裏。對於編輯,有沒有辦法可能刪除現有的鏈接?假設我不小心將遊戲標記爲DS標題而不是Wii標題,並且想要修復該錯誤。如有必要,是否有辦法刪除現有鏈接? – 2010-11-10 21:17:03

+1

當然,使用與上面相同的邏輯,當您創建您的平臺列表以從預選中檢查已經分配的平臺時。當控制器處理表單時,從Game對象中清除所有現有的平臺,併爲所有檢查的PlatformID創建新的平臺。我通常處理這個的方式是使用while循環:while(game.Platforms.Any()){game.Platforms.Remove(game.Platforms.First()); }'。根據我的經驗,調用EntityCollection.Clear()會導致集合被清空,但實際上並沒有從數據存儲中刪除關聯的實體。 – 2010-11-10 22:36:48

+0

謝謝!這讓我堅持了幾天,所以要接近一個可行的解決方案,這樣突然變得非常難以置信。再次感謝! – 2010-11-10 22:49:53