在foreach (DataRow Row in Table.Rows)
行中,我得到一个NullReferenceException。
该程序在C#中的模拟器中。当我调试它并且它崩溃时,它突出显示黄色的单词foreach
。我在下面贴了我的全部代码。
using System;
using System.Collections.Generic;
using System.Data;
using Reality.Storage;
using System.Threading;
namespace Reality.Game.Moderation
{
public static class ModerationBanManager
{
private static List<uint> mCharacterBlacklist;
private static List<string> mRemoteAddressBlacklist;
private static Thread mWorkerThread;
private static object mSyncRoot;
public static void Initialize(SqlDatabaseClient MySqlClient)
{
mCharacterBlacklist = new List<uint>();
mRemoteAddressBlacklist = new List<string>();
mSyncRoot = new object();
mWorkerThread = new Thread(new ThreadStart(ProcessThread));
mWorkerThread.Name = "ModerationBanManager";
mWorkerThread.Priority = ThreadPriority.Lowest;
mWorkerThread.Start();
ReloadCache(MySqlClient);
}
public static void ProcessThread()
{
try
{
while (Program.Alive)
{
Thread.Sleep(600000);
using (SqlDatabaseClient MySqlClient = SqlDatabaseManager.GetClient())
{
ReloadCache(MySqlClient);
}
}
}
catch (ThreadAbortException) { }
catch (ThreadInterruptedException) { }
}
public static void ReloadCache(SqlDatabaseClient MySqlClient)
{
lock (mSyncRoot)
{
mCharacterBlacklist.Clear();
mRemoteAddressBlacklist.Clear();
MySqlClient.SetParameter("timestamp", UnixTimestamp.GetCurrent());
DataTable Table = MySqlClient.ExecuteQueryTable("SELECT * FROM bans WHERE timestamp_expire > @timestamp");
foreach (DataRow Row in Table.Rows)
{
uint UserId = (uint)Row["user_id"];
string RemoteAddr = (string)Row["remote_address"];
if (UserId > 0 && !mCharacterBlacklist.Contains(UserId))
{
mCharacterBlacklist.Add(UserId);
}
if (RemoteAddr.Length > 0 && !mRemoteAddressBlacklist.Contains(RemoteAddr))
{
mRemoteAddressBlacklist.Add(RemoteAddr);
}
}
}
}
public static bool IsRemoteAddressBlacklisted(string RemoteAddressString)
{
lock (mSyncRoot)
{
return mRemoteAddressBlacklist.Contains(RemoteAddressString);
}
}
public static bool IsUserIdBlacklisted(uint UserId)
{
lock (mSyncRoot)
{
return mCharacterBlacklist.Contains(UserId);
}
}
public static void BanUser(SqlDatabaseClient MySqlClient, uint UserId, string MessageText, uint ModeratorId)
{
MySqlClient.SetParameter("userid", UserId);
MySqlClient.SetParameter("reason", MessageText);
MySqlClient.SetParameter("timestamp", UnixTimestamp.GetCurrent());
MySqlClient.SetParameter("timestampex", UnixTimestamp.GetCurrent());
MySqlClient.SetParameter("moderator", ModeratorId);
MySqlClient.ExecuteNonQuery("INSERT INTO bans (user_id,reason_text,timestamp_created,timestamp_expire,moderator_id) VALUES (@userid,@reason,@timestamp,@timestampex,@moderator)");
lock (mSyncRoot)
{
mCharacterBlacklist.Add(UserId);
}
}
}
}
答案 0 :(得分:5)
如果它真的被抛到这一行:
foreach (DataRow Row in Table.Rows)
然后Table
或Table.Rows
为空。如果它是从你的foreach循环内部抛出的话:
foreach (DataRow Row in Table.Rows)
{
//aka in here
}
然后它很可能意味着你的一行是null。要找到哪一个在循环的开头添加它,并在if语句中放置一个断点。
foreach (DataRow Row in Table.Rows)
{
if(Row == null)
{
//breakpoint here!
}
}
您也可以在调试时检查Table.Rows,但如果有1000行,则这不是一个现实选项。
答案 1 :(得分:4)
如果在该行中有NullReferenceException,则表示Table
变量或Rows
属性为null
。几乎没有其他选择。请在那里放一个断点并检查其中哪一个为空 - 然后调查并纠正它。
答案 2 :(得分:1)
如果Table
为null
,我认为该行中唯一会引发空引用异常的行为。
foreach (DataRow Row in Table.Rows)
当抛出异常并突出显示该行时,您将进入调试器。
当您进入调试器时,在屏幕的最底部,您会看到一个名为Watch
或Watch
的标签。点击该标签。
在底部的框中,输入单词Table
,然后按回车键,它会显示Table
的值,我敢打赌它为空。
答案 3 :(得分:1)
根据DataTable documentation,您正在调用的构造函数期望String
对象用作表的名称。它实际上并没有加载表。
使用DataTable的最佳方法是初始化DataTable(例如,DataTable table = new DataTable()
),然后使用Rows属性的.Add()方法添加它。为了说明,您可以在遍历mySql查询结果的foreach循环中使用以下代码:
table.Rows.Add(item)
答案 4 :(得分:0)
你调试了这个并确保你的DataTable实际上不是空的吗?
以下是什么回报?您的问题可能出在那行代码中,而不是在for / each
中DataTable Table = MySqlClient.ExecuteQueryTable("SELECT * FROM bans WHERE timestamp_expire > @timestamp");