nullable object must have a value in Linq - c#

I use following Linq To Entitiy To get the first and only record of my 'siteconfig' Entity :
var site = unitofwork.SiteConfigRepository.Get().FirstOrDefault();
But when my application comes to the following code, throws 'nullable object must have a value' :
if (site!= null) { TimeSpan span = DateTime.Now.Subtract((DateTime)site.logindDate ); }
And the only nullable type in my entity is a property called logindDate and is of type DateTime.
Any one help me out?

Try something like this:
if (site!= null)
{
if (site.loginDate.HasValue)
{ TimeSpan span = DateTime.Now.Subtract((DateTime)site.logindDate.Value ); }
}
You are not checking for a null loginDate and I suspect that may be the problem. Remember, when you have a nullable type, you need to check for HasValue, and then get the value from the Value property.

IEnumerable.FirstOrDefault() returns the first element of the enumerable, or default(T) (which is generally null, unless T is a value type) if there is no element in the list. Most probably your Get() returns an empty enumerable.
On a related matter (if indeed it is what happens), if you're sure that there is always one and only one element returned by a list, you should use Single() (because then you will have an exception thrown at that line) or test it against null just after the FirstOrDefault(). I think it's best having exceptions throwing or handling at the source of the unexpected behavior, and not several lines later.

Related

Can the result of JsonSerializer.Deserialize ever be null?

The return type shown in the docs for the JsonSerializer.Deserialize method all show the return type as nullable.
If you look at the deserialisation examples in the MS docs, you see that they are inconsistent, in that the first and third specify the return type as nullable...
WeatherForecast? weatherForecast =
JsonSerializer.Deserialize<WeatherForecast>(jsonString);
...whereas the second example misses off the ?, meaning it's non-nullable.
By experimenting, it seems that as long as you supply valid JSON (otherwise you get an exception), then the return value is always a non-null object of the specified type. If the property names don't match, then the returned object will have default values for those properties, but you never get a null reference - or at least, I couldn't find a way.
Anyone able to clarify? Is there a situation in which the method can return null, without throwing an exception? If not, why are the return types specified as nullable?
Thanks
Yes, parsing valid JSON "null" with a JSON serializer have to return null.
WeatherForecast? weatherForecast =
JsonSerializer.Deserialize<WeatherForecast>("null");
Note that other valid JSON strings like "123", "\"bob\"", "[]" should cause an exception because none of them represent a valid object.

How to avoid getting "possible "null"assignment to a non-nullable entity"

Sorry for this awkward example, but I want to keep it as to the point as possible
Lets say, I have parsed a json-file, which gives me the hierarchy below
var customers = myObj.SubObj?.CustomerList.EmptyIfNull();
var plusCustomers = customers.Where(...) // Resharper warning
myobj cannot be null
SubObject can be null sometimes
I have an extension method
IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> enumerable) => enumerable ?? Enumerable.Empty<T>();
So I expect the plusCustomers-line to be safe(empty list instead of null). But I get a warning
possible "null"assignment to a non-nullable entity
If I replace the first line with
var customers = myObj.SubObj.CustomerList.EmptyIfNull();
I get rid of the warning, but that is not correct. How can I convince Resharper that this is ok?...or I'm I mistaken?
You can add brackets:
(myObj.SubObj?.CustomerList).EmptyIfNull();
The effect of the null chaining (?.) is to evaluate the whole chain of member accesses to null, if the LHS operand is null, rather than evaluating just that single member access to null. For example, consider a long chain of member accesses a.b.c.d.e.f. If only a is nullable, you would only need to write ? after a for this to be safe. It doesn't just evaluate a?.b to null if a is null, because in that case you'd have to write ? after every member access for this to be safe, and that's a bit annoying.
So without the brackets, the whole member access is made nullable due to ?., regardless of what you call at the end.
By adding brackets, you break up the chain of member accesses, so that myObj.SubObj?.CustomerList is of a nullable type, and calling EmptyIfNull on that works as expected - returning whatever type EmptyIfNull should return.

A little bit of string cast

