Reputation: 1564
I'm getting a strange error in Visual Studio, and of course this great software is unable to tell me where the error is, just that I'm getting an error. I guess the best I can do is paste my code.
using (SQLiteCommand cmd = new SQLiteCommand(query, con))
{
using (SQLiteDataReader rdr = cmd.ExecuteReader())
{
while (rdr.Read())
{
//Console.WriteLine("{0} ", rdr["logLnNum"]);
ulong start, end, delta = 0;
string contentStr;
string contentMarkup;
String group;
start = (ulong)rdr["startTime"];
end = (ulong)rdr["endTime"];
convertTimes(start, end, 2728232, delta);
contentStr = String.Format("{0}, {1}, {2}, {3}, {4} (ms)",
rdr["offsetOfData"], rdr["amountOfData"], rdr["filename"],
rdr["logLnNum"], (delta * .001));
contentMarkup = "<div title=\"" + contentStr + "\">" + contentStr + "</div>";
group = String.Format("{0:X}", rdr["threadId"]);
group = group + ", " + rdr["threadName"];
TimelineData inputData = new TimelineData(contentMarkup, end, group, start);
Console.WriteLine("Data processed");
dataSet.Add(inputData);
}
}
}
Again, the only error I get is "System.InvalidCastException" occurred in .exe.
Upvotes: 0
Views: 373
Reputation: 3376
I would like to recommend you using an extra method to delimit this kind of errors. For instance, consider this code:
protected T getDataValue<T>(object value)
{
if (value != null && DBNull.Value != value)
return (T)value;
else
return default(T);
}
Then call it inside your datareader iteration for each value retrieved, this will help you during debugging to detect which field is producing the exception. Example:
start = getDataValue<ulong>(rdr["startTime"]);
end = getDataValue<ulong>(rdr["endTime"]);
In a nutshell, I usually follow these guidelines when working with data access to avoid exceptions:
If you have access to database, check your data using a db client before executing queries from ADO, this can be done executing the same query.
Consider using the same types in both layers (DB and App), in order to avoid cast exceptions --> it's not the same to convert from varchar to int, that making a simple cast from int to int (of course it comes as an object but for sure it has a type expected value), you reduce a lot of validation logic when using the same types.
If your table's fields accept nulls, consider using a strategy of conversion (like the method I gave you) to assign a valid value when null.
Try to avoid writing too much "logic" in DataAccess methods, just keep it simple, you can use a DTO or a business class in order to store all the values you've got from db, then use it/modify/create a logic in the business layer.
Hope it helps
Upvotes: 0
Reputation: 1310
Direct casting from an object only works when that object inherits from the type you're casting to (somewhere along the line, anyways).
A simple way to get the type you need out of a DataReader
is to call
[type].Parse(reader[index].ToString())
where [type]
is what you want to cast to, i.e.
ulong.Parse(rdr["startTime"].ToString())
The DataReader
objects typically have a .GetInt32(int)
, .GetDecimal(int)
, etc. that simply requires you to pass in the index of the column to parse. If you only have the name of the column, you can use Reader.GetOrdinal("yourColumnName")
.
Upvotes: 1