我试图找出导致此代码出现Cannot perform runtime binding on a null reference
错误的原因:
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 :(得分:2)
对空列值调用.ToString()
方法可能会产生Cannot perform runtime binding on a null reference
。请改用Convert.ToString()
;如果您尝试转换null
值并且不需要额外的null
检查代码,它将返回空字符串。
答案 1 :(得分:2)
您的代码中存在两个问题:
考虑一下:
public ActionResult Index()
{
int n = 0;
ViewBag.speakers[n] = 5;
return View();
}
这段简化的代码抛出Cannot perform runtime binding on a null reference
,因为未定义扬声器(空引用)。
您可以通过在循环之前在动态 ViewBag中定义speakers
来解决此问题:
ViewBag.speakers = new List<string>();
第二个问题:
ViewBag.speakers[n] = speakers;
您的代码中的发言人是一个列表,您可能希望将ViewBag.speakers
定义为List<List<string>>
并调用.Add(speakers)
而不是使用索引进行访问(您可能会得到 index is超出范围)
答案 2 :(得分:1)
ViewBag
是一个动态对象,当您尝试对其属性进行赋值时,将在运行时进行空检查。您收到此错误是因为ViewBag.speakers
为null,或者它在尝试使用索引器访问其nth
广告位时引发异常(可能其大小小于n
,或者它没有&#39} ; t根本定义索引器)。您应该在向其添加元素之前初始化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);
}
}
答案 3 :(得分:0)
您的问题似乎源于在Read
之后使用ExecuteReader
方法,它在某些点上对动态对象ViewBag.speakers
提供了空引用,足以在视图端抛出运行时绑定异常。 / p>
使用DataTable.Load
和简单的for循环来迭代DataTable
内容,我修改了GökhanKurt对此问题的回答:
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();
}
}
注意:SqlDataReader.Read()
仅向前,在最后一行到达后将返回false
。如果ViewBag.speakers
方法返回false,则DataReader.Read
分配给空引用,因此while循环不执行。即使DataTable.Load
关闭或到达最后一行,使用ExecuteReader
方法也会保留SqlDataReader
的返回数据。
其次,您可能会看reader.Read() only read once even when there are multiple rows to read问题,但恕我直言,它似乎只有在行长度已知或固定大小时才有效。由于在数据阅读器关闭之前无法使用SqlDataReader.RecordsAffected
,因此您需要另一种方法从SqlDataReader
获取行数。
参考文献: