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
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.
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 :-).
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
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?
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