Linq to sql: properties of properties that may be null - c#

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?

Related

Code smell Id = blah== null ? null : something.x ? null : something.y

Any tips on how to fix this code smell (not my code):
Id = blah== null ? null : something.x ? null : something.y
Is perlish writing considered beneficial in C#? is using multiple lines and being clear a bad thing? How the hell is anyone to read the above? it is has takes 2 "if"s to assign a value.
Is there cleaner way of dealing with above?
In this case, another alternative to consider would be:
Id = (blah == null || something.x) ? null : something.y;
The benefit being that only one ternary is necessary (and thus null is returned from only one "branch" out of two, rather than two out of three).
This is ternary operator, For clear understanding you can convert it into if..else condition
Like,
if(blah == null)
{
Id = null;
}
else
{
if(something.x)
Id = null;
else
Id = something.y;
}
In your case ternary operator is used twice, so it might look confusing. Syntax of ternary operator is
condition ? consequent : alternative
It seems hard to read, but you could put each condition and statements in a line, it could be more easy to read.
Id = blah== null //Condition
? null //Then
: something.x //Condition
? null //Then
: something.y //Else

inline If run all part of statements with out condition

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.

MVC C# want my query to be able to return null elements

So I have a simple line of code that I'm using to check if the database already has data, but when it doesn't it returns an error (stating that nothing could be found in the database).
Basically I'm trying to get it so that the query can return null aswell? here's the code I'm using:
var ac = db.Houses.Single(d => d.address1 == reviewmodelview.Address1);
So as you can see its really quite simple, I will use the ac variable to run an if statement to see if its null or has has a value. But when its null, it throws an exception. Is there a piece of code I'm missing?
Instead of Single() use FirstOrDefault() that should do what you want.
Try SingleOrDefault - It will returns the default value for the type if the result set returns 0.
var ac = db.Houses.SingleOrDefault(d => d.address1 == reviewmodelview.Address1);
if(ac == null)
{
// null check
}

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.

Setting a default value when getting XML values via Linq

I’m using Linq to extract values from some XML. Shown below is a simplified example to show the problem I’m having. The following code works fine on the XML shown below. The problem I have is when the groupBy section is missing. Because when it’s missing Data.Element("groupBy").Element("property) fails because Data.Element("groupBy") will be null. Is it possible to modify my Linq statement to allow it to provide a default or should it be approached in a different way?
var e = (from Data in theXML.Descendants("exportFile")
select new Export
{
OutputFileName = Data.Element("outputFileName") != null ? (string)Data.Element("outputFileName") : "",
GroupByProperty = Data.Element("groupBy").Element("property") != null ? (string)Data.Element("groupBy").Element("property") : ""
}).First();
<exportFile>
<outputFileName>output.xml</outputFileName>
<groupBy>
<property>DeviceId</property>
</groupBy>
</exportFile>
You can already make it slightly nicer than it is using the null coalescing operator. However, to cope with the groupby element being missing is harder:
select new Export
{
OutputFileName = (string) Data.Element("outputFileName") ?? "",
GroupByProperty = Data.Element("groupBy") == null ? ""
: (string) Data.Element("groupBy").Element("property") ?? ""
}).First();
The conversion to string just returns null if the element reference is null.
An alternative would be:
GroupByProperty =
(string) Data.Elements("groupBy").Elements("property").FirstOrDefault() ?? ""
That uses the extension method which allows you to call Elements on an IEnumerable<XElement>... so that will (lazily) evaluate a sequence of every property element under a groupBy element under Data, then take the first of them if any exist, then apply the string conversion.
You could simply add an additional check in the statement (and clean things up a bit using the null coalescing operator):
GroupByProperty = Data.Element("groupBy") != null ?
(Data.Element("groupBy").Element("property") ?? "") : "";

Categories