MVC5 / C# - 无法对空引用执行运行时绑定
MVC5 / C# - Cannot perform runtime binding on a null reference
我正在尝试从这段代码中找出导致 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++;
}
对空列值调用 .ToString()
方法可能导致 Cannot perform runtime binding on a null reference
。使用 Convert.ToString()
代替;如果您尝试转换 null
值,它将 return 一个空字符串,并且不需要额外的代码来进行 null
检查。
您的代码中有两个问题:
考虑一下:
public ActionResult Index()
{
int n = 0;
ViewBag.speakers[n] = 5;
return View();
}
这段简化的代码抛出 Cannot perform runtime binding on a null reference
因为未定义扬声器(空引用)。
您可以通过在循环之前的 dynamic ViewBag 中定义 speakers
来修复它:
ViewBag.speakers = new List<string>();
第二期:
ViewBag.speakers[n] = speakers;
代码中的演讲者是一个列表,您可能希望将 ViewBag.speakers
定义为 List<List<string>>
并调用 .Add(speakers)
而不是使用索引访问(您可能会得到 索引超出范围)
ViewBag
是一个动态对象,当您尝试对其属性进行赋值时,将在运行时进行空检查。您收到此错误是因为 ViewBag.speakers
为空,或者它在尝试使用索引器访问其 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);
}
}
您的问题似乎源于在 ExecuteReader
之后使用 Read
方法,它在某个点对动态对象 ViewBag.speakers
提供空引用,足以在视图端抛出运行时绑定异常.
使用 DataTable.Load
和简单的 for 循环迭代 DataTable
内容,我修改了 Gökhan Kurt 对此的回答:
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()
是只向前的,它会在到达最后一行后 returns false
。如果DataReader.Read
方法returns为false,则ViewBag.speakers
赋值给空引用,从而不执行while循环。即使在 SqlDataReader
关闭或到达最后一行后,使用 DataTable.Load
方法仍会保留来自 ExecuteReader
的返回数据。
其次,您可能会查看 问题,但恕我直言,它似乎仅在行长度已知或固定大小时才有效。由于在数据 reader 关闭之前无法使用 SqlDataReader.RecordsAffected
,因此您需要另一种方法从 SqlDataReader
.
获取行数
参考文献:
Populate data table from data reader
我正在尝试从这段代码中找出导致 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++;
}
对空列值调用 .ToString()
方法可能导致 Cannot perform runtime binding on a null reference
。使用 Convert.ToString()
代替;如果您尝试转换 null
值,它将 return 一个空字符串,并且不需要额外的代码来进行 null
检查。
您的代码中有两个问题:
考虑一下:
public ActionResult Index()
{
int n = 0;
ViewBag.speakers[n] = 5;
return View();
}
这段简化的代码抛出 Cannot perform runtime binding on a null reference
因为未定义扬声器(空引用)。
您可以通过在循环之前的 dynamic ViewBag 中定义 speakers
来修复它:
ViewBag.speakers = new List<string>();
第二期:
ViewBag.speakers[n] = speakers;
代码中的演讲者是一个列表,您可能希望将 ViewBag.speakers
定义为 List<List<string>>
并调用 .Add(speakers)
而不是使用索引访问(您可能会得到 索引超出范围)
ViewBag
是一个动态对象,当您尝试对其属性进行赋值时,将在运行时进行空检查。您收到此错误是因为 ViewBag.speakers
为空,或者它在尝试使用索引器访问其 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);
}
}
您的问题似乎源于在 ExecuteReader
之后使用 Read
方法,它在某个点对动态对象 ViewBag.speakers
提供空引用,足以在视图端抛出运行时绑定异常.
使用 DataTable.Load
和简单的 for 循环迭代 DataTable
内容,我修改了 Gökhan Kurt 对此的回答:
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()
是只向前的,它会在到达最后一行后 returns false
。如果DataReader.Read
方法returns为false,则ViewBag.speakers
赋值给空引用,从而不执行while循环。即使在 SqlDataReader
关闭或到达最后一行后,使用 DataTable.Load
方法仍会保留来自 ExecuteReader
的返回数据。
其次,您可能会查看 SqlDataReader.RecordsAffected
,因此您需要另一种方法从 SqlDataReader
.
参考文献:
Populate data table from data reader