inline If run all part of statements with out condition - c#

I Have a method to get all Ticket with filtering by FromDate .
my code like this :
public List<Model.Ticket> SelectList(DateTime? fromDate = null)
{
db.Tickets.Where(row=> (!fromDate.HasValue || (fromDate.HasValue ? (row.Date.Date >= fromDate.Value.Date) : false));
}
but when pass null It returns an exception :
Nullable object must have a value.
what's wrong?

You need to get all Ticket with filtering by FromDate, But in your where condition will only return true or false acording to the formdate you are passing as a parameter.But where condition expect a logic to filter data from the table acording to.You have to modify your where condition as
where(ticket=>ticket.formDate--here what ever the condition you need to apply)
NB: For your lambda expression(
db.Tickets.Where(!fromDate.HasValue || (fromDate.HasValue ? (row.Date.Date >= fromDate.Value.Date) : false))
)
the db query will be
select * from Tickets where true/false--acording to the output
this won't work

Maybe in your object declaration you have to initialize it

Null to be initialized by using new keyword. As directly assigning null to certain object doesn't carry desired contents. Debugging still shows value to null but it can't be instantiated likewise.

Related

Handling null with dataset and LINQ

I have a method which uses LINQ to look up a company in a local DataSet, using a company id (Guid). The properties from the data set is then stored in a class (CompanyModel), which is created for the occasion. One of the properties is the OrganizationNo, which is of type Long in the DataSet, but String in the CompanyModel.
The issue is, OrganizationNo can be null in the DataSet. This causes the ToString() method to throw an exception. I can tried fixing it (see below), but with no luck.
Isn't there some sort of simple, easy to read solution for this, which does not require multiple lines of code and/or use of try/catch?
UPDATE
The exception is thrown at an earlier point, since query becomes null if the organization number is null. Hence it has nothing to do with ToString() failing. The code never gets that far. I have tried changing the NullValue property of the OrganizationNo in the data table from (Throw Exception) to (Null), but this is not allowed. Is it a bad design we have chosen, using Long for a property which is sometimes null?
public void SelectCompany(Guid companyId)
{
SelectedCompany = new CompanyModel();
SelectedCompany.Id = companyId;
CompanyDataTabel dt = DataSet.Company;
// Look up the company in the company table in the data Set
var query = from company in dt.AsEnumerable()
where company.Id == companyId
select new
{
company.OrganizationNo,
company.Name,
company.PhoneNo,
company.Email,
};
// If the OrganizationNo is null, then the entire query is null.
// Hence the '.Count()' method will fail.
if (query.Count() != 1)
{
// One (and only one) company should match the organisation ID.
throw new ArgumentException("Multiple companies found.");
}
// These properties are never null and causes no issues
SelectedCompany.Name = query.First().Name;
SelectedCompany.PhoneNumber = query.First().PhoneNo;
SelectedCompany.EmailAddress = query.First().Email;
SelectedCompany.OrganisationNumber = query.First().OrganizationNo.ToString()
}
The problem in your query is that you are using a strongly typed DataSet which throws an error if you try to access a property that is null. To handle that case the DataSet automatically adds a bool method that you have to check before you access that nullable-column property. But your query creates an anonymous type that accesses this nullable property without this check. For that reason you will get the exception when the query is executed which is at query.First().
Use this query instead:
var query = from company in dt.AsEnumerable()
where company.Id == companyId
select new
{
OrganizationNo = company.IsOrganizationNoNull()
? string.Empty
: company.OrganizationNo.ToString(),
company.Name,
company.PhoneNo,
company.Email,
};
Side-note:
Instead of if (query.Count() != 1) you should use Single:
var company = query.Single(); // throws a desired exception if there are no or more than two records
SelectedCompany.Name = company.Name;
SelectedCompany.PhoneNumber = company.PhoneNo;
SelectedCompany.EmailAddress = company.Email;
SelectedCompany.OrganisationNumber = company.OrganizationNo;
This handles the case that there is none or more than one and will throw this exception on both cases. It's more efficient because you only need to execute the query once. Btw, all your query.First() calls must execute the whole query again
you can check OrganisationNumber property is must be define Nulable.. Nulable<long> or long? like this public long? OrganisationNumber {get;set;}
SelectedCompany.OrganisationNumber = string.Empty;
if(query.First() != null && query.First().OrganizationNo.HasValue)
{
SelectedCompany.OrganisationNumber =
query.First().OrganizationNo.Value.ToString();
}
or
SelectedCompany.OrganisationNumber = query.First() != null && query.First().OrganizationNo.HasValue ? "" : "";
or
SelectedCompany.OrganisationNumber =
query.First() != null ? query.First().OrganizationNo?.ToString() ?? string.Empty : string.Empty;
long type variable itself can not be null. but Nullable<long> can
The ?. operator works with null, which works for reference types or nullable value types, but not for normal value types like long.

Setting DateTime property to null

So I have this property and would like to either set the value to what is coming back from the db or to null if it is empty. It is possible to do this with an if-else, but for cleaner code, I would like to use the ternary operator. Could someone point out the mistake I am making. Thanks!!!
public DateTime? OptionExpiration {get;set;}
//actually sets the value to null
if(String.IsNullOrEmpty(dr["OPTION_EXPIRATION"].ToString())){
OptionExpiration = null;
}else{
OptionExpiration = DateTime.Parse(dr["OPTION_EXPIRATION"].ToString());
}
//so I check the to see if the string is empty or null, then try to set the value but recieve this error: Error 2 Operator '|' cannot be applied to operands of type '' and 'System.DateTime?'
String.IsNullOrEmpty(dr["OPTION_EXPIRATION"].ToString())
? OptionExpiration = null
| OptionExpiration = DateTime.Parse(dr["OPTION_EXPIRATION"].ToString())
;
You are using the ternary operator wrong.
It should be:
OptionExpiration = String.IsNullOrEmpty(Convert.ToString(dr["OPTION_EXPIRATION"]))
? (DateTime?)null
: DateTime.Parse(dr["OPTION_EXPIRATION"].ToString())
;
So:
assignment = condition ? trueExpression : falseExpression;
If the field is a date in your database, it might be better to do this:
OptionExpiration = Convert.IsDBNull(dr["OPTION_EXPIRATION"])
? (DateTime?)null
: (DateTime)dr["OPTION_EXPIRATION"]
;
I would use an extension method like this:
public static Nullable<DateTime> AsNullableDateTime(this object item, Nullable<DateTime> defaultDateTime = null)
{
if (item == null || string.IsNullOrEmpty(item.ToString()))
return defaultDateTime;
DateTime result;
if (!DateTime.TryParse(item.ToString(), out result))
return defaultDateTime;
return result;
}
You can pass anything in to this and it will attempt to give you back a date. If it fails for whatever reason (this also checks to make sure the object you send through is not null) you will get a null back; which is fine because you're mapping to a nullable datetime.
To use this you would do something like:
OptionExpiration = dr["OPTION_EXPIRATION"].AsNullableDateTime();
No mess, easy to understand what is happening, abstracting away the clutter, and highly reusable on other parts of your solution.

Lambda expressions query null field

Well, I have the following query that I use to search a LIST with the text that the user has filled.
It's only one textbox that search in all these fields below, it's working but when one of these fields is null, it's throwing a null reference exception, how can I avoid that?
List<REP_MEDIDORDISPLAY> SearchFiltered = new List<REP_MEDIDORDISPLAY>();
if (filter != String.Empty)
{
SearchFiltered.Clear();
foreach (String Item in filter.Split(';').ToList<String>())
{
SearchFiltered.AddRange(Medidores.Where(x => x.Data_TOI.Contains(Item.Trim()) ||
x.Elemento.ToUpper().Contains(Item.Trim()) ||
x.Fase.ToUpper().Contains(Item.Trim()) ||
x.ID.ToUpper().Contains(Item.Trim()) ||
x.KdKe.ToUpper().Contains(Item.Trim()) ||
x.N_Equipamento.ToUpper().Contains(Item.Trim()) ||
x.Status.ToUpper().Contains(Item.Trim()) ||
x.Tensao.ToUpper().Contains(Item.Trim())));
}
}
I hope you guys can help me. thanks.
By checking for null first:
(x.Elemento != null && x.Elemento.ToUpper().Contains(Item.Trim())) ||
// etc
Of course you should also calculate Item.Trim() just once and reuse this value for all tests rather than trimming as many times as there are fields.
You can add null check to each of the properties. Example:
From
x.Fase.ToUpper().Contains(Item.Trim()) ||
To
(x.Fase != null && x.Fase.ToUpper().Contains(Item.Trim())) ||
Maybe you should introduce something like a null object. This object is empty and will therefore always return false on every query against it.
If you implement nullchecks for every property on that object your code will rot over time. And you are gonna have a bad time.
There are many ways to do what you are doing, some more elegant perhaps.
One simple way could be to override the ToString method in the object in the Medidores sequence and use that for the comparison.
Something like this:
class Medidor {
... properties
public override string ToString() {
return Data_TOI + Elemento ... etc
}
}
And then you could compare against that instead.
SearchFiltered.AddRange(
Medidores.Where(x =>
x.ToString()
.IndexOf(Item.Trim(), 0, StringComparison.InvariantCultureIgnoreCase) != -1
);
I'm using IndexOf as it has an overload that takes StringComparison.InvariantCultureIgnoreCase, which ignores casing among other things.
The reason why I think this approach is preferred to what you have now, is that the Meridor object itself is responsible for what fields are included in the ToString method. Maybe it can improve readability and maintainability.

Lightswitch NullReferenceException for String in C#

I am sure this is a case of basic ignorance, but I'm trying to test a database value using code behind in a Lightswitch project.
I'm checking if a varchar(MAX) value is null
if (Order.OrderNotes.Equals(null))
{
do.something...
}
However, I get a NullReferenceException if the value is null. If a value is there I get no error. I've tried using .contains(null), .Length = 0, .ToString() = "" etc without luck. It seems that ints and dates work fine using Equals(null), but not it seems for a string.
Help!!
Assuming you're calling this from a details screen where Order != null as #DeeMac pointed out.
You can check that Order isn't null using the same code below :
if (Order.OrderNotes == null)
{
// do.something...
}
if OrderNotes is null, you can't call any method, properties or whatever using that instance
you should call
if (Order.OrderNotes == null)
of course I assume that the var Order is not itself null,
if you want to be absolutely sure you could change your test in this way
if (Order != null && Order.OrderNotes == null)
In LightSwitch, to test if a nullable property has a value or not, you can use HasValue, so:
"if Order.OrderNotes.HasValue"
If you want the value if there is one, or the default value for the property type, you can use GetValueOrDefault:
"var value = Order.OrderNotes.GetValueOrDefault"
I agree wholeheartedly with Steve that you should be doing null checking on objects (such as Order) before trying to get a value from any of that object's properties.

Linq to sql: properties of properties that may be null

Simple LINQ query:
from transport in db.Transports
select new
{
Current = transport.CurrentLocation,
CurrentCarriers = transport.CurrentLocation.Carriers,
};
Problem: CurrentLocation may be null. If it is, executing this query throws a NullReference. I tried adding a check like
transport.CurrentLocation == null ? null : transport.CurrentLocation.Carriers
but Linq to sql does not seem to be able to parse that.
Any nice solutions that do not involve sending an extra query for each transport?
I normally just use 'let'.
from x in Foo
let y = x.Bar
where y != null
select y.Baz;
UPDATE:
I think the ?? operator does translate to SQL.
If the foreign key on Transports is nullable, you'll have to check that column for null before you can try and get the CurrentLocation object.
You could do something like this:
CurrentLocation = transport.currentLocationId != null ? transport.CurrentLocation : null;
Just do (you where using the wrong property):
transport.CurrentLocation == null ? null : transport.CurrentLocation.Carriers
Update 1: That is weird, I have used some pretty complex queries and didn't face that issue. I just checked one, don't think it matters, but mine had the check inverted:
transport.CurrentLocation != null ? transport.CurrentLocation.Carriers : null;
Can you post the complete query you tried that gives you the parse exception?

Categories