Why does MySqlParameter Add parameter as 0 convert to null - c#

I'm adding a parameter to be called with a MySQL stored procedure like
List<MySqlParameter> MyParams = new List<MySqlParameter>();
MyParams.Add(new MySqlParameter("MyId", 0));
But for some reason when I look at MyParams, MyId value when stepping through my code, it is converted to null. Does anyone know why this is because if I assign the value from a int variable like below it is fine
int id = 0;
List<MySqlParameter> MyParams = new List<MySqlParameter>();
MyParams.Add(new MySqlParameter("MyId", id));

Well, You fell into the corner case of c# that literal 0 can be converted to Enum implicitly
An implicit enumeration conversion permits the decimal-integer-literal 0 to be converted to any enum-type
Reference
So, new MySqlParameter("MyId", 0) is compiled into MySqlParameter(string,MySqlDbType) rather than MySqlParameter(string,object) as the result your value 0 is ignored.
new MySqlParameter("MyId", id) this works because implicit conversions to enum works only when the value is literal not for variables. So It is clear that this gets compiled into MySqlParameter(string,object) resulting the expected results.
new MySqlParameter("MyId", (object)0)//this solves the problem
or this
New MySqlParameter("MyId", MySqlDbType.Int).Value = 0
BTW as #Suraj Singh pointed you may have to use #MyId instead of MyId.
Hope this helps

Use caution when you use this overload of the SqlParameter constructor to specify integer parameter values. Because this overload takes a value of type Object, you must convert the integral value to an Object type when the value is zero ---MSDN
Hope it's applicable for MySql too.
MyParams.Add(New MySqlParameter("#MyId", MySqlDbType.int)).Value = 0;
or try
Parameters.AddWithValue("#MyId", 0);

In your database schema, Is MyId a Primary Key of type int? with allow null set to yes?
assigning a value of 0 to a PK with allow null, will result in NULL being assigned.
I suspect its the database setup and not the code at fault.

Related

Cannot assign null to an implicitly-typed variable

According to Visual Studio this is not ok:
var foo = null;
But this is ok:
var foo = false ? (double?)null : null;
Why? Is the (double?)null affecting also the null in the else branch?
Implicitly typed variable declaration/assignment serves two purposes:
Decides the value of the variable, and
Decides the type of the variable.
Your first declaration has null for the value, with no way to figure out the type (it could be anything derived from System.Object, or a Nullable<T>). That is why it is an error.
Your second declaration pinpoints the type as Nullable<double> because of the cast. That is why C# allows it.
It goes without saying that double? foo = null would be much easier to read.
Because compiler cannot predict the type of null. Null can be assigned to any nullable datatype also to any reference type variable. So for implicit conversion, you have to cast null to some specific type.
var dt = (DateTime?)null; // This is correct
var dt1 = null; // This will throw compile time error.
The second example has double? type and the compiler knows it. According to documentation
It is important to understand that the var keyword does not mean
"variant" and does not indicate that the variable is loosely typed, or
late-bound. It just means that the compiler determines and assigns the
most appropriate type.
The compiler should ensure the type match with var.
var foo = null;
The compiler can't identify the type of foo.
var foo = false ? (double?)null : null;
Now the foo has double? type.
Assigning null to a var to a value, VS can't identify what type gonna be (double,int,bool etc). Var is commonly used when you don't know what type your value gonna be.
Your second declaration pinpoints the type as Nullable that's why you don't get an exception/error.

Invalid Cast Exception While converting from smallint to Int32?

The code below fills the properties of my model from the DataReader.I made some properties Nullable and it isn't working since then.
foreach (var property in _properties)
{
property.SetValue(model, null, null);
if (columnsInDataReader.Contains(property.Name.ToLower()))
{
if (!(_dataReader[property.Name] == DBNull.Value))
property.SetValue(model, _dataReader[property.Name]);
}
}
The property is Int32? and the database column is smallint and the conversion fails.
Even if an implicit conversion from short to int? do exists, the issue here arises from the fact that the data reader returns a boxed short, for which you need an unboxing conversion. In this specific case, the conversion is from object to a value type (int?).
The paragraph that matches your situation is the last of the cited section: since the object returned is a boxed short and not a boxed int, the cast fails.
As a concrete example, compare these two snippets:
short src = 42;
int? dst = (int?)src;
object src = (short)42;
int? dst = (int?)src;
While the first one succeeds, the second throws an InvalidCastException.
In your case, no explicit cast occurs, however the call to SetValue applies similar conversion rules, and therefore fails.
Summing up, in order to have the call succeed, you must choose the type of the property among those that are castable at runtime from the type of the extracted object, such as short and short?.

Actually what is Nothing - How it is converted

