Frage

With the following code:

foreach (JObject obj in arr)
{
    id = (string)obj["Id"];
    packSize = (Int16)obj["PackSize"];
    var description = (string)obj["Description"];
    var deptSubdept = (Double)obj["DeptDotSubdept"];
    var unitCost = (Double)obj["Unit_Cost"];
    var unitList = (Double)obj["Unit_List"];
    var UPC_Code = (string)obj["UPC_code"];
    var UPC_packSize = (Int16)obj["UPC_pack_size"];
    var CRVId = (Int32)obj["CRV_Id"];

inventoryItems.Add(new WebAPIClientUtils.InventoryItem
{
    Id = id,
    PackSize = packSize,
    Description = description,
    DeptDotSubdept = deptSubdept,
    Unit_Cost = unitCost,
    Unit_List = unitList,
    UPC_code = UPC_Code,
    UPC_pack_size = UPC_packSize,
    CRV_Id = CRVId
});

...I'm getting, "System.ArgumentException: Input string was not in a correct format. Couldn't store <> in Cost Column. Expected type is Double. ---> System.FormatException..."

Note: "Cost" is the name of a column in a local table that is defined this way:

// Create temp table that mirrors InventoryItems as a staging area for the data to be bulk copied
var dt = new DataTable();
dt.Columns.Add(new DataColumn("Id", typeof(string)));
. . .
dt.Columns.Add(new DataColumn("Cost", typeof(double)));
. . .

So when the data retrieved has these bogus/empty vals, how can I check for that and use a value such as 0.00 for doubles, 0 for int, string.empty for String, &c?

To see when this was happening, I put a conditional breakpoint on this line:

var unitCost = (Double)obj["Unit_Cost"];

...by entering the following in the Breakpoint Condition dialog:

unitCost.ToString() == ""

...but it is never reached. I also tried setting "unitCost == null" as the conditional breakpoint, with the same [non]result.

UPDATE

With this:

id = (string)obj["Id"] ?? string.Empty;
packSize = (Int16)obj["PackSize"] ?? 0;
var description = (string)obj["Description"] ?? string.Empty;
var deptSubdept = (Double)obj["DeptDotSubdept"] ?? 0.0;
var unitCost = (Double)obj["Unit_Cost"] ?? 0.0;
var unitList = (Double)obj["Unit_List"] ?? 0.0;
var UPC_Code = (string)obj["UPC_code"] ?? string.Empty;
var UPC_packSize = (Int16)obj["UPC_pack_size"] ?? 0;
var CRVId = (Int32)obj["CRV_Id"] ?? 0;

...I get:

Operator '??' cannot be applied to operands of type 'short' and 'int' Operator '??' cannot be applied to operands of type 'double' and 'double' Operator '??' cannot be applied to operands of type 'int' and 'int'

UPDATE 2

I tried this:

double unitCost;
if (obj["Unit_Cost"] != DBNull.Value)
{
    unitCost = (Double) obj["Unit_Cost"];
}
else
{
    unitCost = 0.0;
}

...and get, "Operator '!=' cannot be applied to operands of type 'Newtonsoft.Json.Linq.JToken' and 'System.DBNull'"

UPDATE 3

Encasing the initial part of the conditional assignment in parens like so:

var UPC_Code = ((string)obj["UPC_code"]) ?? string.Empty;

...only works for strings; I still get the err msg for the other data types (int and double).

UPDATE 4

The runtime exception was occurring in this code:

dt.Rows.Add(invItem.Id, invItem.PackSize, invItem.Description, invItem.DeptDotSubdept,  
    invItem.Unit_Cost, invItem.Unit_List, invItem.UPC_code, invItem.UPC_pack_size, 
    invItem.CRV_Id);

...so I tried this:

int packSize = 1;
double unitCost = 0.0;
double unitList = 0.0;

if (invItem.PackSize != null)
{
    packSize = invItem.PackSize;
}
if (invItem.Unit_Cost != null)
{
    unitCost = invItem.Unit_Cost;
}
if (invItem.Unit_List != null)
{
    unitList = invItem.Unit_List;
}

dt.Rows.Add(invItem.Id, packSize, invItem.Description, 
    invItem.DeptDotSubdept, unitCost, unitList, invItem.UPC_code, 
    invItem.UPC_pack_size, invItem.CRV_Id);

...but it still fails, and the "!= null" lines have a case of the blue squigglies in the editor.

UPDATE 5

As to SLaks's suggestion, I tried:

if (obj["Unit_Cost"] == DBNull.Value)
{
    unitCost = 0.0;
}
else
{
    unitCost = (Double)obj["Unit_Cost"];
}

...but get, "Operator '==' cannot be applied to operands of type 'Newtonsoft.Json.Linq.JToken' and 'System.DBNull'"

I get the same thing with this:

if ((Double)obj["Unit_Cost"] == DBNull.Value)

....and this:

if (((Double)obj["Unit_Cost"]) == DBNull.Value)

UPDATE 6

I see that when this fails, the value of unitCost is not null, but 0. So, I set a breakpoint where that value is assigned:

unitCost == 0

...but the breakpoint is hit, even when the value is 0.0 (which is fine). I would think even 0 would be fine, but ... it's failing, so something is obviously wrong with the value.

War es hilfreich?

Lösung

Based on this answer and the recent information on what type you have, try to do:

id = obj.Value<string>("Id") ?? "";
packSize = obj.Value<short?>("PackSize") ?? (short)0;
var description = obj.Value<string>("Description") ?? "";
var deptSubdept = obj.Value<double?>("DeptDotSubdept") ?? 0.0;
var unitCost = obj.Value<double?>("Unit_Cost") ?? 0.0;
...
var crvId = obj.Value<int>("CRV_Id") ?? 0;

Andere Tipps

You're seeing DBNull.Value, which overrides ToString() to return "".

Check

if (obj["Unit_Cost"] == DBNull.Value)

If obj is a DataRow, you can also call obj.IsNull("Unit_Cost")

For default value you can use var def = (Double)(obj["Unit_Cost"] ?? default(Double));

If you use DeserializeObject instead of JObject, you can do this very easily with the DefaultValueAttribute and DefaultValueHandling:

void Main()
{
    var item = JsonConvert.DeserializeObject<InventoryItem>(@"{""Id"": 1}",
         new JsonSerializerSettings {
                DefaultValueHandling = DefaultValueHandling.Populate });
    // item.PackSize == 1
}
public class InventoryItem
{
    public string Id { get; set; }
    [DefaultValue(1)]
    public Int16 PackSize { get; set; }
    [DefaultValue("")]
    public string Description { get; set; }
    public Double DeptDotSubdept { get; set; }
}

try this

Double dbl;
Int16 int16;
Int32 int32;

    foreach (JObject obj in arr)
    {
        id = (string)obj["Id"];
        packSize = Int16.TryParse(obj["PackSize"].ToString(), out int16) ? (Int16)obj["PackSize"]:0;
        var description = (string)obj["Description"];
        var deptSubdept = Double.TryParse(obj["DeptDotSubdept"].ToString(), out dbl) ? (Double)obj["DeptDotSubdept"] : 0.00;
        var unitCost = Double.TryParse(obj["Unit_Cost"].ToString, out dbl) ? (Double)obj["Unit_Cost"] : 0.00;
        var unitList = Double.TryParse(obj["Unit_List"].ToString(), out dbl) ? (Double)obj["Unit_List"] : 0.00;
        var UPC_Code = (string)obj["UPC_code"];
        var UPC_packSize = Int16.TryParse(obj["UPC_pack_size"].ToString(), out int16) ? (Int16)obj["UPC_pack_size"] : 0;
        var CRVId = Int32.TryParse(obj["CRV_Id"].ToString(), out int32) ? (Int32)obj["CRV_Id"] : 0;

    inventoryItems.Add(new WebAPIClientUtils.InventoryItem
    {
        Id = id,
        PackSize = packSize,
        Description = description,
        DeptDotSubdept = deptSubdept,
        Unit_Cost = unitCost,
        Unit_List = unitList,
        UPC_code = UPC_Code,
        UPC_pack_size = UPC_packSize,
        CRV_Id = CRVId
    })

Try converting to a nullable type with the as operator and use Nullable(T).GetValueOrDefault.

foreach (JObject obj in arr)
{
    var id = obj["Id"] as string;
    var packSize = obj["PackSize"] as short?;
    var description = obj["Description"] as string;
    var deptSubdept = obj["DeptDotSubdept"] as double?;
    var unitCost = obj["Unit_Cost"] as decimal?;
    var unitList = obj["Unit_List"] as decimal?;
    var UPC_Code = obj["UPC_code"] as string;
    var UPC_packSize = obj["UPC_pack_size"] as short?;
    var CRVId = obj["CRV_Id"] as int?;

    inventoryItems.Add(new WebAPIClientUtils.InventoryItem
    {
        Id = id ?? string.Empty,
        PackSize = packSize.GetValueOrDefault(),
        Description = description ?? string.Empty,
        DeptDotSubdept = deptSubdept.GetValueOrDefault(),
        Unit_Cost = unitCost.GetValueOrDefault(),
        Unit_List = unitList.GetValueOrDefault(),
        UPC_code = UPC_Code ?? string.Empty,
        UPC_pack_size = UPC_packSize.GetValueOrDefault(),
        CRV_Id = CRVId.GetValueOrDefault()
    });
}

Also use decimal for currency.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top