如何在动作参数中将字符串转换为BigInt?

时间:2012-04-11 23:31:15

标签: c# asp.net-mvc

我有一个我要显示的视图,我有一个接受字符串(StudentID)的控制器。这是我的控制器动作:

public ActionResult ShowStudent(string StudentID)
{
    ViewData.Model = student.vwStudent.Where(s => s.StudentID == StudentID);
    return View();
}

现在,StudentId在其中有前导零。例如00003345,000000223等 因此,要显示特定学生的视图,我必须在网址中输入确切的字符串“00003345”:“http:// Students / ShowStudent / 00003345”即使我输入“我希望能够显示视图” 3345“在网址:”http:// Students / ShowStudent / 3345“但我收到错误。

我尝试传递Long(Int64)参数而不是字符串,并将ViewID转换为ViewData.Model中的String,如:

ViewData.Model = student.vwStudent.Where(s => s.StudentID == StudentID.ToString());

但是我收到了一个错误:

  

LINQ to Entities无法识别方法'System.String ToString()'方法,并且此方法无法转换为商店表达式。

编辑: 将它解析为Int64是有什么问题的:

ViewData.Model = student.vwStudent.Where(s => Int64.Parse(s.StudentID) == Int64.Parse(StudentID));

5 个答案:

答案 0 :(得分:4)

以下是否有效?

public ActionResult ShowStudent(string StudentID)
{
    var padded = StudentID.PadLeft(8, '0');
    ViewData.Model = student.vwStudent.Where(s => s.StudentID == padded);
    return View();
}

或者,如果StudentID并不总是添加到8个字符,则可能必须使用基础SQL LIKE运算符查询所有可能的StudentID:

var students = student.vwStudent.Where(s => s.StudentID.EndsWith(StudentID));

然后循环搜索这些结果,寻找合适的匹配。

最后,如果您希望仅使用基础SQL IN运算符将所有可能的匹配发送到查询以获得完全返回:

public ActionResult ShowStudent(string StudentID)
{
    var possibleStudents = Enumerable.Range(StudentID.Length, 8 - StudentID.Length).Select(l => StudentID.PadLeft(l, '0'));
    ViewData.Model = student.vwStudent.Where(s => possibleStudents.Contains(s.StudentID));
    return View();
}

答案 1 :(得分:2)

如果你的数据库拥有一个大的int,并且你发送的东西更小......你得到的是stack overflow。您需要将该字符串解析为有用的东西:

ViewData.Model = student.vwStudent.Where(s => s.StudentID == long.Parse(StudentID));

然而,这似乎不是问题(即使问题明确指出"如何将字符串转换为大型字符串")。

根据您的说明(StudentId's have leading zeros in them)和您的评论I have to enter it exactly "00003345"我将假设此方法需要一些逻辑。另一方面,我不太确定,因为你的问题表明StudentIds的长度不同。 ?!

public ActionResult ShowStudent(string StudentID)
{
 while( StudentID.Length < 8 )
 {
  StudentID = "0" + StudentID;
 }
 ViewData.Model = student.vwStudent.Where(s => s.StudentID == StudentID);
 return View();
}

或者更有趣:

public ActionResult ShowStudent(string StudentID)
{
 var x = student.vwStudent.Where(s => s.StudentID == StudentID).FirstOrDefault();
 while( x != null && StudentID.Length < 15)
 {
  StudentID = "0" + StudentID;
  x = student.vwStudent.Where(s => s.StudentID == StudentID).FirstOrDefault();
 }
 ViewData.Model = x;
 return View();
}

或稍微DRYer:

public ActionResult ShowStudent(string StudentID)
{
    Student s;
    while( (s=students.FirstOrDefault( x => x.StudentId == StudentId )) == null ) {
        StudentId = "0" + StudentId;
        if( StudentId.Length > 15 ) break;
    }

    return View( s );
}

答案 2 :(得分:2)

LINQ需要能够将所有函数转换为底层数据存储,这可能就是您收到该错误消息的原因。但是,如果我正确理解您的问题,您应该能够通过以下方式完成您正在寻找的问题:

public ActionResult ShowStudent(long studentId)
{
    var studentIdStr = studentId.ToString( "D9" );  // 9-digit number, padded w/ zeros
    ViewData.Model = student.vwStudent.Where(s => s.StudentId == studentIdStr);
    return View();
}

顺便说一下,将模型传递给视图的标准方法不是设置ViewData.Model,而是将其传递给View方法:

public ActionResult ShowStudent(long studentId)
{
    var studentIdStr = studentId.ToString( "D9" );  // 9-digit number, padded w/ zeros
    return View( student.vwStudent.Where(s => s.StudentID == studentIdStr) );
}

答案 3 :(得分:1)

这是一个有趣的问题。如果StudendID与前导零一起存储,那么任何内置的MVC函数都将构造具有相同值的URL(意思是前导零)。但您可以更改Controller方法以获取字符串,然后将其转换为Int64,然后使用.PadLeft()自行添加零,并且模型绑定仍然有效。

public ActionResult ShowStudent(string StudentID) 
{ 
    string paddedStudentID = Convert.ToInt64(StudentID).ToString().PadLeft(9, '0');
    ViewData.Model = student.vwStudent.Where(s => s.StudentID == paddedStudentID); 
    return View(); 
} 

我不确定这会增加很多价值。

答案 4 :(得分:0)

感谢大家的帮助,我提出了一些建议并找到了适合我的解决方案。

我能够通过在我的SQL中强制转换来解决这个问题:

CAST(CAST(StudentID AS bigint) AS nvarchar(33)) AS StudentID 

然后在我的控制器中转换它:

var StudentID = Convert.ToString(Int64.Parse(StudentId));

ViewData.Model = student.vwStudent.Where(a => a.StudentID == StudentId);