I have a VB class library with a test method. Which will return an Integer (sometimes Nothing will be returned).
Public Class Class1
Public Function testMethod() As Integer
'Some code here
Return Nothing
End Function
End Class
If I call the method in a VB Project, everything works great as expected. For example:
Dim output As String = testMethod().ToString() ' Works fine and output =""
But when I call the method by creating an object in C# application, it will throw error as null when the return value is Nothing.
VBTestLib.Class1 classObject = new VBTestLib.Class1();
string objectStringValue = classObject.testMethod().ToString(); // Error
Which means Nothing will be converted to null (null.ToString() is not allowed). Now consider the next example:
int objectIntValue = classObject.testMethod(); // objectIntValue = 0
Here Nothing will be converted to the default value of the int (0). I have extended the testing using dynamic then also the assigned value is 0. i.e.,
dynamic objectDynamicValue = classObject.testMethod();// objectDynamicValue = 0
So my question is, what is Nothing? How it will be converted when assigned to a C# type? Or shall I conclude that:
If a VB Method returns Nothing and the value is assigned to a C# variable of value type then the default value of method's return type will be assigned. And if it is assigned to a reference type variable then null will be assigned.
As I mentioned in the question (I assumed as well), Nothing Represents the default value of any data type (C# default(T)). For reference types, the default value is the null reference. For value types, the default value depends on whether the value type is nullable.
Here in my VB code the return value of the method is Integer (value type) So nothing will be its default value 0. That is why 0 is assigned to the dynamic type also. But it is not an alternative for null or it is not equivalent of null.

Getting type from list of icomparable

I have a dictionary of <string, IComparable> which means the value could Pretty much contain any value type.
Now when I update the value I want to convert a string input to the original type. I have tried all manner of converts but I don't seem to be having any success.
Example
Dictionary val = new Dictionary ();
Val.Add ("test", 1);
Val ["test"]="44"; //this is where I tried convert. But it's not always an int.
So if pre update the value was an int then it will be stored as an int. If it is a byte then it will be stored as an byte.
Can anyone point me in the right direction
Thanks
string id = "type";
val.Add(id, 1);
var type = val[id].getType();
val[id] = System.Convert.ChangeType("44", type);
Assuming that you know all the data types that will be used (int, byte etc), you could use the typeof operator to check for the type before, and then cast to that type from your data.
if (typeof(Val["test]) == int)
{
Val["test"] = int.parse("44");
}

in C#, why not use 'new' keyword when declaring an int?

When declaring an int..
int A = 10;
why not do the following instead?
int A = new Int()
A=10;
are both the same?
Because int is syntax sugar for Int32 which is a value type. Incidentally, so is the constant value 10 (an instance of the value type Int32). That's why you don't need to use new to create a new instance, but rather making a copy of 10 and calling it A. And similar syntax works with reference types as well, but with the difference that a copy isn't made; a reference is created.
Essentially, you can think of 10 as a previously declared instance of Int32. Then int A = 10 is just setting variable A to a copy of value 10 (if we were talking about reference types then A would be set to a reference to the instance instead of a copy).
To better illustrate here's another example:
struct SomeValueType {
public SomeValueType(){
}
}
public static readonly SomeValueType DEFAULT = new SomeValueType();
Then you can just do this:
SomeValueType myValueType = DEFAULT; // no neeed to use new!
Now imagine that SomeValueType is Int32 and DEFAULT is 10. There it is!
You may have seen Java, where int and Integer are two different things, and the latter requires you to write new Integer(10).
In C# int is a special alias for Int32, and for all intents and purposes they are the same. Indeed, to create a new instance of any type you'd have to write new Int32() or something.
However, because integers are primitive types in C# (and most programming languages), there is a special syntax for integer literals. Just writing 10 makes it an Int32 (or int).
In your example you are actually assigning a value to the a variable twice:
int a = new Int32(); // First assignment, a equals 0
a = 10; // Second assignment, a equals 10
You might imagine that since the second assignment overwrites the first, the first assignment is not required.
In C# there are two kinds of types, "reference types" and "value types". (Pointers are a third kind of type but let's not get into that.)
When you use the default constructor of a value type, all you are saying is "give me the default value of this value type". So new int() is neither more nor less than just saying 0.
So your program is the same as:
int i = 0;
i = 10;
if you write youe code like
int A = new Int();
the variable 'A' is assigned by the default value of int, so you can use variable 'A' without assigning a value to it(in c# we cant use a variable without assigning a value to it)
when using the keyword new it will automatically call the default constructor, it will assign default values to the variables.
int A = new Int();
It declares and initializes A to 0.
Basically, the new operator here is used to invoke the default constructor for value types. For the type int, the default value is 0.
It has the same effect as the following:
int A = 0;

Categories

Resources