String.Empty != null

String.Empty != null

Old forum URL: forums.lhotka.net/forums/t/6633.aspx


Geeky posted on Thursday, March 19, 2009

Hi,

On line 2143 of Csla.Core.BusinessBase is the following:

            if (typeof(P) == typeof(string) && newValue == null)
              newValue = Utilities.CoerceValue<P>(typeof(string), field, string.Empty);

Is there a valid reason for this?  I know Rocky has posted elsewhere that null can be a problem for data binding (although I can't remember it ever affecting my projects on the web and in WinForms).

When a property is set, it should return the value that it has been passed.  Basically changing the value is horrible.  We need to duplicate SQL in order to test that an object can load a null value as we can't set the property to null.

I would like to remove this line, but before I do, I would like to know it would have any other effects (eg MobileFormatter).

Cheers

RockfordLhotka replied on Thursday, March 19, 2009

The primary issue is (was?) in WinForms, because data binding would throw null ref exceptions if a string property returned null. Maybe this is no longer the case.

I agree that in the case where "" and null are not the same from a business perspective this can be problematic. However, in that case you can't just use a TextBox either, because the user can't tell the difference between a "" and null since the TextBox control renders them the same way.

So where this difference actually matters, you'll typically need a second bool property for each string property so you can bind it to a checkbox or similar control associated with the textbox so the user knows whether the value is "" or null.

In other words, if null is being used correctly it is virtually never the case that the difference between "" and null for a string matters at the business object/UI layers - because if it actually does matter, the null state is managed in some other property.

Geeky replied on Friday, March 20, 2009

Thanks for the quick reply.  I agree with your point about the UI however if the BO needs to mirror the database, then null should be a valid value.  With regards to the UI, surely if setting the value converts null to string.empty, then surely getting the property should do the same?

Anyway CSLA is great - I still love it and will just remove that line I think :-).

ajj3085 replied on Friday, March 20, 2009

How will you overcome the fact that a text box will render null and String.Empty exactly the same?

lukky replied on Friday, March 20, 2009

Hi,

I don't know if this would be a solution for your use case, but the WinForms Binding object allows you to specify a string to represent NULL. Could you use that ?

Regards.

RockfordLhotka replied on Friday, March 20, 2009

That’s somewhat true. But you must remember that null and DbNull are not the same thing. They have different semantic behaviors and different meanings. So while you can treat them the same to a point, they really aren’t the same at all.

 

It doesn’t sound, from what you’ve said, like the business has any DbNull requirement. In other words, it doesn’t sound like there’s a business requirement to differentiate between a NULL and “” in a database value. Maybe there is, in which case you really need a comprehensive solution.

 

But if you are like 95% of the apps out there, this is actually a technical database issue, not a business issue. In this case, the typical answer is to use something like SafeDataReader to simply and automatically make sure the database always has NULL, and the object always has “”. No muss, no fuss. The business people are happy because they didn’t care about this to start with, and the database people are happy because they get to keep misusing NULL.

 

Yes, misusing. This is actually one of my pet peeves, and I’ve posted on the forum in the past about it. I won’t repeat my rant here, because it is possible that your business people do care about the difference between a value that was never entered and a value that was entered as blank – which is one of only three valid reasons a database should allow a NULL in a column (along with foreign key definition and empty date value).

 

Rocky

Geeky replied on Tuesday, March 24, 2009

The point is that the database may contain a null.  We need to test that we can retrieve a null value (we don't use SafeDataReader - we have our own IDataReader implementation).

If we can't set the value to null, then we can't test that we can retrieve null.

AFAIK, SafeDataReader only reads from the database and cannot ensure that an external process does not enter a null value.

Yes, on the UI we don't care about the difference between null and string.empty however, the UI is a small part of any application.

If CSLA ensured that a null string is never returned by a property, then I could understand your point, but it does not - it only ensures that if a property is set to null, the value is string.empty which results in confusing behaviour.  No one would set a nullable int to 0 just because it was null would they?

 

ajj3085 replied on Tuesday, March 24, 2009

Well, what exactly are you trying to test?  Your IDataReader implementation?  Or what happens if you feed data from your implementation into Csla?  If it's the former, you shouldn't be involving Csla at all in your testing.  If it's the latter, I would expect that you have some way to prefill your database.. just make sure that includes dropping a null in the relevent column.  If your BO doesn't care about the difference between null or an empty string, it should work either way.

The problem with your comparison to Nullable<int> is that it's very easy to see in a text box the difference between null and the value 0.  The same isn't true for null and an empty string.. both are displayed identically.  Csla only translates null to String.Empty if you're talking about a string field.... because you can't see the difference on the UI.

RockfordLhotka replied on Tuesday, March 24, 2009

I don’t think we’re understanding each other completely.

 

There are only three reasons to care about null values. Of those three, only one goes beyond the database: the scenario where the business logic cares about the difference between null and “”. That isn’t just a UI thing – it is a business logic thing.

 

Ask your users – the business stakeholders – whether the software needs to track whether a value is empty (“”) or has never been entered at all (null). If they say they care, then you need to use null throughout the app. If they look at you blankly, wondering what the heck you are talking about, then you don’t need to use null throughout the app.

 

I suspect you are in the latter situation. In that case, the fact that the database allows a null value instead of “” is a bug in the database design. This happens frequently, due to database designers that don’t understand the purpose of null, or database’s that evolve over time and get new columns, and the person adding the new column is too lazy to add the column, set the existing rows to have a valid default value, and then disable null values in the column.

 

Either way, many (most?) databases allow nulls where nulls shouldn’t be allowed.

 

Just because the database is broken doesn’t mean your business layer or UI layer should be complicated too. Use your data access layer to fix the problem. That’s the purpose behind SafeDataReader – but SafeDataReader is just one example of a broader solution to the problem – which is to have the DAL deal with the busted database design so the BL and UI don’t have to worry about it.

 

Rocky

Copyright (c) Marimer LLC