ASP.NET : EF 5.X - Conversion Error - c#

I am trying to pull information out of a database and then add the values together. I have no issue when pulling the information out of the database however, there seems to be a conversion error when I am adding the values.
Cannot implicitly convert type 'double?' to 'double'. An explicit conversion exists (are you missing a cast?)
Outside where I am querying I have this:
var addition = 0.0;
When I pull the data out the Database, I try to add the value to this:
addition = addition + clear;
Both addition and clear are the same datatype which is why I am confused why it would need to do any conversion? (both Double's).
Extra information: clear comes from :
var clear = tbl_detail[a].AmountCleared;
and tbl_detail is an array of the queried data.
Could anyone possibly reference why I am receiving this error? Or possibly point me in the right direction because I am not understand why:
It needs to convert anything since they're the same datatype and
What a cast actually is because Google isn't really helping me when I am searching any of this.

It looks like AmountCleared is a nullable double (double?). You could do this:
addition += clear.Value
This will throw a InvalidOperationException if the Clear is null.
[Edit] You could also use addition += clear ?? 0.0 if you would like to use a default value for nulls.
You could change AmoutCleared into a double. I suspect that you created this through a designer or database first and used 'allow nulls' on the database column, which is why your are getting a nullable type. So you would have to change the database type to not 'allow nulls'. But without seeing the definition of the data type tbl_detail[a] or knowing how you generated it, I cannot help you much further.

AmountCleared is actually a Nullable type (Nullable) which allows C# value types to represent SQL server Nulls (Value types can never be assigned the value of null)
You can get the underlying value of the nullable type by simply calling .Value property, however this will throw a InvalidOperationException if the value is null, you can check if it has a value by calling .HasValue
Try this:
addition += clear.HasValue ? clear.Value : 0;

clear is a nullable value
to safely manipulate nullables use:
if(clear.hasValue)
{
addition += clear.Value;
}
You can also use the null coalescing operator ?? to fallback to a default value if the provided value is null
addition += clear ?? 0.0;

Related

Roundtrip unbounded type parameters through object

An unconstrained type parameter can be a nullable reference, non-nullable reference, value type or nullable value type.
Is it possible to roundtrip a parameter through object[?] ?
The following simplified code demonstrates the problem:
public static void Foo<U>(U unconstrainedParameter)
{
object? nullableObject = unconstrainedParameter;
U assignBack = (U)nullableObject; // [CS8600] Converting null literal or possible null value to non-nullable type.
}
If we change nullableObject to type object then I get the error even at the assignment.
Is there some "trick" to do this roundtrip conversion without the need to suppress the warning (by using a nullable object and then ! when converting back)
The problem here is that U can be both null and not null. Given that the goal is to catch errors C# does the following:
when reading U it is assumed that the value can be null
when writing to U it is assumed that U could be non-nullable
Hence there is no possible workaround, since the casts can lead to errors in the general case. We just have additional information in the given scenario where we know this cannot happen.

How null values was entered to datetime prior to Nullable types?

Nullable types was introduced in .NET 3.X. Assume i have DB table with column of type datetime that accepts null values. If the column data suppose to come from a windows forms client, How do i created a property of type datetime and make it accept null so i can send null values to my DB table column? How this was done in prior versions of .NEt?
I'm assuming by your question that you're using a .NET version older than .NET 2.0.
If that's the case you have a few options:
Use a "magic" date value to represent "null". Usually DateTime.MinValue or DateTime.MaxValue
Add a property to your class IsNull{Column} (or {Column}IsNull}) that would be true if the value is "null".
Nullable types was introduced in .NET 3.X
No, they were introduced in .NET 2.0. See the documentation.
How do i created a property of type datetime and make it accept null so i can send null values to my DB table column?
You couldn't. Typically people used a magic value of DateTime.MinValue to represent null, and then made sure that their object/database translation layer converted that to a SQL null appropriately. An alternative was to have a separate bool property to indicate the presence of a "real" value - or a separate type like SqlDateTime.
Nullable types in DB have no connection to nullables in C#'s value types. In fact, passing null as an argument doesn't count as passing SQL NULL - instead, it means "the argument wasn't passed after all" - that's actually a big difference. Instead, you used (and still use) DBNull.Value, which is a special value that the DB system understands.
And as Jon says in his answer, on the application layer, you used a magic value, like DateTime.MinValue, and just had something like:
cmd.Parameters.AddWithValue("#Par",
par == DateTime.MinValue ? (object)DBNull.Value : par);
You can do a lot of hacks, but orginial Solotion is to set ShowCheckBox of the datetTimePicker to true.
So when checkbox is unChecked, the value of datetimepicker will be null.

