In my database, in one of the table I have a GUID column with allow nulls. I have a method with a Guid? parameter that inserts a new data row in the table. However when I say myNewRow.myGuidColumn = myGuid I get the following error: "Cannot implicitly convert type 'System.Guid?' to 'System.Guid'."
The ADO.NET API has some problems when it comes to handling nullable value types (i.e. it simply doesn't work correctly). We've had no end of issues with it, and so have arrived at the conclusion that it's best to manually set the value to null, e.g.
myNewRow.myGuidColumn = myGuid == null ? (object)DBNull.Value : myGuid.Value
It's painful extra work that ADO.NET should handle, but it doesn't seem to do so reliably (even in 3.5 SP1). This at least works correctly.
We've also seen issues with passing nullable value types to SqlParameters where the generated SQL includes the keyword DEFAULT instead of NULL for the value so I'd recommend the same approach when building parameters.
OK; how is myGuidColumn defined, and how is myGuid defined?
If myGuid is Guid? and myGuidColumn is Guid, then the error is correct: you will need to use myGuid.Value, or (Guid)myGuid to get the value (which will throw if it is null), or perhaps myGuid.GetValueOrDefault() to return the zero guid if null.
If myGuid is Guid and myGuidColumn is Guid?, then it should work.
If myGuidColumn is object, you probably need DBNull.Value instead of the regular null.
Of course, if the column is truly nullable, you might simply want to ensure that it is Guid? in the C# code ;-p
same as Greg Beech's answer
myNewRow.myGuidColumn = (object)myGuid ?? DBNull.Value
You have to cast null to a nullable Guid, this how it worked for me :
myRecord.myGuidCol = (myGuid == null) ? (Guid?)null : myGuid.Value
Try System.Guid.Empty where you want it to be null
If you want to avoid working with nullable GUIDs in your c# code (personally, I often find it cumbersome to work with nullable types) you could somewhere early assign Guid.Empty to the .NET data which is null in the db. That way, you don't have to bother with all the .HasValue stuff and just check if myGuid != Guid.Empty instead.
or:
internal static T CastTo<T>(object value)
{
return value != DBNull.Value ? (T)value : default(T);
}
You can use a helper method:
public static class Ado {
public static void SetParameterValue<T>( IDataParameter parameter, T? value ) where T : struct {
if ( null == value ) { parameter.Value = DBNull.Value; }
else { parameter.Value = value.Value; }
}
public static void SetParameterValue( IDataParameter parameter, string value ) {
if ( null == value ) { parameter.Value = DBNull.Value; }
else { parameter.Value = value; }
}
}
If you are into extension methods...
/// <summary>
/// Returns nullable Guid (Guid?) value if not null or Guid.Empty, otherwise returns DBNull.Value
/// </summary>
public static object GetValueOrDBNull(this Guid? aGuid)
{
return (!aGuid.IsNullOrEmpty()) ? (object)aGuid : DBNull.Value;
}
/// <summary>
/// Determines if a nullable Guid (Guid?) is null or Guid.Empty
/// </summary>
public static bool IsNullOrEmpty(this Guid? aGuid)
{
return (!aGuid.HasValue || aGuid.Value == Guid.Empty);
}
Then you could say:
myNewRow.myGuidColumn = myGuid.GetValueOrDBNull();
NOTE: This will insert null when myGuid == Guid.Empty, you could easily tweak the method if you want to allow empty Guids in your column.
Guid? _field = null;
if (myValue!="")//test if myValue has value
{
_field = Guid.Parse(myValue)
}
Related
I have a class which contains a nullable strings, I want to make a check to see whether they stay null or somebody has set them.
simliar to strings, the class contains integers which are nullable, where i can perform this check by doing an equality comparison
with the .HasValue() method - it seems like strings dont have this?
So how do check whether it goes from null to notNull?
public class Test
{
public string? a
public string? b
public int? c
}
var oldQ = new Test(c=123)
var newQ = new Test(c=546)
bool isStilValid = newQ.c.HasValue() == oldQ.c.HasValue() //(this is not possible?)&& newQ.b.HasValue() == oldQ.b.HasValue()
why is this not possible?
HasValue property belongs to Nullable<T> struct, where T is also restricted to be a value type only. So, HasValue is exist only for value types.
Nullable reference types are implemented using type annotations, you can't use the same approach with nullable value types. To check a reference type for nullability you could use comparison with null or IsNullOrEmpty method (for strings only). So, you can rewrite your code a little bit
var oldQ = new Test() { c = 123 };
var newQ = new Test() { c = 456 };
bool isStilValid = string.IsNullOrEmpty(newQ.b) == string.IsNullOrEmpty(oldQ.b);
Or just use a regular comparison with null
bool isStilValid = (newQ.b != null) == (oldQ.b != null);
Only struct in C# have HasValue method, but you can simple create your own string extension as below and that will solve your problem.
public static class StringExtension {
public static bool HasValue(this string value)
{
return !string.IsNullOrEmpty(value);
}
}
I hope this is helpful for someone.
The equivalent comparing to null would be:
bool isStillValid = (newQ.c != null) == (oldQ.c != null) && (newQ.b != null) == (oldQ.b != null);
That's the equivalent to your original code, but I'm not sure the original code is correct...
isStillValid will be true if ALL the items being tested for null are actually null. Is that really what you intended?
That is, if newQ.c is null and oldQ.c is null and newQ.b is null and oldQ.b is null then isStillValid will be true.
The Nullable<T> type requires a type T that is a non-nullable value type for example int or double.
string typed variables are already null, so the nullable string typed variable doesn't make sense.
You need to use string.IsNullOrEmpty or simply null
I have an object of type Employee which has a Guid property. I know if I want to set to null I must to define my type property as nullable Nullable<Guid> prop or Guid? prop.
But in my case I'm not able to change the type of the prop, so it will remains as Guid type and my colleague and I we don't want to use the Guid.Empty.
Is there a way to set my property as null or string.empty in order to restablish the field in the database as null.
I have a mechanism to transform from string.empty to null but I will change many things if the would change to accept a empty guid to null.
Any help please!
Is there a way to set my property as null or string.empty in order to restablish the field in the database as null.
No. Because it's non-nullable. If you want it to be nullable, you have to use Nullable<Guid> - if you didn't, there'd be no point in having Nullable<T> to start with. You've got a fundamental issue here - which you actually know, given your first paragraph. You've said, "I know if I want to achieve A, I must do B - but I want to achieve A without doing B." That's impossible by definition.
The closest you can get is to use one specific GUID to stand in for a null value - Guid.Empty (also available as default(Guid) where appropriate, e.g. for the default value of an optional parameter) being the obvious candidate, but one you've rejected for unspecified reasons.
Guid? myGuidVar = (Guid?)null;
It could be. Unnecessary casting not required.
Guid? myGuidVar = null;
Since "Guid" is not nullable, use "Guid.Empty" as default value.
Choose your poison - if you can't change the type of the property to be nullable then you're going to have to use a "magic" value to represent NULL. Guid.Empty seems as good as any unless you have some specific reason for not wanting to use it. A second choice would be Guid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff") but that's a lot uglier IMHO.
You can use typeof(Guid), "00000000-0000-0000-0000-000000000000" for DefaultValue of the property.
you can make guid variable to accept null first using ? operator then you use Guid.Empty or typecast it to null using (Guid?)null;
eg:
Guid? id = Guid.Empty;
or
Guid? id = (Guid?)null;
extrac Guid values from database functions:
#region GUID
public static Guid GGuid(SqlDataReader reader, string field)
{
try
{
return reader[field] == DBNull.Value ? Guid.Empty : (Guid)reader[field];
}
catch { return Guid.Empty; }
}
public static Guid GGuid(SqlDataReader reader, int ordinal = 0)
{
try
{
return reader[ordinal] == DBNull.Value ? Guid.Empty : (Guid)reader[ordinal];
}
catch { return Guid.Empty; }
}
public static Guid? NGuid(SqlDataReader reader, string field)
{
try
{
if (reader[field] == DBNull.Value) return (Guid?)null; else return (Guid)reader[field];
}
catch { return (Guid?)null; }
}
public static Guid? NGuid(SqlDataReader reader, int ordinal = 0)
{
try
{
if (reader[ordinal] == DBNull.Value) return (Guid?)null; else return (Guid)reader[ordinal];
}
catch { return (Guid?)null; }
}
#endregion
I think this is the correct way:
Guid filed = Guid.Empty;
Basically I want the following generic function:
public string StringOrNull<T> (T value)
{
if (value != null)
{
return value.ToString();
}
return null;
}
I know I could use a constraint such as where T: class, but T can be a primitive type, Nullable<>, or a class. Is there a generic way to do this?
Edit
Turns out I jumped the gun. This actually works just fine as this sample shows:
class Program
{
static void Main(string[] args)
{
int i = 7;
Nullable<int> n_i = 7;
Nullable<int> n_i_asNull = null;
String foo = "foo";
String bar = null;
Console.WriteLine(StringOrNull(i));
Console.WriteLine(StringOrNull(n_i));
Console.WriteLine(StringOrNull(n_i_asNull));
Console.WriteLine(StringOrNull(foo));
Console.WriteLine(StringOrNull(bar));
}
static private string StringOrNull<T>(T value)
{
if (value != null)
{
return value.ToString();
}
return null;
}
}
default Keyword in Generic Code
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.
Here's a fun one:
public static class ExtensionFunctions{
public static string ToStringOrNull( this object target ) {
return target != null ? target.ToString() : null;
}
}
The cool part? This will work:
( (string) null ).ToStringOrNull();
So will this:
5.ToStringOrNull();
Extension functions are pretty awesome... they even work on null objects!
If you pass a primitive type, it will automatically be boxed, so you don't need to worry about the null comparison. Since boxing occurs automatically, you can even explicitly compare an int to null without an error, but the result will always be false (and you'll probably get a compiler warning telling you so).
You can use default keyword to return the default of T:
public string StringOrNull<T> (T value)
{
.....
return default(T).ToString();
}
Why generic?
public string StringOrNull (object value)
{
if (value != null){
return value.ToString();
}
return null;
}
I got tired of writing the following code:
/* Commenting out irrelevant parts
public string MiddleName;
public void Save(){
SqlCommand = new SqlCommand();
// blah blah...boring INSERT statement with params etc go here. */
if(MiddleName==null){
myCmd.Parameters.Add("#MiddleName", DBNull.Value);
}
else{
myCmd.Parameters.Add("#MiddleName", MiddleName);
}
/*
// more boring code to save to DB.
}*/
So, I wrote this:
public static object DBNullValueorStringIfNotNull(string value)
{
object o;
if (value == null)
{
o = DBNull.Value;
}
else
{
o = value;
}
return o;
}
// which would be called like:
myCmd.Parameters.Add("#MiddleName", DBNullValueorStringIfNotNull(MiddleName));
If this is a good way to go about doing this then what would you suggest as the method name? DBNullValueorStringIfNotNull is a bit verbose and confusing.
I'm also open to ways to alleviate this problem entirely. I'd LOVE to do this:
myCmd.Parameters.Add("#MiddleName", MiddleName==null ? DBNull.Value : MiddleName);
but that won't work because the "Operator '??' cannot be applied to operands of type 'string and 'System.DBNull'".
I've got C# 3.5 and SQL Server 2005 at my disposal if it matters.
Cast either of your values to object and it will compile.
myCmd.Parameters.Add("#MiddleName", MiddleName==null ? (object)DBNull.Value : MiddleName);
You can avoid the explicit cast to object using SqlString.Null instead of DBNull.Value:
MiddleName ?? SqlString.Null
There are corresponding types for int, datetime, and so forth. Here's a code snippet with a couple more examples:
cmd.Parameters.AddWithValue("#StartDate", StartDate ?? SqlDateTime.Null);
cmd.Parameters.AddWithValue("#EndDate", EndDate ?? SqlDateTime.Null);
cmd.Parameters.AddWithValue("#Month", Month ?? SqlInt16.Null);
cmd.Parameters.AddWithValue("#FormatID", FormatID ?? SqlInt32.Null);
cmd.Parameters.AddWithValue("#Email", Email ?? SqlString.Null);
cmd.Parameters.AddWithValue("#ZIP", ZIP ?? SqlBoolean.Null);
Personally this is what I would do with an extension method (make sure this goes into a static class)
public static object GetStringOrDBNull(this string obj)
{
return string.IsNullOrEmpty(obj) ? DBNull.Value : (object) obj
}
Then you'd have
myCmd.Parameters.Add("#MiddleName", MiddleName.GetStringOrDBNull());
myCmd.Parameters.Add("#MiddleName", MiddleName ?? (object)DBNull.Value);
#David Thanks for your suggestion. The following method works great!
MiddleName ?? (object)DBNull.Value
Yeap, we'd all love to do myCmd.Parameters.Add("#MiddleName", MiddleName ?? DBNull.Value);. Or better still, have the freakin' SqlClient layer understand that CLR null should be mapped to DBNull.Value when adding a parameter. Unfortunately the .Net type system closes the first alternative, and the implementation of SqlClient closes the second.
I'd go with a well known function name, like Coalesce or IsNull. Any DB developer will recognize what they do in an instant, from the name alone.
I'd rather give you two totally different suggestions:
Use an ORM. There are plenty of non-intrusive ORM tools.
Write your own wrapper for building commands, with a cleaner interface. Something like:
public class MyCommandRunner {
private SqlCommand cmd;
public MyCommandRunner(string commandText) {
cmd = new SqlCommand(commandText);
}
public void AddParameter(string name, string value) {
if (value == null)
cmd.Parameters.Add(name, DBNull.Value);
else
cmd.Parameters.Add(name, value);
}
// ... more AddParameter overloads
}
If you rename your AddParameter methods to just Add, you can use it in a very slick way:
var cmd = new MyCommand("INSERT ...")
{
{ "#Param1", null },
{ "#Param2", p2 }
};
I would suggest using nullable properties instead of public fields and an 'AddParameter' method (don't know if this code is optimized or correct, just off the top of my head):
private string m_MiddleName;
public string MiddleName
{
get { return m_MiddleName; }
set { m_MiddleName = value; }
}
.
.
.
public static void AddParameter(SQLCommand cmd, string parameterName, SQLDataType dataType, object value)
{
SQLParameter param = cmd.Parameters.Add(parameterName, dataType);
if (value is string) { // include other non-nullable datatypes
if (value == null) {
param.value = DBNull.Value;
} else {
param.value = value;
}
} else {
// nullable data types
// UPDATE: HasValue is for nullable, not object type
if (value.HasValue) // {{{=====================================================
{
param.value = value;
} else
{
param.value = DBNull.Value;
}
}
}
.
.
.
AddParameter(cmd, "#MiddleName", SqlDbType.VarChar, MiddleName);
Is it possible to overload the null-coalescing operator for a class in C#?
Say for example I want to return a default value if an instance is null and return the instance if it's not. The code would look like something like this:
return instance ?? new MyClass("Default");
But what if I would like to use the null-coalescing operator to also check if the MyClass.MyValue is set?
Good question! It's not listed one way or another in the list of overloadable and non-overloadable operators and nothing's mentioned on the operator's page.
So I tried the following:
public class TestClass
{
public static TestClass operator ??(TestClass test1, TestClass test2)
{
return test1;
}
}
and I get the error "Overloadable binary operator expected". So I'd say the answer is, as of .NET 3.5, a no.
According to the ECMA-334 standard, it is not possible to overload the ?? operator.
Similarly, you cannot overload the following operators:
=
&&
||
?:
?.
checked
unchecked
new
typeof
as
is
Simple answer: No
C# design principles do not allow operator overloading that change semantics of the language. Therefore complex operators such as compound assignment, ternary operator and ... can not be overloaded.
This is rumored to be part of the next version of C#. From http://damieng.com/blog/2013/12/09/probable-c-6-0-features-illustrated
7. Monadic null checking
Removes the need to check for nulls before accessing properties or methods. Known as the Safe Navigation Operator in Groovy).
Before
if (points != null) {
var next = points.FirstOrDefault();
if (next != null && next.X != null) return next.X;
}
return -1;
After
var bestValue = points?.FirstOrDefault()?.X ?? -1;
I was trying to accomplish this with a struct I wrote that was very similar Nullable<T>. With Nullable<T> you can do something like
Nullable<Guid> id1 = null;
Guid id2 = id1 ?? Guid.NewGuid();
It has no problem implicitly converting id1 from Nullable<Guid> to a Guid despite the fact that Nullable<T> only defines an explicit conversion to type T. Doing the same thing with my own type, it gives an error
Operator '??' cannot be applied to operands of type 'MyType' and
'Guid'
So I think there's some magic built into the compiler to make a special exception for Nullable<T>. So as an alternative...
tl;dr
We can't override the ?? operator, but if you want the coalesce operator to evaluate an underlying value rather than the class (or struct in my case) itself, you could just use a method resulting in very few extra keystrokes required. With my case above it looks something like this:
public struct MyType<T>
{
private bool _hasValue;
internal T _value;
public MyType(T value)
{
this._value = value;
this._hasValue = true;
}
public T Or(T altValue)
{
if (this._hasValue)
return this._value;
else
return altValue;
}
}
Usage:
MyType<Guid> id1 = null;
Guid id2 = id1.Or(Guid.Empty);
This works well since it's a struct and id1 itself can't actually be null. For a class, an extension method could handle if the instance is null as long as the value you're trying to check is exposed:
public class MyClass
{
public MyClass(string myValue)
{
MyValue = myValue;
}
public string MyValue { get; set; }
}
public static class MyClassExtensions
{
public static string Or(this MyClass myClass, string altVal)
{
if (myClass != null && myClass.MyValue != null)
return myClass.MyValue;
else
return altVal;
}
}
Usage:
MyClass mc1 = new MyClass(null);
string requiredVal = mc1.Or("default"); //Instead of mc1 ?? "default";
If anyone is here looking for a solution, the closest example would be to do this
return instance.MyValue != null ? instance : new MyClass("Default");