Update:
When a database returns a value through the scalar, it will always be an object. So when the value is returned you should have a preconceived notion of what the type will be. Why would you use ToString(); when you you have a SELECT which passes two parameters.
As if it doesn't exist it will always throw a null. So in my refactor I believed the as would be the proper approach. As ToString() will throw an error --- So what form of cast is it comparable to?
I've got some code I'm maintaining, but in apart of my refactor I came across a ToString() attached to an ExecuteScalar. My question would be, does the usage of ToString() equate to:
(string)command.ExecuteScalar();
Or would it represent this:
command.ExecuteScalar() as string;
Obviously the as string would fail gracefully, where the cast (string) would actually fall into an InvalidCastException. So when you call:
command.ExecuteScalar().ToString();
Which method of casting is it attempting to do?
No, it doesn't mean either of those - it simply means calling ToString() on whatever the value is.
In particular, if the value is not a string, it will convert it to a string anyway - whereas string would fail with InvalidCastException and the as would return null.
So for example:
object x = 10;
string a = x.ToString(); // "10"
string b = x as string; // null
string c = (string) x; // Bang
Of course, ToString() can still throw an exception too - most obviously if the target of the call is a null reference.
Personally, I would suggest using a cast if you know what the result type should be - although the result of ExecuteScalar is more commonly a numeric value (e.g. a count) rather than a string.
Yes, that means an exception will be thrown if you're wrong - but if your query isn't doing what it's meant to anyway, then stopping due to an exception may well be better than going ahead with a bogus view of the world. (See my blog post on casting vs as for more on this attitude.)
Neither, because Object.ToString() will returns you a string representation of the object. Regardless whether the query returns a varchar or int.
If command.ExecuteScalar() returns null then it would be something like null.ToString() which will break your production code.
also (string)command.ExecuteScalar() can break your code.
I would suggest to use below line
var result = command.ExecuteScalar() as string;
if(result != null)
{
//your code
}
Let's think about it for a bit.
When you do command.ExecuteScalar() you get back and object in a lot of cases based on the provider you get an int.
What happens is the order of operations triggers
Command.ExecuteScalar() gets and object back.
We are assuming he is an int for the excercise we get that int back.
To String gets called which is defined in the int32 object itself.
You get back the string that was determined inside.
For the most part toString is not meant to throw an exception if no one has implemented in the chain you just get the object type back which is the implementation on the object.
With that said in the case of the int it would probably be the one above. Note if execute scalar returns null to string will error out since null is not an object.
Hope that helps.
P.S. If you tell me the object type of ExecuteScalar i can give you a better answer.

linq-to-sql SingleOrDefault return when null

I'm writing a linq-to-sql query and I'm loading an ID (a bigint in the database and a long in my code) from a table, something like this:
var SomeQuery = (from x in ...
select x.ID).SingleOrDefault();
When I get the result, I use SingleOrDefault in case the return is empty. Does that mean that if the result is empty the SomeQuery variable will be 0 or null?
Thanks.
If you look the documenation for SingleOrDefault
Returns the only element of a sequence, or a default value if the
sequence is empty; this method throws an exception if there is more
than one element in the sequence.
It cleary states that if the sequence is empty it will return the default value which for long and bigint is 0. Why explained below
Documenation for default keyword states
In generic classes and methods, one issue that arises is how to assign
a default value to a parameterized type T when you do not know the
following in advance:
Whether T will be a reference type or a value type.
If T is a value type, whether it will be a numeric value or a struct.
Given a variable t of a parameterized type T, the statement t = null
is only valid if T is a reference type and t = 0 will only work for
numeric value types but not for structs. The solution is to use the
default keyword, which will return null for reference types and zero
for numeric value types.
Default is returned if no element found.(default value of int is 0)
Value is returned if one is found.
Exception is thrown if more than one is found.

What is the best way to deal with DBNull's

