How to handle null values from SQLite DB with C#? - c#

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.

Related

Check if a column exists while reading a database in C#

In my database I made two different tables for objects, let's say OBJECT, and ORIGINAL_OBJECT(in French, in example it is Repere), the only difference between them is ORIGINAL_OBJECT has not any column where I save the modifies made.
I have a function that gets me all the fields :
public Repere Select_detail_repere(string query)
{
Repere det = null; ;
if (this.OpenConnection() == true)
{
IDataReader dataReader = ExecuteReader(query);
while (dataReader.Read())
{
det = new Repere();
det.Name = (dataReader["DET_NOM"] ?? string.Empty).ToString().Trim();
det.Modifies = dataReader["MODIFICATIONS"].ToString().Trim();
det.Profil = (dataReader["DET_PRF"] ?? string.Empty).ToString().Trim();
det.Matiere = (dataReader["DET_MAT"] ?? string.Empty).ToString().Trim();
det.GroupeProfil = (dataReader["DET_GRP_PRF"] ?? string.Empty).ToString().Trim();
det.Longueur = double.Parse(dataReader["LONGUEUR"].ToString().Trim());
det.Largeur = double.Parse(dataReader["DET_LARGE"].ToString().Trim());
det.Hauteur = double.Parse(dataReader["DET_HAUT"].ToString().Trim());
det.Poids = double.Parse(dataReader["DET_PDS"].ToString().Trim());
det.Angle1 = double.Parse(dataReader["ANG_AME_1"].ToString().Trim());
det.Angle2 = double.Parse(dataReader["ANG_AME_2"].ToString().Trim());
det.AngleAile1 = double.Parse(dataReader["ANG_AILE_1"].ToString().Trim());
det.AngleAile2 = double.Parse(dataReader["ANG_AILE_2"].ToString().Trim());
det.PercageString = (dataReader["PERCAGE"] ?? string.Empty).ToString().Trim();
det.ScribingString = (dataReader["SCRIBING"] ?? string.Empty).ToString().Trim();
det.Mark = (dataReader["MARK"] ?? string.Empty).ToString().Trim();
det.ContInt0 = (dataReader["CONT_INT"] ?? string.Empty).ToString().Trim();
det.ContExt0 = (dataReader["CONT_EXT"] ?? string.Empty).ToString().Trim();
det.Revision = (dataReader["REVISION"] ?? string.Empty).ToString().Trim();
}
this.CloseConnection();
}
return det;
}
I use the same function for both OBJECT and OBJECT_ORIGINAL.
But when I want to read my OBJECT_ORIGINAL, I meet an error that says the field doesn't exist (obviously).
I already met the same problem in other situations, as this function will only work if I use SELECT * (if I don't read all columns this will return an error).
Until now the only way I found to solve it is using try/catch (in the catch I will apply a default value, ID=-1 for example), but I feel as it is not a very correct solution, and looking for another way to do that.
You need to check if the column MODIFICATIONS exists in the datareader, as you don't know it on forehand.
In the documentation of Microsoft I found a method called GetSchemaTable.
It will give you a datatable that describes the column metadata. So you could check that table to see if there is a column with the name MODIFICATIONS.
I would put that check in a different method so it doesn't clutter the code in your while loop that much.
OR
You could check this question on StackOverflow Check for column name in a SqlDataReader object which has a shorter solution to your problem.
I think that's even a nicer and easier solution, but I found it (with a simple google search) after I had almost completed my answer above. So that's why I give you both solutions (and also to help you a little with the MS documentation, which I pointed to in my comment)
It would be helpful to give as the query you use as well but I think you can use IF COL_LENGTH('table_name','column_name') IS NOT NULL in your query.
You can use the mysql stored procedure and do the checking inside on it.
check it here.
check if column exists before ALTER TABLE -- mysql
This question can be quoted as "Duplicate", I found the answer on stack
public Repere Select_detail_repere(string query)
{
Repere det = null; ;
if (this.OpenConnection() == true)
{
IDataReader dataReader = ExecuteReader(query);
bool containsModification = CheckIfDataContains(dataReader, "MODIFICATIONS");
while (dataReader.Read())
{
det = new Repere();
det.Name = (dataReader["DET_NOM"] ?? string.Empty).ToString().Trim();
if(containsModification)
{
det.Modifies = dataReader["MODIFICATIONS"].ToString().Trim();
}
else
{
det.Modifies = "";
}
det.Profil = (dataReader["DET_PRF"] ?? string.Empty).ToString().Trim();
det.Matiere = (dataReader["DET_MAT"] ?? string.Empty).ToString().Trim();
...
}
this.CloseConnection();
}
return det;
}
public bool CheckIfDataContains(IDataReader dataReader,string columnName)
{
for (int i = 0; i < dataReader.FieldCount; i++)
{
if (dataReader.GetName(i).Equals(columnName, StringComparison.InvariantCultureIgnoreCase))
return true;
}
return false;
}

Handling null objects in object setters

I am trying to use a nice near object setter, but have null issues.
My code right now:
var Result = new RefundReplyObject
{
AuthorisationNumber = reply.refundResponse.transactionDetails.authorisationNumber,
ChargeValue = reply.refundResponse.transactionDetails.totalAmount.amount,
Message = reply.refundResponse.transactionDetails.message,
ReconciliationReference = reply.refundResponse.transactionDetails.reconciliationReference,
SettlementDate = reply.refundResponse.transactionDetails.settlementDate,
Status = TransactionStatusToLocalModel(reply.refundResponse.transactionDetails.status),
TransactionReference = reply.refundResponse.transactionDetails.transactionReference
};
BUT ... 'totalAmount' might be null. So, I get errors.
Is there a neat way to handle this, so that if 'totalAmount' is null, then set chargevalue to zero?
How about a ternary operator, that checks to see if total amount is null. If it isn't, then use it's amount, otherwise 0.
ChargeValue = (reply.refundResponse.transactionDetails.totalAmount != null) ? reply.refundResponse.transactionDetails.totalAmount.amount : 0,
You could do, for example:
ChargeValue = reply.refundResponse.transactionDetails.totalAmount != null ? reply.refundResponse.transactionDetails.totalAmount.amount : 0
ternary operator to the rescue!
ChargeValue = totalAmount ? totalAmount.amount : 0;
Something like this?
ChargeValue = (null == reply.refundResponse.transactionDetails.totalAmount)
? 0
: reply.refundResponse.transactionDetails.totalAmount.amount
You're not going to be able to do it on the setter side of things since the exception is occuring before you even get there. You can get what you're after (and clean up your code substantially in the process) by doing something like this:
var trans = reply.refundResponse.transactionDetails;
var Result = new RefundReplyObject
{
AuthorisationNumber = trans.authorisationNumber,
ChargeValue = trans.totalAmount == null ? 0 : trans.totalAmount.amount,
Message = trans.message,
ReconciliationReference = trans.reconciliationReference,
SettlementDate = trans.settlementDate,
Status = TransactionStatusToLocalModeltrans.status),
TransactionReference = trans.transactionReference
};

Logic to check for Null Value in Multiple Textboxes

Hi guys, probably a simple one.
Using C# .Net 4.0 and Visual Studio 2012 Ultimate.
Got the following code:
string part = "";
part = txtIOpart.Text;
txtBatchCV.Text = txtBatchIO.Text;
txtPartCV.Text = part;
txtExternalCV.Text = Sqlrunclass.SplitSpec_External(part, pg);
txtInternalCV.Text = Sqlrunclass.SplitSpec_Internal();
txtABSCV.Text = Sqlrunclass.SplitSpec_cvABS();
txtOilCV.Text = Sqlrunclass.SplitSpec_OilSeal();
txtBarCV.Text = "*" + Sqlrunclass.SplitInfo_ASno(part, pg) + "*";
txtBarNumCV.Text = txtBarCV.Text;
txtLocnCV.Text = Sqlrunclass.SplitInfo_Location();
txtFitsCV.Text = Sqlrunclass.SplitInfo_Desc();
txtHeightCV.Text = Sqlrunclass.SplitSpec_Height();
txtDiameterCV.Text = Sqlrunclass.SplitSpec_Diameter();
txtCirclitCV.Text = Sqlrunclass.SplitSpec_Circlit();
picTypeCV.Image = ftpclass.Download("CVspecType" + Sqlrunclass.SplitSpec_TypeCV() + ".jpg", "ftp.shaftec.com/Images/TypeJpg", "0095845|shafteccom0", "4ccc7365d4");
if (txtBatchCV.Text == null || txtBatchCV.Text == "")
{
txtBatchCV.Text = "ALL";
}
As you can see at the bottom I'm checking the batch, but I need to check all of the data thats being set by a bunch of methods. Each one will have a different txt output if it sees a null or blank txt. Is there anyway to shorten this code?
Try, txtBatchCV.Text For example
//Just for null
txtBatchCV.Text = (txtBatchCV.Text ?? "ALL").ToString();
//for both null and empty string
txtBatchCV.Text = string.IsNullOrEmpty(txtBatchCV.Text) ? "ALL": txtBatchCV.Text;
You could iterate through all the textboxes
foreach (var txt in form.Controls.OfType<TextBox>())
{
switch(txt.Id){
case "txtBatchCV":
// Do whatever you want for txtBatchCV e.g. check string.IsNullOrEmpy(txt.Text)
break;
}
}
I borrowed the above from here:
How do I loop through all textboxes and make them run corresponding actions from action dictionary?
In response to the comment I got from Tim, I've added a bit more code to explain what you could do. My code example was never meant to be a full solution.
TextBox.Text is never null, it will return "" then. If your methods return null you could use the null-coalescing operator:
string nullRepl = "ALL";
txtExternalCV.Text = Sqlrunclass.SplitSpec_External(part, pg) ?? nullRepl;
txtInternalCV.Text = Sqlrunclass.SplitSpec_Internal() ?? nullRepl;
txtABSCV.Text = Sqlrunclass.SplitSpec_cvABS() ?? nullRepl;
txtOilCV.Text = Sqlrunclass.SplitSpec_OilSeal() ?? nullRepl;
txtLocnCV.Text = Sqlrunclass.SplitInfo_Location() ?? nullRepl;
txtFitsCV.Text = Sqlrunclass.SplitInfo_Desc() ?? nullRepl;
txtHeightCV.Text = Sqlrunclass.SplitSpec_Height() ?? nullRepl;
txtDiameterCV.Text = Sqlrunclass.SplitSpec_Diameter() ?? nullRepl;
txtCirclitCV.Text = Sqlrunclass.SplitSpec_Circlit() ?? nullRepl;
For starters you could use string.IsNullOrEmpty(txtBatchCV.Text), it's a convevience method that basically does what you do in the if check.
You can atleast use one of these methods:
string.IsNullOrEmpty(txtBatchCV.Text)
or
string.IsNullOrWhitespace(txtBatchCV.Text)
I would try something like this:
void SetDefaultIfNull(TextBox txt, string defaultVal)
{
if (string.IsNullOrWhitespace(txt.Text))
txt.Text = defaultVal;
}
Then pass each textbox and the default to the method.

Convert a datetime to string

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);

Convert combobox string value to int

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

Categories

Resources