I began fixing a problem the customer had with signatures not displaying correctly. The customer has 2 columns one for current and for prior times - so they can have five outcomes:
Current new These two we just need to show the CurrDate
Prior New This hits the 1st ret
Current New This hits the 3rd ret
Prior Null
Current old These three we need to show the PrevDate
Prior old This hits the 2nd ret
Current new This hits the 2nd ret
Prior old
Current old This hits the 4th ret
Prior null
I and got to this if statement
private string CheckBoxDescription()
{
if (ViewState["PrevDate"] != null &&
ViewState["PrevDate"].ToString().Trim() != "" &&
ViewState["CurrDate"] != null &&
ViewState["CurrDate"].ToString().Trim() != "")
{
if (DateTime.Parse(ViewState["PrevDate"].ToString()) >
DateTime.Parse("01-JAN-12") &&
DateTime.Parse(ViewState["CurrDate"].ToString()) >
DateTime.Parse("01-JAN-12"))
{
return "SELECT Statement to get CurrDate;
}
else
{
return "SELECT Statement to get PrevDate;
}
}
if (DateTime.Parse(ViewState["CurrDate"].ToString()) >
DateTime.Parse("01-JAN-12"))
{
return "SELECT Statement to get CurrDate (Same as the CurrDate above);
}
else
{
return "SELECT Statement to get PrevDate (Same as the PrevDate above);
}
}
I tried this:
if (DateTime.Parse(ViewState["CurrDate"].ToString()) >
(DateTime.Parse("011-JAN-12")) &
(DateTime.Parse(ViewState["PrevDate"].ToString()) >
(DateTime.Parse("011-JAN-12")) |
(DateTime.Parse(ViewState["PrevDate"].ToString()) !=
null)))
but it will not pick up one of the null values.
For the null/empty check you can use String.IsNullOrWhitespace:
if (!string.IsNullOrWhiteSpace(ViewState["PrevDate"]) &&
!string.IsNullOrWhiteSpace(ViewState["CurrDate"]))
I would also store the parsed dates in variables rather than parsing each time
DateTime minDate = new DateTime(2012,1,1);
DateTime prevDate = DateTime.Parse(ViewState["PrevDate"]));
DateTime currDate = DateTime.Parse(ViewState["CurrDate"]));
then use those in the comparisons:
if (prevDate > minDate &&
currDate > minDate)
For the last check, DateTime.Parse will never return null so I'm not sure what conditions you're trying to check there. If the string value could be null then just check that:
if (currDate > minDate &
(ViewState["PrevDate"] == null ||
prevDate > minDate)
)
private string CheckBoxDescription()
{
if (ViewState["PrevDate"] != null &&
ViewState["PrevDate"].ToString().Trim() != "" &&
ViewState["CurrDate"] != null &&
ViewState["CurrDate"].ToString().Trim() != "")
{
if (DateTime.Parse(ViewState["PrevDate"].ToString()) >
DateTime.Parse("01-JAN-12") &&
DateTime.Parse(ViewState["CurrDate"].ToString()) >
DateTime.Parse("01-JAN-12"))
{
return "SELECT Statement to get CurrDate;
}
return "SELECT Statement to get PrevDate;
}
if (DateTime.Parse(ViewState["CurrDate"].ToString()) >
DateTime.Parse("01-JAN-12"))
{
return "SELECT Statement to get CurrDate (Same as the CurrDate above);
}
return "SELECT Statement to get PrevDate (Same as the PrevDate above);
}
From what you have done in the second block of code this is was what i could change, not much but what i have done is removed the else statements as you are returning i the first if statement, the else isn't needed.
Your friend: Case statements https://msdn.microsoft.com/en-GB/library/06tc147t.aspx
Multiple if statements also have a habit of slowing your code down because the IDE has to process all the conditions
With Case statements, it will only use certain pieces of information based on conditions
You can simplify this considerably by writing a method to parse a string into a nullable date:
private static DateTime? parseDate(object date)
{
DateTime result;
if (DateTime.TryParse(date.ToString(), out result))
return result;
return null;
}
Note that I had to make the parameter an object because I don't know what type ViewState["key"] returns.
One you have that you can simplify your code. However, doing so reveals that you haven't handled the case where currDate is not a valid date:
private string CheckBoxDescription()
{
var prevDate = parseDate(ViewState["PrevDate"]);
var currDate = parseDate(ViewState["CurrDate"]);
if (prevDate != null && currDate != null)
{
return
prevDate > DateTime.Parse("01-JAN-12") && currDate > DateTime.Parse("01-JAN-12")
? "SELECT Statement to get CurrDate"
: "SELECT Statement to get PrevDate";
}
// You have a problem here. What if currDate is not a valid date?
if (currDate == null)
throw new InvalidOperationException("Your current code doesn't handle this case.");
if (currDate > DateTime.Parse("01-JAN-12"))
{
return "SELECT Statement to get CurrDate (Same as the CurrDate above)";
}
else
{
return "SELECT Statement to get PrevDate (Same as the PrevDate above)";
}
}
How about this;
private string CheckBoxDescription()
{
var prevDate = ViewState["PrevDate"] != null && ViewState["PrevDate"].ToString().Trim() != ""
? DateTime.Parse(ViewState["PrevDate"].ToString())
: null;
var currDate = ViewState["PrevDate"] != null && ViewState["CurrDate"].ToString().Trim() != ""
? DateTime.Parse(ViewState["CurrDate"].ToString())
: null;
if (prevDate != null && currDate != null)
{
return
prevDate > DateTime.Parse("01-JAN-12") && currDate > DateTime.Parse("01-JAN-12")
? "SELECT Statement to get CurrDate"
: "SELECT Statement to get PrevDate";
}
if (currDate > DateTime.Parse("01-JAN-12"))
{
return "SELECT Statement to get CurrDate (Same as the CurrDate above);
}
else
{
return "SELECT Statement to get PrevDate (Same as the PrevDate above);
}
}
Related
I have the following code method, which is designed to check if a user is blocked temporarily after invalidating their maximum attempts (say, 10) to login in a two hour period.
public MyError ValidationMethod(MyObject myObject) {
int maxMaximumAttempts = 10;
if (myObject.Attempts >= maximumAttempts && myObject.LastAttempt.Value.AddHours(2)) < DateTime.Now)
return new MyError();
return null;
}
Both of the DateTime fields, "Attempts" and "LastAttempt" are nullable, what is the proper way to format this if statement to ensure I don't get null reference exceptions?
Null for either of the fields, should be the same result as if the if statement returned false, i.e. they haven't tried to login before. I will then return null from the method itself which symbolises, no error was found with the input.
I thought the fields being null would make the whole statement false but instead I get a null reference exception, can anyone explain why please?
Edit: I have added the full method to make the context clearer.
you can this code:
if (myObject != null && myObject.LastAttempt != null)
if (myObject.Attempts >= maximumAttempts && myObject.LastAttempt.Value.AddHours(2) < DateTime.Now)
return new myError();
or:
try
{
if (myObject.Attempts >= maximumAttempts && myObject.LastAttempt.Value.AddHours(2) < DateTime.Now)
return new myError();
}
catch(Exception ex)
{
return new myError(ex.Message);
}
Don't bother with nullables, use DateTime.MaxTime as not yet set value.
and for Attempts use 0 as not yet set value
public class myType {
// initialize myObject.LastAttempt = DateTime.MaxTime
DateTime LastAttempt = DateTime.Max;
int Attempts = 0;
/*
.... rest of the class
*/
}
public MyError ValidationMethod(MyObject myObject) {
int maxMaximumAttempts = 5;
if (myObject.Attempts >= maximumAttempts && myObject.LastAttempt != DateTime.Max && myObject.LastAttempt.AddHours(2)) < DateTime.Now)
return new MyError();
return null;
}
The nullable DateTime object has a property called HasValue, so you could write:
if (myObject.Attempts.HasValue && myObject.Attempts.Value >= maximumAttempts && myObject.LastAttempt.HasValue && myObject.LastAttempt.Value.AddHours(2) < DateTime.Now)
return new myError();
First of all, I would move these checks to the class which holds Attempts and LastAttempt fields (or at least created an extension for this class) - check Tell Don't Ask Principle
public class MyObject
{
public bool IsBlockedOn(DateTime time)
{
if (!Attempts.HasValue || !LastAttempt.HasValue)
return false;
var hasTooManyAttempts = MaximumAttempts <= Attempts.Value;
var timeoutPassed = Timeout < (time - LastAttempt.Value);
return hasTooManyAttempts && !timeoutPassed;
}
private TimeSpan Timeout = TimeSpan.FromHours(2);
private int MaximumAttempts = 10;
// other properties
}
Your if statement:
if (myObject.IsBlockedOn(DateTime.Now))
return new MyError();
The good part - this logic is now unit-testable because you can execute it with different time arguments.
Also, consider making Attempts non-nullable and initialize it with 0.
I have function which calculates quantity .Its working fine but some due to null values in field it does not return anything . these field can be null .i want to calculate only where both fields are not null. i think i need to use foreach but i dont know the way how can i use it here .
Help appreciated
private double Get_Quantity()
{
try
{
double sum = 0;
sum = (double)(from s in ManagerClass.oSqlData.table
where s.Demand.Order.Order_ID == Order_ID
where s.Demand.Order.Order_Date >= ManagerClass.startDate && s.Demand.Order.Order_Date <= ManagerClass.EndDate
select s.ValueA - s.ValueB ).Sum();
return sum;
}
catch
{
return 0;
}
}
Try like this;
sum = (double)(from s in ManagerClass.oSqlData.table
where (s.Demand != null && s.Demand.Order != null && s.Demand.Order.Order_ID == Order_ID)
&& (s.Demand != null && s.Demand.Order != null && s.Demand.Order.Order_Date >= ManagerClass.startDate && s.Demand.Order.Order_Date <= ManagerClass.EndDate)
&& s.ValueA != null
&& s.ValueB != null
select s.ValueA - s.ValueB).DefaultIfEmpty(0).Sum();
string query = "SELECT COUNT(DISTINCT [PIN]) AS [pinCount] FROM [Users]";
DataTable dt = Execute(query);
if (dt == null || dt.Rows.Count == 0 || dt.Rows[0][0] == DBNull.Value)
return false;
else if ((int)dt.Rows[0]["pinCount"] > 0)
return true;
return false;
i have this kind of query in my code, and when casting the count to int, it gives me an exception that when castin the value must be less then infinite...what am i doing wrong?
Try this code
if (dt != null)
{
if (dt.Rows.Count > 0)
{
object tVal = dt.Rows[0][0];
if (!Convert.IsDBNull(tVal))
return (Convert.ToInt32(tVal) > 0);
}
}
return false;
I have a LINQ query that queries a DataTable. In the DataTable, the field is a string and I need to compare that to an integer, basically:
if ((electrical >= 100 && electrical <= 135) || electrical == 19)
{
// The device passes
}
the problem is, I am trying to do this in LINQ like this:
var eGoodCountQuery =
from row in singulationOne.Table.AsEnumerable()
where (Int32.Parse(row.Field<String>("electrical")) >= 100 &&
Int32.Parse(row.Field<String>("electrical")) <= 135) &&
Int32.Parse(row.Field<String>("electrical")) != 19 &&
row.Field<String>("print") == printName
select row;
I keep getting the exception:
Input string was not in a correct format
The main problem occurs when electrical == ""
Unfortunately, the framework doesn't provide a nice clean way to handle parsing scenarios where it fails. Of what's provided, they only throw exceptions or use out parameters, both of which does not work well with linq queries. If any one value you're parsing fails, the entire query fails and you just can't really use out parameters. You need to provide a method to handle the parsing without that does not throw and does not require using out parameters.
You can handle this in many ways. Implement it where upon failure, you return some default sentinel value.
public static int ParseInt32(string str, int defaultValue = 0)
{
int result;
return Int32.TryParse(str, out result) ? result : defaultValue;
}
Or what I would recommend, return a nullable value (null indicating it failed).
public static int? ParseInt32(string str)
{
int result;
return Int32.TryParse(str, out result) ? result : null;
}
This simplifies your query dramatically while still leaving it readable.
public bool GetElectricalStatus(string printName)
{
var query =
from row in singulationOne.Table.AsEnumerable()
where row.Field<string>("print") == printName
// using the nullable implementation
let electrical = ParseInt32(row.Field<string>("electrical"))
where electrical != null
where electrical == 19 || electrical >= 100 && electrical <= 135
select row;
return !query.Any();
}
p.s., your use of the Convert.ToInt32() method is incorrect. It is the same as calling Int32.Parse() and does not return a nullable, it will throw on failure.
I would check if the data in the column does not contain leading/trailing whitespaces - i.e. "15 " rather than "15" and if it does (or might do) trim it before trying to convert:
Int32.Parse(row.Field<String>("electrical").Trim())
BTW: not related to the error but I'd use let statement to introduce a local variable and do the conversion once:
let x = Int32.Parse(row.Field<String>("electrical").Trim())
where x >= 100...
I could not get anything to work, so I re-did the whole method:
public bool GetElectricalStatus(string printName)
{
List<object> eGoodList = new List<object>();
var eGoodCountQuery =
from row in singulationOne.Table.AsEnumerable()
where row.Field<String>("print") == printName
select row.Field<String>("electrical");
foreach (var eCode in eGoodCountQuery)
{
if (!string.IsNullOrEmpty(eCode.ToString()))
{
int? eCodeInt = Convert.ToInt32(eCode);
if (eCodeInt != null &&
(eCodeInt >= 100 && eCodeInt <= 135) || eCodeInt == 19)
{
eGoodList.Add(eCode);
}
}
}
if (eGoodList.Count() > 0)
{
return false;
}
else
{
return true;
}
}
The main problem occurs when electrical == ""
Why not make a function that does your evaluation, and call it in your Linq query. Put logic in to check the validity of the data contained within (so if you can't parse the data, it should return false)...
The function:
bool IsInRange(string text, int lower, int upper, params int[] diqualifiers)
{
int value = int.MinValue;
if (!int.TryParse(text, out value)) {
return false;
}
if (!(value >= lower && value <= upper)) {
return false;
}
if (disqualifiers != null && disqualifiers.Any(d => d == value)) {
return false;
}
return true;
}
The Linq query...
var eGoodCountQuery =
from row in singulationOne.Table.AsEnumerable()
where
IsInRange(row.Field<String>("electrical"), 100, 135, 19)
&& row.Field<String>("print") == printName
select row;
I have a search that returns a result that is dynamic. So I am trying to just show a label if there are no results found. The problem i am having is i dont know how to count the result because it is dynamic and is not equal to a type.
The error message is :
Operator '!=' Cannot be applied ot operands of type
System.Collections.Generic.List and int
if (Page.IsValid)
{
string keyword = txtSearch.Text.Trim();
List<dynamic> results = SearchItems(keyword);
List<dynamic> Cresults = SearchContacts(keyword);
if(results != 0 || Cresults !=0)
{
//bind and return
LVI.DataSource = results;
LVI.DataBind();
// System.Threading.Thread.Sleep(500);
//Contact Bind return
LVC.DataSource = Cresults;
LVC.DataBind();
// System.Threading.Thread.Sleep(250);
lvAdmin.DataSource = results;
lvAdmin.DataBind();
LVCAdmin.DataSource = Cresults;
LVCAdmin.DataBind();
}
else{
NoResults.Visible = true;
}
You cannot just do:
if(results != 0 || Cresults !=0)
{
}
That way your comparing the actual List to 0, which obviously fails.
Just do:
if(results.Count != 0 || Cresults.Count !=0)
{
}
Or:
if(results.Any() || Cresults.Any())
{
}
Use the Count property of the List class:
if (results.Count != 0 || Cresults.Count != 0)
{
//rest of code
}
Docs: http://msdn.microsoft.com/en-us/library/a7f69ad7.aspx
you can try using count
if(results.Count > 0 || Cresults.Count > 0)