【问题标题】:How can I convert a string to a BigInt in an action parameter?如何在操作参数中将字符串转换为 BigInt?
【发布时间】:2012-04-14 06:21:51
【问题描述】:

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

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

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

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

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));

【问题讨论】:

  • 如果值是字符串,则无需再次调用ToString()。但是您提到当您尝试使用没有前导零的资源时遇到错误。这是什么错误?我认为你不应该在那里使用Long ..也许这是格式化参数添加零的问题..你能显示你尝试时遇到的错误吗?
  • @MilkyWayJoe 对不起,当我输入不带前导零的学生 ID 时,我没有收到错误消息,它没有显示任何结果。我必须准确输入“00003345”
  • 那么您为什么不尝试在您的操作中添加缺失的零呢? (在动作中,但 before 您将参数传递给查询)或者在渲染视图时(在 get 动作上)添加零?
  • @MilkyWayJoe 另外,当我将 StudentID 参数更改为“Int64”而不是“string”时,我正在调用 ToString()。将参数类型更改为“Int64”后,如果我不调用 ToString(),它会给出错误:Delegate 'System.Func' does not take one argument on: s => s .StudentID == StudentID);
  • 你去......人们正在回答我告诉你的内容:P

标签: c# asp.net-mvc


【解决方案1】:

以下是否有效?

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();
}

【讨论】:

  • @Yamen 有没有办法解决存储在同一列中没有前导零的数字?我应该如何处理显示未用前导零填充的数字?
  • 是的,在底层 SQL 中,您将希望最终查询查找 StudentId LIKE '%9999',因此在 LINQ .Where(s => s.StudentId.EndsWith(StudentID) 中。当然,您随后可以获得多个结果,您需要搜索完全匹配的结果。
  • @yamen 是的,EndsWith 会起作用,但并非总是如此,需要找到一种解决方案来仅显示输入的学生的输出
  • OK 添加了一个最终选项,用于构建所有可能的学生 ID 组合,并使用 Contains(SQL IN 运算符)检查所有组合是否完全匹配。
  • @yamen 您的查询仍将显示所有可能的学生。例如:如果学生 id 是 0022323 和 2323,它将同时显示
【解决方案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) );
}

【讨论】:

  • StudentId 不是 9 的固定长度
  • 我对您的问题的理解是,它被存储为带有前导零的固定长度字符串。无论您的固定长度有多长,您都可以替换 9。
  • @EthanBrown 它的长度不同。我应该通过将 StudentId 列设为固定长度来解决它吗?
  • 我认为这将是明智的......如果你正在做字符串相等,003 不同于 03 不同于 3,所以除非底层存储能够将其转换为数字形式之前进行比较,我认为您最好使用固定宽度。最好将学生 ID 存储为数字,而不是字符串。
  • @EthanBrown 更改表中的数据类型不是我的权限,但是我会尝试与这里的数据库人员交谈。我非常怀疑他们会更改任何数据类型。因此,想要一个我可以控制的替代解决方案。
【解决方案3】:

如果您的数据库包含一个大整数,而您发送的数据更小……您将得到一个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();
}

或稍微干燥:

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 );
}

【讨论】:

    【解决方案4】:

    这是一个有趣的问题。如果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(); 
    } 
    

    不过,我不确定这会增加多少价值。

    【讨论】:

    • 有没有办法解决存储在同一列中没有前导零的数字?此列的学生 ID 带有前导零,有些没有前导零。因此,我希望将字符串转换为 bigint,这将解决所有问题,但在尝试了几种方法后,我仍然无法将字符串转换为 bigint。我应该如何处理显示未用前导零填充的数字?
    • 我见过类似的情况。唯一的解决方案是每次查询数据库时将生成的列值转换为 bigint。如果将该列用作外键,则可能会特别麻烦。最终,选择填充或将列转换为 bigint 符合您的长期利益,我的偏好是 bigint(您始终可以添加填充以进行显示)。
    • 我想我并没有真正回答你的问题,你所追求的是一种查询所有可能的填充组合在哪里返回的方法?
    • 是的,我想返回所有的填充组合,即使是那些没有填充的。
    【解决方案5】:

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

    我能够通过强制转换我的 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);
    

    【讨论】:

      猜你喜欢
      • 2016-08-18
      • 1970-01-01
      • 2012-08-02
      • 2015-05-07
      • 2015-06-02
      • 1970-01-01
      • 2018-07-14
      • 2015-04-11
      • 1970-01-01
      相关资源
      最近更新 更多