2

我试图弄清楚发生了什么,从这个代码导致Cannot perform runtime binding on a null reference错误:MVC5/C# - 无法执行运行时的空引用结合

var query = "SELECT Id, UserName, List_Order, LoggedIn " + 
      "FROM AspNetUsers" + 
      "WHERE LoggedIn = 1" + 
      "ORDER BY List_Order ASC"; 

var conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString); 
var cmd = new SqlCommand(query, conn); 
conn.Open(); 
var rdr = cmd.ExecuteReader(); 
var n = 0; 
while(rdr.Read()) 
{ 
    if (Convert.ToString(rdr["UserName"]) != null) 
    { 
     ViewBag.speakers[n] = new string[4] { 
      Convert.ToString(rdr["Id"]), 
      Convert.ToString(rdr["UserName"]), 
      Convert.ToString(rdr["List_Order"]), 
      Convert.ToString(rdr["LoggedIn"]) 
     }; 

     //Exception Details: Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: Cannot 
     //perform runtime binding on a null reference 
     n++; 
    } 
} 

n++增量似乎是这个错误的原因,并我不明白为什么。

更新代码以反映可能的解决方案。但是,错误仍然存​​在。

具有相同的结果尝试这样做:

if (!string.IsNullOrWhiteSpace(Convert.ToString(rdr["UserName"]))) { 
     List<string> speakers = new List<string>(); 
     speakers.Add(Convert.ToString(rdr["Id"])); 
     speakers.Add(Convert.ToString(rdr["UserName"])); 
     speakers.Add(Convert.ToString(rdr["List_Order"])); 
     speakers.Add(Convert.ToString(rdr["LoggedIn"])); 

     ViewBag.speakers[n] = speakers; 
     n++; 
} 
+0

退房[这个类似的帖子(http://stackoverflow.com/questions/28235162/cannot -perform-runtime-binding-on-a-null-reference-empty-excel-cells) –

+0

@LuisLavieri我更新了代码,错误仍然显示出来。 –

+0

你是否也更新了'if'?现在它应该是:'if(!string.IsNullOrWhiteSpace(Convert.ToString(rdr [“UserName”]))' –

回答

2

有在你的代码的两个问题:

考虑一下:

public ActionResult Index() 
{ 
    int n = 0; 
    ViewBag.speakers[n] = 5; 
    return View(); 
} 

这种简化的一段代码抛出Cannot perform runtime binding on a null reference,因为扬声器未定义(空引用)。

ViewBag.speakers = new List<string>(); 

第二个问题:

ViewBag.speakers[n] = speakers; 

喇叭在你的代码是一个列表,你可能想

您可以通过循环之前在动态 ViewBag定义speakers修复将ViewBag.speakers定义为List<List<string>>,并调用.Add(speakers)而不是使用索引访问(您可能会得到索引超出范围

2

调用上的空列值的.ToString()方法可导致Cannot perform runtime binding on a null reference。改为使用Convert.ToString();如果您尝试转换null值并且不需要额外的代码来检查null,它将返回一个空字符串。

+0

这是一个很好记住的技巧。我会全部使用'possibleNull?.ToString()? string.Empty' – Gusdor

+0

我尝试了'Convert.ToString'方法,但仍然得到相同的错误。 –

+0

@Daniel你已经在某处实例化了'speaker'吗? –

1

是一个动态对象,当您尝试对其属性进行赋值时,null检查将在运行时发生。你会得到这个错误,因为ViewBag.speakers要么是null,要么在尝试使用索引器访问其nth插槽(可能其大小小于n,或者根本没有定义索引器)时抛出异常。在添加元素之前,您应该初始化ViewBag.speakers

var query = "SELECT Id, UserName, List_Order, LoggedIn " + 
      "FROM AspNetUsers" + 
      "WHERE LoggedIn = 1" + 
      "ORDER BY List_Order ASC"; 

var conn = new SqlConnection(System.Configuration.ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString); 
var cmd = new SqlCommand(query, conn); 
conn.Open(); 
var rdr = cmd.ExecuteReader(); 
ViewBag.speakers = new List<string[]>(); 
while(rdr.Read()) 
{ 
    if (Convert.ToString(rdr["UserName"]) != null) 
    { 
     var speakers = new string[4] { 
      Convert.ToString(rdr["Id"]), 
      Convert.ToString(rdr["UserName"]), 
      Convert.ToString(rdr["List_Order"]), 
      Convert.ToString(rdr["LoggedIn"]) 
     }; 
     ViewBag.speakers.Add(speakers); 
    } 
} 
0

你的问题似乎ExecuteReader后来源于Read方法的使用,这使得在某一点上有足够的扔在一边查看运行时绑定的异常动态对象ViewBag.speakers的空引用。

使用DataTable.Load和简单的for循环迭代DataTable内容,我修改格克汗库尔特的答案,这一个:

var query = "SELECT Id, UserName, List_Order, LoggedIn " + 
      "FROM AspNetUsers" + 
      "WHERE LoggedIn = 1" + 
      "ORDER BY List_Order ASC"; 

using (var conn = new SqlConnection(ConfigurationManager.ConnectionStrings["DefaultConnection"].ConnectionString)) 
{ 
    using (var cmd = new SqlCommand(query, conn)) 
    { 
     conn.Open(); 
     var dt = new DataTable(); 
     ViewBag.speakers = new List<string[]>(); 
     var rdr = cmd.ExecuteReader(); 
     dt.Load(rdr); 

     for (int n = 0; n < dt.Rows.Count; n++) 
     { 
      if (!String.IsNullOrWhiteSpace(Convert.ToString(dt.Rows[n]["UserName"]))) 
      { 
       // speakers returns String[4] array instead of null value 
       var speakers = new String[4] { 
        Convert.ToString(dt.Rows[n]["Id"]), 
        Convert.ToString(dt.Rows[n]["UserName"]), 
        Convert.ToString(dt.Rows[n]["List_Order"]), 
        Convert.ToString(dt.Rows[n]["LoggedIn"]) 
       }; 

       ViewBag.speakers.Add(speakers); 
      } 
     } 

     conn.Close(); 
    } 
} 

NB:SqlDataReader.Read()是只进,返回false最后后将排已经达到。如果DataReader.Read方法返回false,则ViewBag.speakers分配给空引用,因此while循环未执行。即使在SqlDataReader被关闭或到达最后一行之后,使用DataTable.Load方法也会从ExecuteReader保留返回的数据。

其次,你可以看看reader.Read() only read once even when there are multiple rows to read的问题,但恕我直言,它似乎只有在行长度已知或固定大小时才有效。由于在数据读取器关闭之前无法使用SqlDataReader.RecordsAffected,因此需要使用另一种方法从SqlDataReader获取行计数。

参考文献:

Populate data table from data reader

SqlDataReader.Read()

SqlDataReader.RecordsAffected

DataTable.Load()

相关问题