繁体   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