Howsit!
I encounter an error when i get a null value in my datareader.
public List<Complaint> View_all_complaints()
{
csDAL objdal= new csDAL();
List<Complaint> oblcomplist=new List<Complaint>();
using( IDataReader dr=objdal.executespreturndr("View_all_complaints"))
{
while (dr.Read())
{
Complaint objcomp= new Complaint();
populate_reader(dr,objcomp);
oblcomplist.Add(objcomp);
}
}
return oblcomplist;
}
public void populate_reader(IDataReader dr, Complaint objcomp)
{
objcomp.ref_num = dr.GetString(0);
objcomp.type = dr.GetString(1);
objcomp.desc = dr.GetString(2);
objcomp.date = dr.GetDateTime(3);
objcomp.housenum = dr.GetInt32(4);
objcomp.streetnum = dr.GetInt32(5);
objcomp.status = dr.GetString(6);
objcomp.priority = dr.GetString(7);
objcomp.cid = dr.GetInt32(8);
if (!dr.IsDBNull(9))
{
objcomp.resolved_date = dr.GetDateTime(9);
}
}
in sql resolved date allows null values, this is so because only when a complaint has been resolved , it must reflect that date otherwise it should be null.
if dr.getdatetime(9) is null then it must just set a string saying "Not Resolved"
please help!
You haven't shown what your Complaint type looks like, but basically you'll want to make sure that its resolved_date is of type DateTime? aka Nullable<DateTime>. That allows you to model a missing value elegantly.
As for displaying it - you haven't shown anything about where you display the data, but you'd want something like:
string text = complaint.ResolvedDate.HasValue ? complaint.ResolvedDate.ToString()
: "Not Resolved";
(I've changed this to use a property with the idiomatic name at the same time...)
IDataReader has a "IsDBNull" method, that should be called before calling GetXXX(), in case your value is not nullable.
For example:
objcomp.date = dr.GetDateTime(3);
should be:
objcomp.date = dr.IsDBNull(3) ? DateTime.MinValue : dr.GetDateTime(3);
Related
I am getting a System.InvalidCastException at runtime with this code:
inf.Country = (Country)(int)rdr["Country"];
Model class:
public class BasicInfo
{
.....
public Gender Gender { get; set; }
public Country Country { get; set; }
}
public enum Gender
{
Male,
Female
}
public enum Country
{
Australia,
Bangladesh,
England,
France,
Usa
}
DbConnect class: the method return the entities list and it will pass through the controller's view.
usp_GetAllStudentData is a stored procedure that returns the list of records.
public List<BasicInfo> SelectStudent()
{
ConnectionString();//Contain Connection string
List<BasicInfo> entities = new List<BasicInfo>();
SqlCommand cmd = new SqlCommand("usp_GetAllStudentData", conn);
cmd.CommandType = CommandType.StoredProcedure;
conn.Open();
SqlDataReader rdr = cmd.ExecuteReader();
while(rdr.Read())
{
BasicInfo inf = new BasicInfo();
inf.FirstName = (string)rdr["FirstName"];
.....//other required value are assigned to class members.
//inf.Gender = (Gender)(int)rdr["Gender"];
inf.Country = (Country)(int)rdr["Country"]; // Getting run time exception here
entities.Add(inf);
}
return entities;
}
How the data is stored in the database
Can you guys let me know what is the best method to cast an enum value?
Or let me know if there is any alternative way to fix this issue.
Table Design
If your database field contains a NULL value then the result of your code is the Invalid Cast Exception
For example
object x = DbNull.Value; // A null value on the db is represented by DbNull.Value
inf.Country = (Country)(int)x; // Gives the Invalid Cast Exception
How to fix depends on what you want to do with null values. If you don't allow null values for countries then you should revise your code that accepts an invalid input and block these inputs (and not forget to set the Country field to NOT allow NULL values on the database table)
If you accept a null value then I suggest to add another entry to your country enum
public enum Country
{
Australia = 0,
Bangladesh,
England,
France,
Usa,
// <=== new countries should be added here....
Undefined = 9999
}
and change your reading code to
int ordinal = rdr.GetOrdinal("Country");
inf.Country = rdr.IsDBNull(ordinal) ? Country.Undefined
: (Country)(int)rdr["Country"];
From your comments it seems that you have stored the numeric value of the enum in a varchar column transforming your number in a string
If you want to convert back this string to the appropriate enum value then you should use Enum.TryParse, but the conversion back is not as simple as it seems.
So if you want to still check for null values then:
int ordinal = rdr.GetOrdinal("Country");
// Check for null value....
if(rdr.IsDBNull(ordinal))
inf.Country = Country.Undefined;
else
{
// OK, not null, but what if it is "ABC"??
if(!Enum.TryParse(rdr["Country"].ToString(), out inf.Country))
inf.Country = Country.Undefined;
// OK, but what if it is a number not defined in the coutry enum (IE "88")
if(!Enum.IsDefined(typeof(Country), inf.Country))
inf.Country = Country.Undefined;
}
As you can see, if there isn't a specific reason then I suggest to store the enum value as an integer and not as a string. This allow more flexibility in your code and in future changes to this variable.
try this
if (rdr["Country"]!=DBNull.Value)
{
inf.Country =(Country)Enum.ToObject(typeof(Country) , rdr["Country"].ToString());
}
EDIT:
Thanks to everyone who replied! I appreciate all of your answers :)
So I have a class with the following constructor:
public Transaction(DataRow row)
{
LastName = row.Field<string>("LastName");
FirstName = row.Field<string>("FirstName");
MI = row.ItemArray[3].ToString()[0];
ContactNumber = row.ItemArray[4].ToString();
Hours = int.Parse(row.ItemArray[5].ToString());
CheckIn = (DateTime)row.ItemArray[6];
roomNumber = int.Parse(row.ItemArray[9].ToString());
//Paid = row.Field<int>("Paid");
//TotalBill = row.Field<int>("TotalBill");
}
Notice I have 2 of them commented out with /'s That's because if I don't they return null values even if I try ''row.Field([Whatever]).GetValueOrDefault()'', it still comes out null and my constructor returns null. I also have my DB set with default values so IDK what's wrong.
Anyone got a work around? :)
The DataRow class has a method that is called IsNull and that could receive the column name.
Just combine it with the conditional operator
Paid = row.IsNull("Paid") ? 0 : row.Field<int>("Paid");
the same is true for all other fields that could contain a null value.
Just check for null first and supply a default value:
public Transaction(DataRow row)
{
LastName = row.Field<string>("LastName");
FirstName = row.Field<string>("FirstName");
MI = row.ItemArray[3].ToString()[0];
ContactNumber = row.ItemArray[4].ToString();
Hours = int.Parse(row.ItemArray[5].ToString());
CheckIn = (DateTime)row.ItemArray[6];
roomNumber = int.Parse(row.ItemArray[9].ToString());
Paid = row.Field<int?>("Paid") ?? 0;
TotalBill = row.Field<int?>("TotalBill") ?? 0;
}
See the ?? Operator (C# Reference) page on MSDN for further information on the ?? operator.
You can simply use the Nullable type and GetValueOrDefault method or use null coalescing operator.
Paid = row.Field<int?>("Paid").GetValueOrDefault()
or
Paid = row.Field<int?>("Paid") ?? 0
In both cases Paid will have a value of 0, you can change if you want.
Create your own little function that does a simple check.
Along the lines of:
public integer GetNumber (object val)
{
if (IsNumeric (val))
{
return val;
} else
{
return 0;
}
}
I'm not fantastic with C#, but that should give you an idea. Sorry about formatting, I'm on a phone which doesn't help at all.
I'm trying to update my table with this LINQ query
public void updateProduct(
int selectedIDToUpdate,
string prodNAMEToUp,
double prodPriceToUp,
string prodTYPEToUp,
int prodMANUToUp,
int prodCODEToUp)
{
DataClassesLINQEPOSDataContext dcld = new DataClassesLINQEPOSDataContext();
TBLPRODUCT tblprod = (from prod in dcld.TBLPRODUCTs
where prod.product_id == selectedIDToUpdate
select prod).First();
tblprod.product_name = prodNAMEToUp;
tblprod.product_price = prodPriceToUp;
tblprod.product_type = prodTYPEToUp;
tblprod.product_manufacturer = prodMANUToUp;
tblprod.product_code = prodCODEToUp;
dcld.SubmitChanges();
}
and then when I start to run the program I have this error
"InvalidCastException was unhandled"
"Specified cast is not valid."
Sorry I cant post image because I dont have enough reputation "points" :(
this is the control to pass the parameter on my class.
private void btnSaveToUpdate_Click(object sender, EventArgs e)
{
if (txtNameToUpdate.Text != "" ||
txtPriceToUpdate.Text != "" ||
txtTypeToUpdate.Text != "" ||
txtCodeToUpdate.Text != "")
{
Connection_Products update = new Connection_Products();
int selctedID = selectedIDToUpdate;
string prodNAMEToUp = txtNameToUpdate.Text;
double prodPriceToUp = double.Parse(txtPriceToUpdate.Text);
string prodTYPEToUp = txtTypeToUpdate.Text;
int prodMANUToUp = Convert.ToInt32(cmbManufacturerToUpdate.SelectedValue);
int prodCODEToUp = Convert.ToInt32(txtCodeToUpdate.Text);
update.updateProduct(selctedID, prodNAMEToUp, prodPriceToUp,
prodTYPEToUp, prodMANUToUp, prodCODEToUp);
}
else
{
MessageBox.Show("Error");
}
}
You most likely have some datatype mismatch between the values that you are trying to store and the data types of the columns in the database. This would be in one of the numeric columns.
If the prodPriceToUp column uses the money data type, this maps to a decimal type in Linq2Sql. You are trying to cast the double for the input parameter to decimal, which may be causing this issue. Try converting prodPriceToUp to a decimal before saving it.
I guess you are missing something in type mapping between updateProduct params and properties in tblprod. Please check here you are using correct types
This is because one of the following is trying to cast into an invalid type:
tblprod.product_name = prodNAMEToUp;
tblprod.product_price = prodPriceToUp;
tblprod.product_type = prodTYPEToUp;
tblprod.product_manufacturer = prodMANUToUp;
tblprod.product_code = prodCODEToUp;
Check for each of the these that the type of the left side is the same as the type of the right side. for example ensure that "tblprod.product_name" is a string property as you are trying to save a string to that property.
It is also possible that in your LINQ query, the where clause may have this problem, ensure that "prod.product_id" is an integer and not something else like a long or a short.
if these are all ok and you are still getting the exception then you will need to tell use what line is throwing the exception, and give use the details of the structure of tblprod;
I am trying to insert a DateTime value in sqlserver using linq. The DateTime value in the csharp side may be null. The corresponding field in sqlserver is a nullable datetime field. Following is my code:
using (var dataContext = GetDataContext())
{
DateTime dateTime;
var combinedWorkBasket = new CombinedWorkBasket()
{
FirstName = combinedWorkbasketData.FirstName,
LastName = combinedWorkbasketData.LastName,
Address1 = combinedWorkbasketData.Address1,
RetirementDate = Convert.ToDateTime(combinedWorkbasketData.RetirementDate),
};
dataContext.CombinedWorkBaskets.InsertOnSubmit(combinedWorkBasket);
dataContext.SubmitChanges();
}
When combinedWorkbasketData.RetirementDate happens to be null, which is a string value, which could be a valid date or null, then sqlserver throws error saying the date should be within range. When combinedWorkbasketData.RetirementDate happens to be null, Convert.ToDateTime(combinedWorkbasketData.RetirementDate) translates to some invalide data value. I tried the following, still same issue.
RetirementDate = DateTime.TryParse(combinedWorkbasketData.RetirementDate, out temp) ? Convert.ToDateTime(combinedWorkbasketData.RetirementDate) : Convert.ToDateTime(null)
I simply want to accomplish the following: When combinedWorkbasketData.RetirementDate is a valid date insert RetirementDate, otherwise don't insert it but insert other values such as Firstname etc
Thanks
You might want to use a nullable data type, but this helps only if your database permits null values in the RetirementDate column. In addition, you must make the RetirementDate field in class CombinedWorkBasket nullable, too.
using (var dataContext = GetDataContext())
{
DateTime? dateTime;
var combinedWorkBasket = new CombinedWorkBasket()
{
FirstName = combinedWorkbasketData.FirstName,
LastName = combinedWorkbasketData.LastName,
Address1 = combinedWorkbasketData.Address1,
RetirementDate = combinedWorkbasketData.RetirementDate != null ?
Convert.ToDateTime(combinedWorkbasketData.RetirementDate) : null;
};
dataContext.CombinedWorkBaskets.InsertOnSubmit(combinedWorkBasket);
dataContext.SubmitChanges();
}
The problem is that datetime does not holds null value but it holds minimum time i.e. some thing like this. '1/1/0001 12:00:00 AM'.
Instead of directly passing the date time try using
DateTime.MinValue== Convert.ToDateTime(combinedWorkbasketData.RetirementDate)?Null:Convert.ToDateTime(combinedWorkbasketData.RetirementDate)
I have not tested the code use it as reference u might be needing some refinement.
I think RetirementDate must be of nullable type for Entity framework to insert DBNull.
So make it like
public class CombinedWorkBasket
{
// other fields
public DateTime? RetirementDate { get; set; }
}
Then try assigning Null as per logic with associated column as "Allow Null" in database.
Hopefully it will insert null.
I have a question about converting types. I want to change the currently selected combobox value string to an int, but I get errors
My code:
int.Parse(age.SelectedItem.ToString());
What can I do for this problem?
Ok now we know the error, you can check for a null value before trying to parse it using:
if (comboBox1.SelectedItem != null)
{
int x = int.Parse(comboBox1.SelectedItem.ToString());
}
else { //Value is null }
You can avoid a null value being passed by setting the text property of the control to what ever default value you want.
If you are still not getting a value after making sure one is selected you really need to post your code.
TryParse is a good method for this sort of thing:
int value;
if (!Int32.TryParse(this.comboBoxNumeric.Text, out value))
{
//Do something fun...
}
Use a Convert.ToInt32 method. You can always use the databinding like this:
class A
{
public int ID{get;set;}
public string Name{get;set;}
}
cbo.DataSource = new A[]{new A{ID=1, Name="hello"}};
cbo.DisplayMember = "Name";
cbo.DisplayValue = "ID";
int id = Convert.ToInt32(cbo.SelectedValue);
A a = (A) cbo.SelectedItem;
int a_id = a.ID;
int a_name = a.Name;
If you use LINQ to DataSets, develop is very easy for C# program.
try
{
string name = comboBoxPort.SelectedItem.ToString();
int portBaudrate = Convert.ToInt32(comboBoxBaudrate.SelectedItem);
}
//just solved
//enjoy