[英]ServerVersion = 'conn.ServerVersion' threw an exception of type 'System.InvalidOperationException'
[英]'accessibilityobject' threw an exception of type 'system.invalidoperationexception'
SO上有很多關於'system.invalidoperationexception
'的問題,但是沒有一個問題可以幫助我解決這個問題。
我有一個datatable
( tab2tableExtra
)從另一個獲取其值datatable
( tab2table
),進而得到的是從數據庫中值。 tab2tableExtra
僅包含4行和8列,並且其所有值(禁止列[0])均從tab2table
計算tab2table
。 具體來說, tab2table
中的兩列用於驅動for循環,而這似乎是問題的症結所在。 它們是MLevel
和RLevel
,顯示在下面的代碼中。
當MLevel
列和RLevel
列都具有一些非null值時,一切都將正常工作。 但是,如果這些列之一全為空( DBNull.Value
有時可能會發生),那么似乎出了問題。 有趣的是,它實際上並沒有導致代碼中斷,但似乎使tab2tableExtra
的計算值混亂了,因為整個表為空(列[0]除外,該列僅是1,2,3,4) 。
在調試時,當任一MLevel
或RLevel
(但不是兩者)包含所有空我看到“system.invalidoperationexception from
this`,如示於以下圖中。 導致代碼執行此操作的原因是,在一次迭代后退出for循環,然后不執行任何其他計算。
此消息來自以下代碼:
// 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;
作為參考,當我和一個調試tab2table
,在這兩個具有至少一個非空值, MLevel
和RLevel
,我看到這一點:
如果有人知道如何解決這個問題,甚至只是知道為什么會發生,那將非常有用。
在這些代碼行中:
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()
沒有返回可以解析為int
的string
,則int.TryParse
將返回false。 這包括x
是否為DBNull.Value
。 那不會被解析為int
。
然后,在之后TryParse
,你有這樣的: ? d : (int?)null)
? d : (int?)null)
換句話說,如果TryParse
返回TryParse
它能夠解析,則您選擇d
解析后的值。
但是,如果它無法解析該值TryParse
返回TryParse
那么您將返回(int?)null
實際上是null。
最后,您要過濾1到4之間的值的結果,然后計算這些結果的數量:
.Where(x => x >= 1 && x <= 4).Count();
正如您所描述的,如果存在一些非空值,則該Count
可能會返回一個或多個。 但是,如果所有值都為空,則.Count
等於0,因為沒有值在1到4之間。
在這種情況下, countnumM
和/或countnumRW
將等於0。
更進一步, if countnumM > 0
和if countnumM > 0
, if countnumRW > 0
需要設置一些其他值。 但是它們不大於0。它們是0。如果它們是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
的所有屬性。
其中一些可能是您不使用或不在意的屬性,但是當它嘗試讀取屬性以便向您顯示它們時,該屬性將引發異常。 因此,現在它代替了一個屬性值,它向您顯示了嘗試讀取該屬性時遇到的異常。
可以理解這是令人困惑的,因為您正在調試試圖弄清楚代碼中正在發生的事情,然后看到異常。 您想知道它們是否與問題有關。
通常,這不是因為如果您的代碼引發異常,那么它將停止執行您的代碼。 這是一個例外,您需要弄清楚。 但是,如果它沒有阻止代碼運行,並且是甚至沒有使用的某個框架類(例如Form.AccessibilityObject
)上的一個屬性,那么通常可以忽略它。
正如Scott Hannen所說,這里的問題與'system.invalidoperationexception'
異常無關。 對於遇到類似問題的任何人,實際的問題是null
。
事實證明,在C#中,數據表無法處理null
值。 它並沒有給出錯誤,而只是遇到數據表時就停止填充數據表。 為了解決此問題,必須確保使用DBNull.Value
。 因此,例如,在有問題的代碼中,將所有null
更改為DBNull.Value
將解決此問題。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.