I am trying to make the optional parameter of a C# Method to be converted to DBNull (if it is null) to be added with Parameter.AddWithValue method.
I saw many solutions (Set a database value to null with a SqlCommand + parameters), extension methods, etc, but i wanted a single line solution.
command.Parameters.AddWithValue("#Municipio", municipio ?? DBNull.Value)don't work (Operator '??' cannot be applied to operands of type 'string' and 'System.DBNull')
The method: public static void Foo(string bar, string municipio = null)
Unfortunately i can't do string municipio = DBNull.Value because "default parameter must be a compile-time constant" (what i don't exactly understand the meaning).
I was able to make it work as such:
object obj = municipio == null ? command.Parameters.AddWithValue("#Municipio", DBNull.Value) : command.Parameters.AddWithValue("#Municipio", municipio);
I am very uncomfortable with this, seems like a JavaScript way of doing, i want something like:
if municipio == null ? command.Parameters.AddWithValue("#Municipio", DBNull.Value) : command.Parameters.AddWithValue("#Municipio", municipio);
But somehow i am not being able to make it work like this, perhaps im missing some syntax (i tried many parenthesis/etc combinations).
So my question is, is it good practice the one-line solution i reached, or should i replace it?
Updated to handle if the variable is not initialized.
Here is an example:
OracleParameter P_COUNTYCODE = new OracleParameter("P_COUNTYCODE", OracleDbType.Varchar2);
P_COUNTYCODE.Direction = ParameterDirection.Input;
P_COUNTYCODE.Value = countyCode.Length > 0 ? countyCode : (object)DBNull.Value;
try:
command.Parameters.AddWithValue("#Municipio", !string.IsNullOrEmpty(municipio) > 0 ? municipio : (object)DBNull.Value)
Related
I have the following code:
// TryGetAttributeValue returns string value or null if attribute not found
var attribute = element.TryGetAttributeValue("bgimage");
// Convert attribute to int if not null
if (attribute != null) BgImage = convert.ToInt32(attribute);
The thing I don't like is that I have to create a temp variable, attribute, in order to test if it's null or not, and then assign the value to the BgImage variable, which is a nullable int.
I was hoping I could figure out a way to write it all on one line, but I cannot figure a way. I even tried using a ternary statement, but got nowhere:
if (element.TryGetAttributeValue("bgimage") != null) ? BgImage = //Convert result to int : else null;
Realistically, my original two lines of code do the job. I was just hoping to pare it down to one line. But, if anyone knows how to do what I'm trying to accomplish, I'd love to learn how.
I recommend you to use Linq to Xml for parsing Xml (according to your attempt you have BgImage as nullable integer):
BgImage = (int?)element.Attribute("bgimage");
You also can assign some default value if BgImage is not nullable:
BgImage = (int?)element.Attribute("bgimage") ?? 0;
Assuming TryGetAttributeValue returns a string you could do something like
BgImage = convert.ToInt32(element.TryGetAttributeValue("bgimage") ?? "-1")
This would set BgImage to a default value (-1) if the attribute does not exist. If you would prefer to have BgImage set to null when there is no bgimage attribute then it gets a little bit clunkier
BgImage = element.TryGetAttributeValue("bgimage") != null ?
convert.ToInt32(element.TryGetAttributeValue("bgimage")) : (int?)null;
I am trying to populate a combobox with a list my query returns. When I execute my program it gives me a specified cast is not valid error ( I have it execute on page load event). Every field in the database I have to work with can be null except the primary key. So I tried using DBNull.Value but it can't get my (int)reader fields to work. I have supplied my code below for a better understanding. How can I get my (int)reader's to work with my statements, so they can read when there is a null value?
CustData cd = new CustData();
cd.CustomerID = (int)reader["CustomerID"];
cd.Name = reader["Name"] != DBNull.Value ? reader["Name"].ToString() : string.Empty;
cd.ShippingAddress = reader["ShippingAddress"] != DBNull.Value ? reader["ShippingAddress"].ToString() : string.Empty;
cd.ShippingCity = reader["ShippingCity"] != DBNull.Value ? reader["ShippingCity"].ToString() : string.Empty;
cd.ShippingState = reader["ShippingState"] != DBNull.Value ? reader["ShippingState"].ToString() : string.Empty;
cd.ShippingZip = (int)reader["ShippingZip"];
cd.BillingAddress = reader["BillingAddress"] != DBNull.Value ? reader["BillingAddress"].ToString() : string.Empty;
cd.BillingCity = reader["BillingCity"] != DBNull.Value ? reader["BillingCity"].ToString() : string.Empty;
cd.BillingState = reader["BillingState"] != DBNull.Value ? reader["BillingState"].ToString() : string.Empty;
cd.BillingZip = (int)reader["BillingZip"];
cd.Territory = reader["Territory"] != DBNull.Value ? reader["Territory"].ToString() : string.Empty;
cd.Category = reader["Category"] != DBNull.Value ? reader["Category"].ToString() : string.Emptyy
That is because int is not nullable. You need to use int? or nullable<int> (long hand) to allow it to be an int OR a null value.
You can then use the usual .HasValue and .Value etc to get the value from the item.
EDIT: To enhance the visibility of my comment to this answer. I would advise against checking for NULL and storing Zero into your property because then when you save back you are changing a Null to a Zero even though nothing has been changed by the system. Now, reports etc may distinguish between NULL and Zero (very often) and could start doing strange things!
Null does NOT equal zero!! If you assume it does as a work around... What happens if I truly do want to record zero? How do you differentiate between a real zero and a "was null now zero" trick? Do it right, save yourself the pain!
Use nullable int, or just make your control for your int's too
reader["ShippingZip"] != DBNull.Value ? (int)reader["ShippingZip"] : default(int);
You should use a nullable int for your variable and cast it, like (int?). Int can only have a value; nullable types can also be null. When you use a nullable type, you can look at the property .HasValue. Here is the MSDN page: http://msdn.microsoft.com/en-us/library/2cf62fcy.aspx
I'm creating an object for my database and I found a weird thing, which I don't understand:
I've an object which should reference a "language" by an ID, but this can be null, so my property is a int?(Nullable<int>)
so firstly I tried to use the object initializer:
myObject = new MyObject()
{
myNullableProperty = language == null ? null : language.id;
}
but it doesn't work! It tell me that null cannot be converted to int
But if I it in a if/else structure, I can put null in a var and then assign it to my properties.
Why is this acting like this?
You may try casting the null to int? as the ?: operator requires both operands to return the same type:
myNullableProperty = language == null ? (int?)null : language.id
This is because of a type mismatch. You must cast your null value to the int type.
The reason is, when using the ? operator the left and the right side of the : are required to be from the same type and typeof(null)!=typeof(int) so:
myNullableProperty = language == null ? (int?)null : language.id;
Most likely null is interpreted as object which obviously can't be assigned to int. You might want to use myNullableProperty = language == null ? (int?)null : language.id;
I have defined Class Person property Birthday as nullable DateTime? , so why shouldn’t the null coalescing operator work in the following example?
cmd.Parameters.Add(new SqlParameter("#Birthday",
SqlDbType.SmallDateTime)).Value =
person.Birthday ?? DBNull.Value;
The compiler err I got was "Operator '??' cannot be applied to operands of type 'System.DateTime?' and 'System.DBNull'"
The following also got a compile error :
cmd.Parameters.Add(new SqlParameter("#Birthday",
SqlDbType.SmallDateTime)).Value =
(person.Birthday == null) ? person.Birthday:DBNull.Value;
I added a cast to (object) as recommended by Refactor, and it compiled, but didn’t work properly and the value was stored in the sqlserver db as null in both cases.
SqlDbType.SmallDateTime)).Value =
person.Birthday ?? (object)DBNull.Value;
Can someone explain what is going on here?
I needed to use the following clumsy code:
if (person.Birthday == null)
cmd.Parameters.Add("#Birthday", SqlDbType.SmallDateTime).Value
= DBNull.Value;
else cmd.Parameters.Add("#Birthday", SqlDbType.SmallDateTime).Value =
person.Birthday;
The problem is that DateTime? and DBNull.Value are not the same type so you can't use the null coalescing operator on them.
In your case you can do person.Birthday ?? (object)DBNull.Value to pass a value of type object through to Add()
I prefer to iterate over my parameters just before executing the query, changing all instances of null to DBNull as appropriate, for example:
foreach (IDataParameter param in cmd.Parameters)
if (param.Value == null)
param.Value = DBNull.Value;
This lets me leave null values as-is and simply swap them out en masse later.
Your first problem is that for the ?? or ?: operator, the objects for either choice must be the same type. Here they are different type.
In my code, is there a shorthand that I can use to assign a variable the value of a object's property ONLY if the object isn't null?
string username = SomeUserObject.Username; // fails if null
I know I can do a check like if(SomeUserObject != null) but I think I saw a shorthand for this kind of test.
I tried:
string username = SomeUserObject ?? "" : SomeUserObject.Username;
But that doesn't work.
Your syntax on the second is slightly off.
string name = SomeUserObject != null ? SomeUserObject.Username : string.Empty;
In c# 6.0 you can now do
string username = SomeUserObject?.Username;
username will be set to null if SomeUSerObject is null.
If you want it to get the value "", you can do
string username = SomeUserObject?.Username ?? "";
The closest you're going to get, I think, is:
string username = SomeUserObject == null ? null : SomeUserObject.Username;
This is probably as close as you are going to get:
string username = (SomeUserObject != null) ? SomeUserObject.Username : null;
You can use ? : as others have suggested but you might want to consider the Null object pattern where you create a special static User User.NotloggedIn and use that instead of null everywhere.
Then it becomes easy to always do .Username.
Other benefits: you get / can generate different exceptions for the case (null) where you didn't assign a variable and (not logged in) where that user isn't allowed to do something.
Your NotloggedIn user can be a derived class from User, say NotLoggedIn that overrides methods and throws exceptions on things you can't do when not logged in, like make payments, send emails, ...
As a derived class from User you get some fairly nice syntactic sugar as you can do things like if (someuser is NotLoggedIn) ...
You're thinking of the ternary operator.
string username = SomeUserObject == null ? "" : SomeUserObject.Username;
See http://msdn.microsoft.com/en-us/library/ty67wk28.aspx for more details.
It is called null coalescing and is performed as follows:
string username = SomeUserObject.Username ?? ""