10
\$\begingroup\$

I have code which works pretty well. I just need some of your opinions on how to write it better with fewer line of code. I want to use a ternary operator but I couldn't make it work so I did an if else instead.

Basically, I want to insert a price on my database. The price column is a nullable decimal. Even in my C# code, it's a nullable decimal as well.

if (items.Price == null)
{
    SqlParameter[] p =
    {
        new SqlParameter("@purchaseorder", items.PurchaseOrderItems),
        new SqlParameter("@modelnumber", items.ModelNumber), 
        new SqlParameter("@quantity", items.Quantity),
        new SqlParameter("@Price",  DBNull.Value),
        new SqlParameter("@Description", items.Description),
        new SqlParameter("@OrderNumber", items.OrderNumber),
        new SqlParameter("@Unit", items.Unit)
    };

    i = Dal.ExecuteNonQuery(sql,p);
}
else
{
    SqlParameter[] p =
    {
        new SqlParameter("@purchaseorder", items.PurchaseOrderItems),
        new SqlParameter("@modelnumber", items.ModelNumber), 
        new SqlParameter("@quantity", items.Quantity),
        new SqlParameter("@Price",  items.Price),
        new SqlParameter("@Description", items.Description),
        new SqlParameter("@OrderNumber", items.OrderNumber),
        new SqlParameter("@Unit", items.Unit)
    };

    i = Dal.ExecuteNonQuery(sql,p);
}
return i;

Can this be written without the else block?

\$\endgroup\$
2
  • \$\begingroup\$ Why not make life easier and use an ORM? "if you’re writing ADO.Net code by hand, you’re stealing from your employer or client." \$\endgroup\$
    – BCdotWEB
    Oct 10, 2016 at 9:19
  • 1
    \$\begingroup\$ @BCdotWEB As a few coders out there commented on that post, if people followed that advice we wouldn't have all of those pretty ORMs out there. Sometimes, doing it the old, artisanal way is the best way to learn - we learn about the difficulties and discover what problems we need to solve. \$\endgroup\$
    – T. Sar
    Oct 10, 2016 at 19:38

4 Answers 4

10
\$\begingroup\$

All you have to do is to use the ?: (ternary operator):

new SqlParameter("@Price", items.Price == null ? DBNull.Value : (object)items.Price)

Alternatively you could write an extension for it:

public static object PriceOrDefault(this ItemsType items)
{
    return items.Price == null ? DBNull.Value : (object)items.Price;
}

and use it instead:

new SqlParameter("@Price", items.PriceOrDefault())

As it turns out the Price is a decimal? so you may consider using the HasValue property and swap the values:

items.Price.HasValue ? (object)items.Price : DBNull.Value;

I find this looks better then the null-check.

\$\endgroup\$
4
  • \$\begingroup\$ Sorry, but i got a squiggly line underneath. s15.postimg.org/xmy26aduz/werw.png \$\endgroup\$ Oct 10, 2016 at 6:31
  • \$\begingroup\$ @DikongPrigm Just cust it to object. I edited the examples. SqlParameter excpects it anyway. \$\endgroup\$
    – t3chb0t
    Oct 10, 2016 at 6:36
  • \$\begingroup\$ That works.. Thank. I will wrap this to extension method. Thank you \$\endgroup\$ Oct 10, 2016 at 6:40
  • \$\begingroup\$ If you go with the helper method, I'd rather go with the more general object NulltoDBNull(object o) { return o != null ? o : DBNull.Value; }. \$\endgroup\$ Oct 10, 2016 at 14:47
11
\$\begingroup\$

The most terse and declarative way to write this is to use C#'s ?? operator. Your line becomes:

new SqlParameter("@Price",  (object)items.Price ?? DbNull.Value),

The expression here will either return the non-null value of the left operand (items.Price), or return the operand to the right instead.

If you hadn't guessed, the ?? operator is basically syntactic sugar for if operl != null ? operl : operr.

\$\endgroup\$
2
  • \$\begingroup\$ nice, I actually know this one too but didn't think it would work like this with a nullable :-] \$\endgroup\$
    – t3chb0t
    Oct 10, 2016 at 11:27
  • 2
    \$\begingroup\$ Using null coalescing is definitely the cleanest option. \$\endgroup\$
    – William
    Oct 10, 2016 at 11:53
5
\$\begingroup\$

This is down to personal taste, but if you do go down the extension method route suggested by t3chb0t, I'd consider making it generic so that you can reuse it for any future Nullable types you might use and you don't end up with a bunch of very similar looking functions for different fields. Something like this:

public static object DbValueOrNull<T>(this T? value) where T : struct
{
    return value.HasValue ? (object)value.Value : DBNull.Value;
}

Would allow:

new SqlParameter("@Price", items.Price.DbValueOrNull())
new SqlParameter("@SomeOtherNullableVar", items.SomeOtherNullableVar.DbValueOrNull())

etc.

\$\endgroup\$
1
  • \$\begingroup\$ wow, I believe I've never come up with the idea to use the nullable ? on a T + struct ;-) \$\endgroup\$
    – t3chb0t
    Oct 10, 2016 at 10:35
1
\$\begingroup\$

Have you taken a look at the System.Data.SqlTypes namespace - particularly SqlDecimal?

Building on some of the other answers, you can use SqlDecimal and the ?? operator as follows:

new SqlParameter("@Price",  items.Price ?? SqlDecimal.Null),
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.