I frequently have problems dealing with DataRows returned from SqlDataAdapters. When I try to fill in an object using code like this:
DataRow row = ds.Tables[0].Rows[0];
string value = (string)row;
What is the best way to deal with DBNull's in this type of situation.
Nullable types are good, but only for types that are not nullable to begin with.
To make a type "nullable" append a question mark to the type, for example:
int? value = 5;
I would also recommend using the "as" keyword instead of casting. You can only use the "as" keyword on nullable types, so make sure you're casting things that are already nullable (like strings) or you use nullable types as mentioned above. The reasoning for this is
If a type is nullable, the "as" keyword returns null if a value is DBNull.
It's ever-so-slightly faster than casting though only in certain cases. This on its own is never a good enough reason to use as, but coupled with the reason above it's useful.
I'd recommend doing something like this
DataRow row = ds.Tables[0].Rows[0];
string value = row as string;
In the case above, if row comes back as DBNull, then value will become null instead of throwing an exception. Be aware that if your DB query changes the columns/types being returned, using as will cause your code to silently fail and make values simple null instead of throwing the appropriate exception when incorrect data is returned so it is recommended that you have tests in place to validate your queries in other ways to ensure data integrity as your codebase evolves.
If you aren't using nullable types, the best thing to do is check to see if the column's value is DBNull. If it is DBNull, then set your reference to what you use for null/empty for the corresponding datatype.
DataRow row = ds.Tables[0].Rows[0];
string value;
if (row["fooColumn"] == DBNull.Value)
{
value = string.Empty;
}
else
{
value = Convert.ToString(row["fooColumn"]);
}
As Manu said, you can create a convert class with an overloaded convert method per type so you don't have to pepper your code with if/else blocks.
I will however stress that nullable types is the better route to go if you can use them. The reasoning is that with non-nullable types, you are going to have to resort to "magic numbers" to represent null. For example, if you are mapping a column to an int variable, how are you going to represent DBNull? Often you can't use 0 because 0 has a valid meaning in most programs. Often I see people map DBNull to int.MinValue, but that could potentially be problematic too. My best advice is this:
For columns that can be null in the database, use nullable types.
For columns that cannot be null in the database, use regular types.
Nullable types were made to solve this problem. That being said, if you are on an older version of the framework or work for someone who doesn't grok nullable types, the code example will do the trick.
Add a reference to System.Data.DataSetExtensions, that adds Linq support for querying data tables.
This would be something like:
string value = (
from row in ds.Tables[0].Rows
select row.Field<string>(0) ).FirstOrDefault();
I always found it clear, concise, and problem free using a version of the If/Else check, only with the ternary operator. Keeps everything on one row, including assigning a default value if the column is null.
So, assuming a nullable Int32 column named "MyCol", where we want to return -99 if the column is null, but return the integer value if the column is not null:
return row["MyCol"] == DBNull.Value ? -99 : Convert.ToInt32(Row["MyCol"]);
It is the same method as the If/Else winner above - But I've found if you're reading multiple columns in from a datareader, it's a real bonus having all the column-read lines one under another, lined up, as it's easier to spot errors:
Object.ID = DataReader["ID"] == DBNull.Value ? -99 : Convert.ToInt32(DataReader["ID"]);
Object.Name = DataReader["Name"] == DBNull.Value ? "None" : Convert.ToString(DataReader["Name"]);
Object.Price = DataReader["Price"] == DBNull.Value ? 0.0 : Convert.ToFloat(DataReader["Price"]);
If you have control of the query that is returning the results, you can use ISNULL() to return non-null values like this:
SELECT
ISNULL(name,'') AS name
,ISNULL(age, 0) AS age
FROM
names
If your situation can tolerate these magic values to substitute for NULL, taking this approach can fix the issue through your entire app without cluttering your code.
DBNull implements .ToString() like everything else. No need to do anything. Instead of the hard cast, call the object's .ToString() method.
DataRow row = ds.Tables[0].Rows[0];
string value;
if (row["fooColumn"] == DBNull.Value)
{
value = string.Empty;
}
else
{
value = Convert.ToString(row["fooColumn"]);
}
this becomes:
DataRow row = ds.Tables[0].Rows[0];
string value = row.ToString()
DBNull.ToString() returns string.Empty
I would imagine this is the best practice you're looking for
It is worth mentioning, that DBNull.Value.ToString() equals String.Empty
You can use this to your advantage:
DataRow row = ds.Tables[0].Rows[0];
string value = row["name"].ToString();
However, that only works for Strings, for everything else I would use the linq way or a extension method. For myself, I have written a little extension method that checks for DBNull and even does the casting via Convert.ChangeType(...)
int value = row.GetValueOrDefault<int>("count");
int value = row.GetValueOrDefault<int>("count", 15);
Often when working with DataTables you have to deal with this cases, where the row field can be either null or DBNull, normally I deal with that like this:
string myValue = (myDataTable.Rows[i]["MyDbNullableField"] as string) ?? string.Empty;
The 'as' operator returns null for invalid cast's, like DBNull to string, and the '??' returns
the term to the right of the expression if the first is null.
You can also test with Convert.IsDBNull (MSDN).
I usually write my own ConvertDBNull class that wraps the built-in Convert class. If the value is DBNull it will return null if its a reference type or the default value if its a value type.
Example:
- ConvertDBNull.ToInt64(object obj) returns Convert.ToInt64(obj) unless obj is DBNull in which case it will return 0.
For some reason I've had problems with doing a check against DBNull.Value, so I've done things slightly different and leveraged a property within the DataRow object:
if (row.IsNull["fooColumn"])
{
value = string.Empty();
}
{
else
{
value = row["fooColumn"].ToString;
}
Brad Abrams posted something related just a couple of days ago
http://blogs.msdn.com/brada/archive/2009/02/09/framework-design-guidelines-system-dbnull.aspx
In Summary "AVOID using System.DBNull. Prefer Nullable instead."
And here is my two cents (of untested code :) )
// Or if (row["fooColumn"] == DBNull.Value)
if (row.IsNull["fooColumn"])
{
// use a null for strings and a Nullable for value types
// if it is a value type and null is invalid throw a
// InvalidOperationException here with some descriptive text.
// or dont check for null at all and let the cast exception below bubble
value = null;
}
else
{
// do a direct cast here. dont use "as", "convert", "parse" or "tostring"
// as all of these will swallow the case where is the incorect type.
// (Unless it is a string in the DB and really do want to convert it)
value = (string)row["fooColumn"];
}
And one question... Any reason you are not using an ORM?
You should also look at the extension methods. Here are some examples to deal with this scenerio.
Recommended read
If you are concerned with getting DBNull when expecting strings, one option is to convert all the DBNull values in the DataTable into empty string.
It is quite simple to do it but it would add some overhead especially if you are dealing with large DataTables. Check this link that shows how to do it if you are interested

Categories

Resources