Search code examples
c#.nettypesdatatableado.net

Can ADO.NET DataTables hold data of types other than Object when grabbing data from a SQL Server?


I'm currently forced to use System.Data and System.Data.SqlClient, i.e. ADO.NET. I DataAdapter.Fill a lot of my DataTables with data from my SQL server. I know with absolute certainty that many of the columns will be set up in SQL such that they can only contain ints, but ADO.NET doesn't know that. Instead, it assumes that my data is of the Object type, meaning that my code is filled with many occurrences of ridiculous int.Parse(Row["RowName"].ToString()) code. I'd like to cut off this problem at the source and have my C# code know the types of the SQL columns that it's pulling through.

Is there any way to achieve this? I'm aware that DataColumns can be given types and that DataTables are built from them, but I don't know where to make those changes relative to when I'm fetching data from the server. So, for argument's sake, where would I modify this code to communicate that I know for absolutely certain that my columns will always be ints?

using System.Data;
using System.Data.SqlClient;

public static DataTable GetEmployeeStatistics(int EmployeeID)
{
    var Command = new SqlCommand("Select [Height], [Weight], [Salary] from [Schema].[Employees] Where EmployeeID = @EmployeeID", GrabMySqlConnection())
    Command.AddWithValue("@EmployeeID", EmployeeID)
    var Adapter = new SQLDataAdapter(Command);
    var Tab = new DataTable();
    var Adapter.Fill(Tab)
    return Tab
}

Solution

  • Your DataTable will contain the correct column-type int, but since DataTablea are very old they are not generic, so all rows contain objects as fields. You have to cast them to int. The best you can do is to use the Field-extension method which is generic and also supports nullable types(for example int? if it's nullable in DB).

    So instead of this:

    int.Parse(Row["ColumnName"].ToString())
    

    use

    Row.Field<int>("ColumnName") 
    

    By the way, your approach was already incorrect because you should not convert an object to string, just to be able to parse it to int. This would be the classic correct way:

    Convert.ToInt32(Row["ColumnName"])