Working with Nulls


Author
Message
Ger Cannoll
Ger Cannoll
Advanced StrataFrame User (582 reputation)Advanced StrataFrame User (582 reputation)Advanced StrataFrame User (582 reputation)Advanced StrataFrame User (582 reputation)Advanced StrataFrame User (582 reputation)Advanced StrataFrame User (582 reputation)Advanced StrataFrame User (582 reputation)Advanced StrataFrame User (582 reputation)Advanced StrataFrame User (582 reputation)
Group: StrataFrame Users
Posts: 430, Visits: 507
I dont particulalrly like working with nulls. I know there is an option in SF for repacing null values with a different value. I am considering goint back a step to the database set up. I notice there is a property on each filed called 'Default Vlaue or Binding' . I have played around with this and noticed that if i insert ' ' (Space within single quotes) for chrarcter and date fields, or 0 (Zero) fro numeric fields, it seems to default to a Non Null when I add a record (In SSMS at any rate) i.e. Spaces for character fields and Zero for numeric fields, which is just what I want (Similar to VFP if you add a record)

I would welcome any suggestions, if this is a good idea or if there are any 'Gotchas' down the line.

Replies
Ger Cannoll
Ger Cannoll
Advanced StrataFrame User (582 reputation)Advanced StrataFrame User (582 reputation)Advanced StrataFrame User (582 reputation)Advanced StrataFrame User (582 reputation)Advanced StrataFrame User (582 reputation)Advanced StrataFrame User (582 reputation)Advanced StrataFrame User (582 reputation)Advanced StrataFrame User (582 reputation)Advanced StrataFrame User (582 reputation)
Group: StrataFrame Users
Posts: 430, Visits: 507
Hi Greg. thanks for yur detailed reply

I used to use more DEFAULT constraints within SQL (and sometimes triggers), but the problem there is that the application won't know about these defaults until AFTER the record has been saved. I find it much easier to use the SetDefaultValues event handler to set defaults, which are set when the new record in the BO is created and thus show in any bound controls immediately.

If I use defaults within Sql, does this cause any issues in the BO , when I am saving, testing etc. What you seem to be saying is that, if I for instance Add a record, and I have a Default of Zero set up in Sql only , The BO will initially be populated with NUll (Unless I have a default set in SF). I guess if this is the case , and within the BO I try to , for instance , add two fields, once which may be a Null, this might give some errors

Greg McGuffey
Greg McGuffey
Strategic Support Team Member (2.8K reputation)
Group: Forum Members
Posts: 2K, Visits: 6.6K
Yeah, this can get confusing. It helps to understand how things are working (at least it helped me). The first thing to remember/understand is that the BO is essentially disconnected from the database, thus when you create a new record in the BO, it isn't talking to the database just yet. As I understand it, the process of creating a new row is something like this (kind of medium level view) when you add a new record to a BO from a maintenance form:



1. Add() is called on BO.

2. BO creates a DataRow and adds it to the underlying DataTable within the BO (standard ADO stuff). The values of the items in the row are all NULL.

3. The SetDefaultValues event is raised. You can set the values of items within the row at this time, before anybody will be able to access them.

4. The BO will update any bound controls. During this process the strongly typed properties of the BO are accessed. It is here that we will get errors if the value within the underlying DataRow is NULL and the property is just doing a straight access of that item. I.e. if the property is an int, and the value in the DataRow is NULL, a invalid casting exception is thrown as .NET can't cast a NULL into an int. The code would look something like this (this would be in a property called MyColumn):



'-- Vb version...bombs if value in DataRow is Null

Return CType(Me.CurrentDataRow.Item("MyColumn"), Integer)



// C# version...bombs if value in DataRow is Null

return (int)this.CurrentDataRow.Item["MyColumn"];




When you setup the Return Alternate on Null or Use NullableGeneric options in the BO mapper, all it is doing is adding code to the property Get/Set (depending on setup) that handles the value being null in the DataRow. Something like this when you use Return Alternate on Null:



'-- Vb version...handles value in DataRow being Null

Dim value As Object = Me.CurrentDataRow.Item("MyColumn")

If value Is DbNull.Value Then

  Return String.Empty

Else

  Return CType(Me.CurrentDataRow.Item("MyColumn"), Integer)

End If



// C# version...handles value in DataRow being Null

Object value = this.CurrentDataRow.Item["MyColumn"];

if (value = DbNull.Value) {

  return String.Empty;

} else {

  return (int)this.CurrentDataRow.Item["MyColumn"];

}




5. The user then enters information into some UI control.

6. Via binding, the value in the BO is updated. This is done by accessing the strongly typed properties and would use code something like:



'-- VB version

Me.CurrentDataRow.Item("MyColumn") = value



//-- C# version

this.CurrentDataRow.Item["MyColumn"] = value;




You'll never get into trouble here (unless the property has a rule to not allow nulls, in which case the BO would handle raising that error and notifying the user), because the value within the DataRow is an object...it accepts anything. If you setup the field to set a null on alternate value, the code changes a bit to:



'-- VB version

If value <> String.Empty Then

  Me.CurrentDataRow.Item("MyColumn") = value

Else

  Me.CurrentDataRow.Item("MyColumn") = String.Empty

End If

  Me.CurrentDataRow.Item("MyColumn") = value



//-- C# version

if (value != String.Empty) {

  this.CurrentDataRow.Item["MyColumn"] = value;

} else {

  this.CurrentDataRow.Item["MyColumn"] = String.Empty;

}




7. The user continues to enter data into bound controls, resulting in updating of the BO's underlying DataTable to have the appropriate values.

8. The Save button is clicked (or Save() is called).

9. The BO the produces a SQL call, which could be either a SQL statement or a call to a sproc. It will include the values of every field in the BO (minus those excluded via the FieldsToExcludeFromInsert property).

10. The SQL call is sent to SQL server to be executed. This is where any defaults setup at the db level come into play (and triggers, constraints, etc.). As you can see, the BO won't even know that these defaults have been set until it is refreshed with the data for this record (I'm a little fuzzy on if that happens automatically or if you'd need to make a call to have it happen).



Based on how I understand this works, you can see that even if you have defaults set at the db, the BO will throw an exception long before the db has a chance to set that default. This means that you have to also set defaults within the SetDefaultValues event handler. Now, the code posted by Peter at http://forum.strataframe.net/Topic10223-6-1.aspx shows a nice way to set those defaults from the defaults defined within the db. Kind of the best of both worlds.



I hope that helps you understand how defaults work (this is of course assuming I got the process pretty close to right).

GO

Merge Selected

Merge into selected topic...



Merge into merge target...



Merge into a specific topic ID...





Similar Topics

Reading This Topic

Login

Explore
Messages
Mentions
Search