簡體   English   中英

避免過多的控制流與MVC中的ID數組一起使用

[英]Avoiding excessive control flow working with Id arrays in MVC

MVC中的多選列表似乎沒有綁定到復雜的模型。 相反,它們返回選定ID號的數組。

我在頁面上有這樣的控件,而讓我不得不部署大量條件邏輯才能使我感到煩惱。 有問題的對象是一個Staff對象,可以擁有一個或多個團隊的TeamMember成員身份。

我的對象來自實體框架。 我將此添加到Staff對象:

public int[] SelectedTeamMembers
{
    get; set;
} 

現在,我可以在視圖中綁定到該屬性,用戶可以編輯多選列表。 在發回編輯表單時,我必須這樣做(為清楚起見添加了注釋):

//user.TeamMembers not bound, so get existing memberships
IEnumerable<TeamMember> existingTeamMembers = rep.TeamMembers_Get().Where(t => t.UserId == user.UserID);

//if array is empty, remove all team memberships & avoid null checks in else
if(user.SelectedTeamMembers == null)
{
    foreach(TeamMember tm in existingTeamMembers)
    {
        rep.TeamMembers_Remove(tm);
    }
}
else
{
    // if team members have been deleted, delete them
    foreach (TeamMember tm in existingTeamMembers)
    {
        if (!user.SelectedTeamMembers.Contains(tm.TeamId))
        {
            rep.TeamMembers_Remove(tm);
        }
    }

    // if there are new team memberships, add them
    foreach (int i in user.SelectedTeamMembers)
    {
        if (!existingTeamMembers.Select(t => t.TeamId).Contains(i))
        {
            TeamMember tm = new TeamMember { TeamId = i, UserId = user.UserID };
            rep.TeamMembers_Change(tm);
        }
    }
}

當然,我可以通過將一點點耕種到某個功能上來整理一下,但是仍然感覺像是敲碎堅果的大錘。

有沒有更整潔的方法來實現這一目標?

您應該評估將forforeach循環合並為一個循環的可能性,以此作為簡化此代碼的第一步。

另外,您知道如何使用LINQ(如您的初始Where()語句所證明的),因此也可以使用LINQ及其一些輔助擴展來簡化null條件操作:

//user.TeamMembers not bound, so get existing memberships
IEnumerable<TeamMember> existingTeamMembers = rep.TeamMembers_Get().Where(t => t.UserId == user.UserID);

//if array is empty, remove all team memberships & avoid null checks in else
if(user.SelectedTeamMembers == null)
{
    existingTeamMembers.ToList().ForEach(tm => rep.TeamMembers_Remove(tm));
}
else
{
    // if team members have been deleted, delete them
    existingTeamMembers.Where(tm => !user.SelectedTeamMembers.Contains(tm.TeamId)).ToList().ForEach(tm => rep.TeamMembers_Remove(tm));

    // if there are new team memberships, add them    
    user.SelectedTeamMembers.Except(existingTeamMembers.Select(t=> t.TeamId)).ToList().ForEach(i =>
    {
        TeamMember tm = new TeamMember { TeamId = i, UserId = user.UserID };
        rep.TeamMembers_Change(tm);
    });

}

盡管這並沒有降低條件的復雜性(因為所有條件仍然存在),但語法更具可讀性。

您可以通過這種方式進行操作...它依賴於使用RemoveRange方法。

實體-我將自己用於演示目的

public class User
{

    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }
    public String Name { get; set; }

}

行動

public ActionResult Action(Guid[] selectedTeamMembers)
{



    using (var ctx = new DatabaseContext())
    {

        //
        // Start by targeting all users!
        //
        var usersToRemove = ctx.Users.AsQueryable();

        //
        // if we have specified a selection then select the inverse.
        //
        if (selectedTeamMembers != null)
        {
            usersToRemove = usersToRemove.Where(x => !selectedTeamMembers.Contains(x.Id));
        }


        //
        // Use the Set Generic as this gives us access to the Remove Range method
        //
        ctx.Set<User>().RemoveRange(usersToRemove);


        ctx.SaveChanges();

    }



    return View();
}

希望這可以幫助。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM