'accessibilityobject'引发了'system.invalidoperationexception'类型的异常

时间:2019-04-30 16:55:51

标签: c# winforms

关于'system.invalidoperationexception'的问题很多,但是没有一个问题能帮助我解决这个问题。

我有一个datatabletab2tableExtra),它从另一个datatabletab2table)获取其值,而另一个tab2tableExtratab2table)从数据库获取值。 tab2table仅包含4行8列,并且其所有值(禁止列[0])均根据MLevel计算得出。具体来说,RLevel中的两列用于驱动for循环,而这似乎是问题的症结所在。它们是MLevelRLevel,在下面的代码中显示。

DBNull.Value列和tab2tableExtra列都具有一些非null值时,一切都将正常工作。但是,如果这些列之一全为空(MLevel-有时可能会发生),那么似乎出了问题。有趣的是,它实际上并没有导致代码中断,但是似乎与RLevel中的计算值混淆了,因为整个表为空(列[0]除外,该列仅是1,2, 3,4)。

在调试时,当from// Add values to tab2tableExtra // Add Levels columns DataRow row = tab2tableExtra.NewRow(); for (int i = 1; i < 5; i++) { row = tab2tableExtra.NewRow(); row["Level"] = i; tab2tableExtra.Rows.Add(row); } // Add participation rate column values DataRow dr = tab2tableExtra.Rows[0]; int rowCount = tab2table.Rows.Count; /*int countnumM = tab2table.AsEnumerable().Where(x => int.Parse(x["MLevel"].ToString()) == 1 || int.Parse(x["MLevel"].ToString()) == 2 || int.Parse(x["MLevel"].ToString()) == 3 || int.Parse(x["MLevel"].ToString()) == 4).ToList().Count;*/ int countnumM = tab2table.AsEnumerable().Select(x => int.TryParse(x["MLevel"].ToString(), out var d) ? d : (int?)null).Where(x => x >= 1 && x <= 4).Count(); int countnumRW = tab2table.AsEnumerable().Select(x => int.TryParse(x["RLevel"].ToString(), out var d) ? d : (int?)null).Where(x => x >= 1 && x <= 4).Count(); /*int countnumRW = tab2table.AsEnumerable().Where(x => int.Parse(x["RLevel"].ToString()) == 1 || int.Parse(x["RLevel"].ToString()) == 2 || int.Parse(x["RLevel"].ToString()) == 3 || int.Parse(x["RLevel"].ToString()) == 4).ToList().Count;*/ for (int i = 1; i < 5; i++) { if (countnumM > 0) { float levelPercM = Convert.ToInt32(tab2table.Compute("COUNT(MLevel)", "MLevel =" + i.ToString())); tab2tableExtra.Rows[i - 1][1] = Math.Round(100 * levelPercM / countnumM, 2); } else tab2tableExtra.Rows[i - 1][1] = null; if (countnumRW > 0) { decimal levelPercRW = Convert.ToDecimal(tab2table.Compute("COUNT([RLevel])", "RLevel =" + i.ToString())); tab2tableExtra.Rows[i - 1][2] = Math.Round(100 * levelPercRW / countnumRW, 2); } else tab2tableExtra.Rows[i - 1][2] = null; } // Add the rest of the column values that only require a single number tab2tableExtra.Rows[0][3] = rowCount; if (countnumM > 0) tab2tableExtra.Rows[0][4] = 100*countnumM/rowCount; else tab2tableExtra.Rows[0][4] = null; if (countnumRW > 0) tab2tableExtra.Rows[0][5] = 100*countnumRW/rowCount; else tab2tableExtra.Rows[0][5] = null; decimal RWavg = Convert.ToDecimal(tab2table.Compute("AVG([ROverall])", "")); decimal Mavg = Convert.ToDecimal(tab2table.Compute("AVG([MOverall])", "")); tab2tableExtra.Rows[0][6] = RWavg; tab2tableExtra.Rows[0][7] = Mavg; (但不是全部)都包含所有null时,我看到一个'system.invalidoperationexception tab2table this`,如下图所示。导致代码执行此操作的原因是,在一次迭代后退出for循环,然后不执行任何其他计算。 Error messages

此消息来自以下代码:

MLevel

作为参考,当我使用RLevel和{{1}}都具有至少一个非空值的{{1}}进行调试时,我看到以下内容: No Errors

如果有人知道如何解决这个问题,甚至只是知道为什么会发生,那将非常有用。

2 个答案:

答案 0 :(得分:1)

在这些代码行中:

int countnumM = tab2table.AsEnumerable()
    .Select(x => int.TryParse(x["MLevel"].ToString(), out var d) ? d : (int?)null)
    .Where(x => x >= 1 && x <= 4).Count();
int countnumRW = tab2table.AsEnumerable()
    .Select(x => int.TryParse(x["RLevel"].ToString(), out var d) ? d : (int?)null)
    .Where(x => x >= 1 && x <= 4).Count();

您正在使用int.TryParse来读取x["MLevel"]的值。

如果x["MLevel"].ToString()未返回可解析为string的{​​{1}},则int将返回false。其中包括int.TryParse是否为x。那不会被解析为DBNull.Value

然后,在int之后,您将拥有:TryParse

换句话说,如果? d : (int?)null)返回true-能够解析,则您选择的是TryParse-解析后的值。

但是,如果无法解析该值-d返回false-那么您将返回TryParse-实际上为空。

最后,您要过滤1到4之间的值的结果,然后计算这些结果的数量:

(int?)null

正如您所描述的,如果存在一些非空值,那么.Where(x => x >= 1 && x <= 4).Count(); 可能会返回一个或多个。但是,如果存在所有个空值,则Count将等于0,因为没有值在1到4之间。

在这种情况下,.Count和/或countnumM等于0。

进一步,您正在设置一些其他值countnumRWif countnumM > 0。但是它们不大于0。它们是0。如果它们是0,则您的代码将执行您期望的操作:

if countnumRW > 0

要澄清其他部分- for (int i = 1; i < 5; i++) { if (countnumM > 0) // this is == 0 { float levelPercM = Convert.ToInt32(tab2table.Compute("COUNT(MLevel)", "MLevel =" + i.ToString())); tab2tableExtra.Rows[i - 1][1] = Math.Round(100 * levelPercM / countnumM, 2); } else // This is what's happening tab2tableExtra.Rows[i - 1][1] = null; if (countnumRW > 0) // this is == 0 { decimal levelPercRW = Convert.ToDecimal(tab2table.Compute("COUNT([RLevel])", "RLevel =" + i.ToString())); tab2tableExtra.Rows[i - 1][2] = Math.Round(100 * levelPercRW / countnumRW, 2); } else // This is what's happening tab2tableExtra.Rows[i - 1][2] = null; }

当您进入调试器并检查变量的属性时,它将尝试显示每个属性的值。这就是图像中的属性列表-它是InvalidOperationException的所有属性。

其中一些可能是您不使用或不在意的属性,但是当它尝试读取这些属性以便向您显示它们时,该属性将引发异常。因此,现在,它代替了一个属性值,它向您显示了尝试读取该属性时遇到的异常。

这是可以理解的,因为您正在调试试图弄清楚代码中正在发生什么,然后看到异常。您想知道它们是否与问题有关。

通常不是,因为如果您的代码引发异常,则它将停止执行您的代码。这是一个例外,您需要弄清楚。但是,如果它没有阻止代码运行,并且是甚至没有使用的某个框架类(例如this)上的一个属性,那么通常可以忽略它。

答案 1 :(得分:0)

正如Scott Hannen所说,这里的问题与'system.invalidoperationexception'异常无关。对于遇到类似问题的人,实际的问题是null

事实证明,在C#数据表中无法处理null值。它并没有给出错误,而只是遇到数据表时就停止填充数据表。为了解决此问题,必须确保使用DBNull.Value。因此,例如,在相关代码中,将所有null更改为DBNull.Value将解决此问题。