C# 为什么对SqlCeConnection调用Open()会导致NullReferenceException?
我已经把这类问题转化为这个问题;瞧,这是一个更简洁、更容易理解的关于精确问题的陈述,但与更新8非常相似 基本上,mnuSendINV_Click()调用SendInventoryData(),后者调用getDataAsXMLFromTable(),后者抛出NRE 更具体地说,以下是上下文中的代码:C# 为什么对SqlCeConnection调用Open()会导致NullReferenceException?,c#,sql-server-ce,compact-framework,windows-ce,nullreferenceexception,C#,Sql Server Ce,Compact Framework,Windows Ce,Nullreferenceexception,我已经把这类问题转化为这个问题;瞧,这是一个更简洁、更容易理解的关于精确问题的陈述,但与更新8非常相似 基本上,mnuSendINV_Click()调用SendInventoryData(),后者调用getDataAsXMLFromTable(),后者抛出NRE 更具体地说,以下是上下文中的代码: private void mnuSendINV_Click(object sender, EventArgs e) { SendInventoryData(); } private
private void mnuSendINV_Click(object sender, EventArgs e)
{
SendInventoryData();
}
private void SendInventoryData()
{
String siteNum = String.Empty;
ArrayList sbInventories = new ArrayList();
foreach (String tbl in listboxWork.Items)
{
// Ignore CCR tables; just get INV tables
if (tbl.IndexOf("CCR") >-1) continue;
String tblName = getTableNameForInventoryName(tbl);
siteNum = getSiteNumberFromInventoryName(tbl);
sbInventories.Add(tblName);
}
foreach (string tbl in sbInventories)
{
string strData = getDataAsXMLFromTable(tbl, "003");
. . .
}
}
private String getDataAsXMLFromTable(String tableName, String siteNum)
{
string xmlOutput = String.Empty;
// data/xml fields
String lineId;
String refNum;
. . .
String newItem;
String paddedSiteNum = Prepad(3, siteNum);
string connStr = String.Format("Data Source=\"\\My Documents\\HHSDB{0}.SDF\"", paddedSiteNum);
String qry = String.Format("SELECT * FROM {0}", tableName);
MessageBox.Show(String.Format("connstr is {0}; qry is {1}", connStr, qry));
SqlCeConnection sqlceConn;
SqlCeCommand sqlceCmd;
try
{
sqlceConn = new SqlCeConnection(connStr);
sqlceCmd = new SqlCeCommand(qry, sqlceConn);
sqlceCmd.CommandType = CommandType.Text;
MessageBox.Show("Made it just before conn.Open()"); // <= I see this
if ((null != sqlceConn) && (!sqlceConn.State.Equals(ConnectionState.Open)))
{
MessageBox.Show("Will try to Open"); // <= I see this
sqlceConn.Open(); // <= This is where the world explodes
}
MessageBox.Show("Made it just after conn.Open()"); // <= I don't see this/make it to here; I see the NRE instead
SqlCeDataReader dtr = sqlceCmd.ExecuteReader(CommandBehavior.Default);
XmlDocument doc = new XmlDocument();
XmlDeclaration dec = doc.CreateXmlDeclaration("1.0", null, null);
doc.AppendChild(dec);// Create the root element
XmlElement root = doc.CreateElement("Command");
doc.AppendChild(root);
try
{
while (dtr.Read())
{
// outer INV
XmlElement invRec = doc.CreateElement("INV");
// Line ID
lineId = dtr["line_id"].ToString();
XmlElement _lineId = doc.CreateElement("line_id");
_lineId.InnerText = lineId;
invRec.AppendChild(_lineId);
// Ref Num
refNum = dtr["ref_no"].ToString();
XmlElement _refNum = doc.CreateElement("ref_no");
_refNum.InnerText = refNum;
invRec.AppendChild(_refNum);
. . .
// New Item
newItem = dtr["new_item"].ToString();
XmlElement _new_item = doc.CreateElement("new_item");
_new_item.InnerText = newItem;
invRec.AppendChild(_new_item);
root.AppendChild(invRec);
}
}
finally
{
xmlOutput = doc.OuterXml;
dtr.Close();
if (sqlceCmd.Connection.State == ConnectionState.Open)
{
sqlceCmd.Connection.Close();
}
}
}
catch (Exception ex)
{
MessageBox.Show(String.Format("inner ex is {0}", ex.InnerException.ToString()));
SSCS.ExceptionHandler(ex, "frmCentral.getDataAsXMLFromTable()");
}
return xmlOutput;
} //getDataAsXMLFromTable
INV1226006091415不存在于HHSDB003.SDF中
更新
为了回应Alexei的怀疑,以下是设备上有问题的文件:
.exe位于\Program Files\HHS中
更新2
对于聪明的新词(在异常类上似乎没有可用的“StackTrace”):
更新3
StackTrace不可用;编译失败,出现“'System.Exception'不包含'StackTrace'的定义”并出现以下错误:
更新4
我尝试了daniele3004的建议,使用以下基本代码:
private void menuItemTestSendingXML_Click(object sender, System.EventArgs e)
{
// If one of the below works, try it with the String.Format() jazz
//string connStr = "Data Source=\"\\My Documents\\HHSDB003.SDF"; <= NRE, without a catch block
string connStr = @"Data Source= \\My Documents\\HHSDB003.SDF"; // NRE with a catch block IF InnerException not first checked for null
//string connStr = @"Data Source= \\My Documents\HHSDB003.SDF";
//string connStr = "Data Source= \\My Documents\\HHSDB003.SDF";
//string connStr = "Data Source= \\\My Documents\\HHSDB003.SDF";
SqlCeConnection conn = null;
try
{
try
{
conn = new SqlCeConnection(connStr);
conn.Open();
MessageBox.Show("it must have opened okay");
}
finally
{
conn.Close();
}
}
catch (Exception ex)
{
if (null == ex.InnerException)
{
MessageBox.Show("inner Ex is null");
}
MessageBox.Show(String.Format("msg is {0}", ex.Message));
}
}
如果存在异常(而且存在,因为我到达了catch块),为什么InnerException为null
更新5
我的任何尝试都不起作用(请注意评论):
…更糟糕的是,现在它甚至不会向我显示“80004005存在文件共享冲突。另一个进程可能正在使用该文件。”err msg不再显示。相反,它变得神秘而有趣:
调用Open()
不是问题,我认为
- 您的
语句正在引发异常(可能是由于路径或密码无效或其他原因)李>Open()
- 它被catch语句捕获
- catch语句尝试显示消息框,将InnerException作为字符串注入消息中
没有异常
,并返回内部异常
null
在null上调用ToString()
- 空指针异常泄漏
堆栈跟踪将在10秒内清除此问题。您确定
Open()
抛出NRE吗?文档没有。问题中还包括stacktrace。问题似乎在connessione的字符串中。fai是一个小型演示程序,它只执行打开和关闭连接来隔离问题。请注意:“\My Documents\HHSDB003.SDF”可能不是有效的文件路径。。。不太可能是NRE的原因,但很可疑。您没有检查处理程序中的所有对象是否为null,这可能是NRE源。一个普通的MessageBox.Show(ee.ToString())给了你什么?我不知道如何从运行.exe的手持设备上获取堆栈跟踪(不能从PC上运行它;必须将.exe复制到设备上)。StackTrace是Exception类的字符串属性。您正在使用MessageBox告诉用户您捕获的内容。。。我想你可以从那里找到答案。我会试试看,但我不太乐观;毕竟,我的“内奸是”从我的捕获块从来没有显示;为什么会显示堆栈跟踪?我发现没有StackTrace可用(参见更新2)。不要相信Intellisense,看看API。每个异常都有一个StackTrace属性。至于为什么堆栈跟踪会显示而InnerException不会显示,这是因为MessageBox.Show调用实际上失败了。。。您在尝试打印InnerException时遇到异常。您已经解决了这个问题。正如我所说的。。。InnerException为空(基于您的更新)。忘了追踪吧。您已发现空指针异常源。“如果存在异常(确实存在,因为我到达了catch块),为什么InnerException为null?”因为没有异常!当使用异常包装另一个异常(装饰器模式)时,将使用InnerException。Exception中没有消息,所以我猜您只能继续使用异常的类型。
private void menuItemTestSendingXML_Click(object sender, System.EventArgs e)
{
// If one of the below works, try it with the String.Format() jazz
//string connStr = "Data Source=\"\\My Documents\\HHSDB003.SDF"; <= NRE, without a catch block
string connStr = @"Data Source= \\My Documents\\HHSDB003.SDF"; // NRE with a catch block IF InnerException not first checked for null
//string connStr = @"Data Source= \\My Documents\HHSDB003.SDF";
//string connStr = "Data Source= \\My Documents\\HHSDB003.SDF";
//string connStr = "Data Source= \\\My Documents\\HHSDB003.SDF";
SqlCeConnection conn = null;
try
{
try
{
conn = new SqlCeConnection(connStr);
conn.Open();
MessageBox.Show("it must have opened okay");
}
finally
{
conn.Close();
}
}
catch (Exception ex)
{
if (null == ex.InnerException)
{
MessageBox.Show("inner Ex is null");
}
MessageBox.Show(String.Format("msg is {0}", ex.Message));
}
}
"InnerEx is null"
"msg is " // [ex.Message is blank]
//string connStr = "Data Source=\"\\My Documents\\HHSDB003.SDF"; <= NRE
//string connStr = @"Data Source= \\My Documents\\HHSDB003.SDF"; // No NRE, but exception
//string connStr = @"Data Source= \\My Documents\HHSDB003.SDF"; // "inner ex is null; msg is [blank]
//string connStr = "Data Source= \\My Documents\\HHSDB003.SDF"; // ""
//string connStr = "Data Source= \\\My Documents\\HHSDB003.SDF"; <= won't even compile ("unrecognized escape sequence")
//string connStr = @"Data Source= My Documents\HHSDB003.SDF"; // "inner ex is null; msg is [blank]
//string connStr = "Data Source= My Documents\HHSDB003.SDF"; <= won't even compile ("unrecognized escape sequence")
string connStr = "Data Source= My Documents\\HHSDB003.SDF"; // "inner ex is null; msg is [blank]
SqlCeConnection conn = new SqlCeConnection(@"Data Source=/My Documents/HHSDB003.sdf;");
try
{
conn.Open();
MessageBox.Show("Connection!");
}
catch (SqlCeException ee) // <- Notice the use of SqlCeException to read your errors
{
SqlCeErrorCollection errorCollection = ee.Errors;
StringBuilder bld = new StringBuilder();
Exception inner = ee.InnerException;
if (null != inner)
{
MessageBox.Show("Inner Exception: " + inner.ToString());
}
// Enumerate the errors to a message box.
foreach (SqlCeError err in errorCollection)
{
bld.Append("\n Error Code: " + err.HResult.ToString("X"));
bld.Append("\n Message : " + err.Message);
bld.Append("\n Minor Err.: " + err.NativeError);
bld.Append("\n Source : " + err.Source);
// Enumerate each numeric parameter for the error.
foreach (int numPar in err.NumericErrorParameters)
{
if (0 != numPar) bld.Append("\n Num. Par. : " + numPar);
}
// Enumerate each string parameter for the error.
foreach (string errPar in err.ErrorParameters)
{
if (String.Empty != errPar) bld.Append("\n Err. Par. : " + errPar);
}
}
MessageBox.Show(bld.ToString());
bld.Remove(0, bld.Length);
}
@"Data Source=\My Documents\HHSDB003.sdf; File Mode=Read Write;");