如何确定哪个元素导致溢出?

How can I determine which element is causing an overflow?

我有这个代码:

String testData = File.ReadAllText("siteQueryTest.txt");
XDocument xmlDoc = XDocument.Parse(testData);
List<SiteQuery> sitequeries =
 (from sitequery in xmlDoc.Descendants("SiteQuery")
  select new SiteQuery
  {
      Id = Convert.ToInt32(sitequery.Element("Id").Value),
      UPCPackSize = Convert.ToInt32(sitequery.Element("UPCPackSize").Value),
      UPC_Code = sitequery.Element("UPC_Code").Value,
      crvId = sitequery.Element("crvId").Value,
      dept = Convert.ToInt32(sitequery.Element("dept").Value),
      description = sitequery.Element("description").Value,
      openQty = Convert.ToDouble(sitequery.Element("openQty").Value),
      packSize = Convert.ToInt32(sitequery.Element("packSize").Value),
      subDept = Convert.ToInt32(sitequery.Element("subDept").Value),
      unitCost = Convert.ToDecimal(sitequery.Element("unitCost").Value),
      unitList = Convert.ToDecimal(sitequery.Element("unitList").Value),
      vendorId = sitequery.Element("vendorId").Value,
      vendorItem = sitequery.Element("vendorItem").Value,
  }).ToList<SiteQuery>();

测试数据是:

<SiteQueries><SiteQuery><Id>00006000002</Id><UPCPackSize>1</UPCPackSize><UPC_Code>00006000002</UPC_Code><crvId></crvId><dept>8</dept><description>ZZ</description><openQty>0.0</openQty><packSize>1</packSize><subDept>80</subDept><unitCost>1.25</unitCost><unitList>5.0</unitList><vendorId>CONFLICT</vendorId><vendorItem>123456</vendorItem></SiteQuery>
. . . // gazillions of other SiteQuery "records"
<SiteQuery><Id>5705654</Id><UPCPackSize>1</UPCPackSize><UPC_Code>5705654</UPC_Code><crvId></crvId><dept>2</dept><description>what do you want</description><openQty>0.0</openQty><packSize>1</packSize><subDept>0</subDept><unitCost>0.55</unitCost><unitList>1.62</unitList><vendorId></vendorId><vendorItem></vendorItem></SiteQuery></SiteQueries>

但我使用此代码和数据得到以下运行时异常:

System.OverflowException was unhandled
  _HResult=-2146233066
  _message=Value was either too large or too small for an Int32.
  HResult=-2146233066
  IsTransient=false
  Message=Value was either too large or too small for an Int32.
  Source=mscorlib
  StackTrace:
       at System.Number.ParseInt32(String s, NumberStyles style, NumberFormatInfo info)
       at System.Convert.ToInt32(String value)
       at Sandbox.Form1.<button56_Click>b__e(XElement sitequery) in c:\HoldingTank\Sandbox\Form1.cs:line 2041
       at System.Linq.Enumerable.WhereSelectEnumerableIterator`2.MoveNext()
       at System.Collections.Generic.List`1..ctor(IEnumerable`1 collection)
       at System.Linq.Enumerable.ToList[TSource](IEnumerable`1 source)
    . . .
  InnerException: 

每个xml中有几个int值(4) "record";有数千条记录。我如何才能在不尝试戴上雨人帽(不太适合我)的情况下确定哪个值是导致上溢或下溢的有问题的值?

如果是下溢(异常消息同时显示 "OverflowException" 和 "Value was either too large or too small for an Int32",是否可能是这四个 int 成员之一的空值引起的?如果是,我怎么知道将空值视为 0?

这就是为什么大多数编码人员最终使用扩展方法而不是 LINQ 的原因。重写为:

private static SiteQuery ParseSiteQuery(XElement sitequery)
{
  return new SiteQuery
  {
      Id = Convert.ToInt32(sitequery.Element("Id").Value),
      UPCPackSize = Convert.ToInt32(sitequery.Element("UPCPackSize").Value),
      UPC_Code = sitequery.Element("UPC_Code").Value,
      crvId = sitequery.Element("crvId").Value,
      dept = Convert.ToInt32(sitequery.Element("dept").Value),
      description = sitequery.Element("description").Value,
      openQty = Convert.ToDouble(sitequery.Element("openQty").Value),
      packSize = Convert.ToInt32(sitequery.Element("packSize").Value),
      subDept = Convert.ToInt32(sitequery.Element("subDept").Value),
      unitCost = Convert.ToDecimal(sitequery.Element("unitCost").Value),
      unitList = Convert.ToDecimal(sitequery.Element("unitList").Value),
      vendorId = sitequery.Element("vendorId").Value,
      vendorItem = sitequery.Element("vendorItem").Value,
  };
}

然后

List<SiteQuery> sitequeries = xmlDoc.Descendants("SiteQuery")
                                    .Select(ParseSiteQuery).ToList();

现在,当异常发生时,您将进入此转换函数内部,在 sitequery 范围内,立即了解导致失败的特定 XElement。

然后您可以使用快速观察表达式快速找出是什么初始化程序导致了异常。或者甚至为每个 属性 赋值编写单独的语句。

这就是最终的效果:

   private void button42_Click(object sender, EventArgs e)
   {
       ArrayList arrList = 
    FetchSiteQuery("http://localhost:21608/api/sitequery/getall/dbill/ppus/42"); 
        String omnivore = "<SiteQueries>";
        foreach (String s in arrList) //- see siteQueryData.png
        {
            omnivore += s;
        }
        omnivore += "</SiteQueries>";

        String messedUpJunk = "<ArrayOfSiteQuery xmlns:i=\"http://www.w3.org/2001/XMLSchema-
    instance\" xmlns=\"http://schemas.datacontract.org/2004/07/CStore.DomainModels.HHS\">";
        omnivore = omnivore.Replace(messedUpJunk, String.Empty);
        omnivore = omnivore.Replace("</ArrayOfSiteQuery>", String.Empty);

        XDocument xmlDoc = XDocument.Parse(omnivore);
        List<SiteQuery> sitequeries = 
    xmlDoc.Descendants("SiteQuery").Select(GetSiteQueryForXMLElement).ToList();
    }

    private static SiteQuery GetSiteQueryForXMLElement(XElement sitequery)
    {
        return new SiteQuery
        {
            Id = sitequery.Element("Id").Value,
            UPCPackSize = Convert.ToInt32(sitequery.Element("UPCPackSize").Value),
            UPC_Code = sitequery.Element("UPC_Code").Value,
            crvId = sitequery.Element("crvId").Value,
            dept = Convert.ToInt32(sitequery.Element("dept").Value),
            description = sitequery.Element("description").Value,
            openQty = Convert.ToDouble(sitequery.Element("openQty").Value),
            packSize = Convert.ToInt32(sitequery.Element("packSize").Value),
            subDept = Convert.ToInt32(sitequery.Element("subDept").Value),
            unitCost = Convert.ToDecimal(sitequery.Element("unitCost").Value),
            unitList = Convert.ToDecimal(sitequery.Element("unitList").Value),
            vendorId = sitequery.Element("vendorId").Value,
            vendorItem = sitequery.Element("vendorItem").Value,
        };
    }