C# adding data to a SQL table “Specified cast is not valid.”

548 views Asked by At

C# adding data to a SQL table with ASP.NET throws an error

System.InvalidCastException: "Specified cast is not valid"

This is for a foreign key column with a data type of bigint.

I set my type in C# to be Int64, after int definition threw an error but still get the error.

Is this because I can't add to a column that has foreign keys? Do I need to cascade?

This is my datacontroller:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Web.Http;
using SchoolDb.Models;
using MySql.Data.MySqlClient;
using System.Diagnostics;

namespace SchoolDb.Controllers
{
    public class CoursesDataController : ApiController
    {
        private SchoolDbContext School = new SchoolDbContext();

        /// <summary>
        /// returns list of courses in the system
        /// </summary>
        /// <example>GET api/CoursesData/ListCourses</example>
        /// <returns>a list of courses</returns>
        [HttpGet]
        [Route("api/CourseData/ListCourses/{SearchKey?}")]
        public IEnumerable<Course> ListCourses(string SearchKey = null)
        {
            //create an instance of a connection
            MySqlConnection Conn = School.AccessDatabase();

            //open the connection between server and database
            Conn.Open();

            string query = "Select * from classes where lower(classname) like lower(@key) or classid like (@key)";
            Debug.WriteLine("the search key is " + query);

            // establish a new command query for our database
            MySqlCommand cmd = Conn.CreateCommand();

            // SQL query
            cmd.CommandText = query;
            cmd.Parameters.AddWithValue("@key", "%" + SearchKey + "%");
            cmd.Prepare();

            // gather result set of query into variable
            MySqlDataReader ResultSet = cmd.ExecuteReader();

            // create an empty list of courses
            List<Course> Courses = new List<Course> { };

            while (ResultSet.Read())
            {
                // access column information by the db column name as an index
                int ClassId = (int)ResultSet["classid"];
                string ClassCode = (string)ResultSet["classcode"];
                Int64 TeacherId = (Int64)ResultSet["teacherid"];
                DateTime StartDate = (DateTime)ResultSet["startdate"];
                DateTime FinishDate = (DateTime)ResultSet["finishdate"];
                string ClassName = (string)ResultSet["classname"];

                Course NewCourse = new Course();
                NewCourse.ClassId = ClassId;
                NewCourse.ClassCode = ClassCode;
                NewCourse.TeacherId = TeacherId;
                NewCourse.StartDate = StartDate;
                NewCourse.FinishDate = FinishDate;
                NewCourse.ClassName = ClassName;

                // add the course info to the list
                Courses.Add(NewCourse);
            }

            Conn.Close();

            // return the final list of courses
            return Courses;
        }

