在C#MVC 4中使用Linq的where子句

时间:2014-03-25 03:22:18

标签: c# entity-framework lambda

我正在尝试从我的UserProfile表中选择一个字段RoleID。传递给此Post方法的参数是Username,它是文本框中正常工作的字符串。

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult GetRoles(string UserName)
    {
        if (!string.IsNullOrWhiteSpace(UserName))
        {
             string applyfor = db.Profiles
               .Select(s => s.RoleID)
               .Where(a=>Profile.UserName.Contains(UserName))
               .First();
             ViewBag.ApplyingFor = applyfor;

然而,这给了我序列不包含任何元素。

我尝试了其他几种方法,例如.Equals()。我很确定这是我的where子句。

我在这里做错了什么?

注意:RoleID不是Websecurity的一部分,数据库中也有数据。

3 个答案:

答案 0 :(得分:5)

如果您分解代码并突出显示每个Lambda语句返回的内容,您将看到问题:

string applyfor = db.Profiles
                     ^^^^^^^^

这很可能会返回DbSet<Profile>

之类的内容
  .Select(s => s.RoleID)
   ^^^^^^

这很可能会返回IQueryable<int>。此时您已丢失了配置文件的上下文,现在只有零个或多个RoleID s。

所以你在where语句中的a是一个int值,你现在无法找到一个用户名,而这个where语句根本没有意义。

  .Where(a=>Profile.UserName.Contains(UserName))

当您将Lambda表达式重新排列为Grant Winney's Answer shows时,您可以看到为什么Select()在大多数情况下通常发生的最后事情(在简单查询中)。

我敢打赌UserName上没有Profile。你想要

string applyfor = db.Profiles
                    .Where(p => p.User.Any(u.UserName == UserName))
                    .Select(p => p.RoleID)
                    .First();

作为旁注,Microsoft最佳做法是Camel-Case method parameters。所以我建议你的方法如下:

public ActionResult GetRoles(string userName) // or username
{
}

答案 1 :(得分:2)

你的Where声明应该看起来更像这样:

 ... .Where(a => a.UserName == Profile.UserName).FirstOrDefault();

答案 2 :(得分:2)

请改为尝试:

string applyfor = db.Profiles
                    .Where(x => x.UserName == UserName)
                    .Select(x => x.RoleID)
                    .First();

此外,如果您有可能找不到匹配的记录,请使用FirstOrDefault()代替.First(),然后测试null