Updating a Bit Field with Null

am getting this error once i try to update a bit field with null. please note that technically the bit is set to 'allow null'.
am getting this error :
'Object of type 'System.DBNull' cannot be converted to type 'System.Nullable`
When I do this :
e.NewValues.Add("IdleBlock", DBNull.Value);
Try using an actual null instead of DBNull.Value. As you can see in the error message it's trying to convert the latter into a null, so I'm guessing EF wants a proper null value and handle conversion on it's own.
Edit: Err, actually I think I'm wrong here. It wants a System.Nullable not a null. Try passing it a new System.Nullable with Value set to null?

how to handle null values for SQLDecimal datatype in FileHelper classes

I am trying to load a file using FileHelpers (like it already except for this one issue :P )
I have to save CSV file data into the database, and so am using a SqlDecimal datatype to store the decimal values of the CSV files.
[FileHelpers.FieldOptional()]
[FileHelpers.FieldConverter(typeof(SqlDecimalConverter))]
public SqlDecimal Rate;
All this works fine, until I have a blank value for the FixRate1. This is flagged up with an error.
"Warn Exception:Null Value found for
the field 'Rate' in the class
'SWTrade'. You must specify a
FieldNullValueAttribute because this
is a ValueType and canĀ“t be null."
I tried putting [FileHelpers.FieldNullValue(SqlDecimal.Null)] but it obviously throws an error.
An attribute argument must be a
constant expression, typeof expression
or array creation expression of an
attribute parameter type
Even though I override the FieldToString method in the SqlDecimalConverter class, the function is not called, when reading the data.
Well, this being the case, is there a way I can assign any null value or even some other hardcoded value to the Rate data, which I can then replace with a null direclty in my own logic ?
Please do let me know if you would need more details.
Thanks in advance.
The other comments are right u need to use
private decimal? internalRate;
And later create a property for the conversion, in fact the library only autoconverts native types and SqlDecimal is not one.
public SqlDecimal? Rate
{
get
{
if (internalRate.HasValue)
return new SqlDecimal(internalRate.Value);
else
return null;
}
}
PS: If u want to go to the custom converter way, to use it for read u need to override the method StringToField (FieldToString is called for writing)
Hope this helps :)
You could try using a Nullable type. If you are using a Nullable type then you don't need to specify the FieldNullValue attribute.
[FileHelpers.FieldConverter(typeof(SqlDecimalConverter))]
public SqlDecimal? Rate;
That approach works fine with DateTime using the FileHelpers built in type converter.
If that does not work then you could assign a default value that you could treat as a null. But that can be problematic if there is an actual value that corresponds to the chosen default value:
[FieldNullValue(typeof(SqlDecimal), "-1")]
[FileHelpers.FieldConverter(typeof(SqlDecimalConverter))]
public SqlDecimal Rate;
Update
I just did a test and simply using a decimal? type works fine. Then you can convert it in your code to the proper SqlType to access the database. I think that is the easiest approach.
So the field would just look like:
public decimal? Rate;
no attributes required.
I've never worked with FileHelpers, but you could try instead:
[FileHelpers.FieldNullValue(null)]
public SqlDecimal? Rate;
In addition to your other attributes, of course.
Note the big change here - I added a question mark to SqlDecimal to make it a nullable type.
Then you can use Rate.HasValue to se whether it's null or not and Rate.Value to access the SqlDecimal if HasValue is true.
Something like this will properly use SqlDecimal.Null after you parse the file:
SqlDecimal trueRate = (Rate.HasValue ? Rate.Value : SqlDecimal.Null);
Edit - It's possible that if you make Rate nullable (SqlDecimal?) you don't even need the "FieldNullValue" attribute. Again, I'm not familiar with the library. :(
Why can't you use Decimal or an appropriate .net datatype instead of SqlDecimal?
I am suggesting that you should change the code to public Decimal? Rate; instead.

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