        /// <summary>
        /// returns a single instance of a course
        /// </summary>
        /// <param name="id">class id</param>
        /// <returns>info on a particular course based on classid input</returns>
        [HttpGet]
        public Course FindCourse(int id)
        {
            Course NewCourse = new Course();

            // create an instance of a connection
            MySqlConnection Conn = School.AccessDatabase();

            // open the connection between server and database
            Conn.Open();

            // establish a new command query for our database
            MySqlCommand cmd = Conn.CreateCommand();

            // SQL query
            cmd.CommandText = "Select * from classes where classid = " + id;

            // gather result set of query into variable
            MySqlDataReader ResultSet = cmd.ExecuteReader();

            while (ResultSet.Read())
            {
                // access column information by the db column name as an index
                int ClassId = (int)ResultSet["classid"];
                string ClassCode = (string)ResultSet["classcode"];
                Int64 TeacherId = (Int64)ResultSet["teacherid"];
                DateTime StartDate = (DateTime)ResultSet["startdate"];
                DateTime FinishDate = (DateTime)ResultSet["finishdate"];
                string ClassName = (string)ResultSet["classname"];

                NewCourse.ClassId = ClassId;
                NewCourse.ClassCode = ClassCode;
                NewCourse.TeacherId = TeacherId;
                NewCourse.StartDate = StartDate;
                NewCourse.FinishDate = FinishDate;
                NewCourse.ClassName = ClassName;
            }

            return NewCourse;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="id"></param>
        /// <example>POST: /api/CoursesData/DeleteCourse/3</example>
        [HttpPost]
        public void DeleteCourse(int id)
        {
            // create an instance of a connection
            MySqlConnection Conn = School.AccessDatabase();

            // open the connection between server and database
            Conn.Open();

            // establish a new command query for our database
            MySqlCommand cmd = Conn.CreateCommand();

            // SQL query
            cmd.CommandText = "Delete from classes where classid=@id";
            cmd.Parameters.AddWithValue("@id", id);
            cmd.Prepare();

            cmd.ExecuteNonQuery();

            Conn.Close();
        }

        [HttpPost]
        public void AddCourse(Course NewCourse)
        {
            // create an instance of a connection
            MySqlConnection Conn = School.AccessDatabase();

            // open the connection between server and database
            Conn.Open();

            // establish a new command query for our database
            MySqlCommand cmd = Conn.CreateCommand();

            // SQL query
            cmd.CommandText = "insert into classes (classcode, teacherid, startdate, finishdate, classname) value (@ClassCode, @TeacherId, @StartDate,@FinishDate,@ClassName)";
            cmd.Parameters.AddWithValue("@ClassCode", NewCourse.ClassCode);
            cmd.Parameters.AddWithValue("@TeacherId", NewCourse.TeacherId);
            cmd.Parameters.AddWithValue("@StartDate", NewCourse.StartDate);
            cmd.Parameters.AddWithValue("@FinishDate",NewCourse.FinishDate );
            cmd.Parameters.AddWithValue("@ClassName", NewCourse.ClassName);
            cmd.Prepare();

            cmd.ExecuteNonQuery();

            Conn.Close();
        }
    }
}
2

There are 2 answers

0
Bradley Grainger On BEST ANSWER

You didn't specify which line the InvalidCastException occurs on, so I'm going to assume it's one of the following lines with explicit casts:

//access column information by the db column name as an index
int ClassId = (int)ResultSet["classid"];
string ClassCode = (string)ResultSet["classcode"];
Int64 TeacherId = (Int64)ResultSet["teacherid"];
DateTime StartDate = (DateTime)ResultSet["startdate"];
DateTime FinishDate = (DateTime)ResultSet["finishdate"];
string ClassName = (string)ResultSet["classname"];

One possibility is trying to retrieve an int from a long column, or vice versa. This can be avoided by using the GetInt32 or GetInt64 method. These will convert the value to a smaller size if possible, otherwise throw an OverflowException.

Another possibility is that some of the columns contain NULL. In that case, ResultSet["Name"] will return DBNull.Value, which can't be cast to a string (or int or DateTime).

Depending on what columns can contain NULL values, you likely need code similar to the following:

//access column information by the db column name as an index
int ClassId = ResultSet.GetInt32("classid");
string ClassCode = ResultSet.IsDBNull("classcode") ? null : reader.GetString("classcode");
Int64 TeacherId = ResultSet.GetInt64("teacherid");
DateTime StartDate = (DateTime)ResultSet["startdate"];
DateTime FinishDate = (DateTime)ResultSet["finishdate"];
string ClassName = ResultSet.IsDBNull("classname") ? null : ResultSet.GetString("classname");

But I would recommend using an ORM like Dapper to simplify all of this code and map a DB row easily to a C# object.

1
thunderkill On

Hello there : An InvalidCastException basically is thrown when the conversion of an instance of one type to another type is not supported(and that is the definition of it). For example, attempting to convert a Char value to a DateTime value throws an InvalidCastException exception. in your case I think first of all where you are casting "startdate" to DateTime you need to surround that whole code with a Try{}Catch(InvalidCastException ex){}. Then for the actual problem I think you need to use var instead of DateTime or Int64 if you have a dought about the return type .