StrataFrame Forum

Handling Null Dates

http://forum.strataframe.net/Topic12633.aspx

By Randy Jean - 11/12/2007

Been away from this issue for a while - thought I had it figured out before but must have tabled it. Anyway, datetime is the only type in SQL we allow nulls to handle when a date can be empty. So, I've set the bizobj to AllowNullValuesOnNewRow = False but in SetDefaultValues I set:



Me.CurrentRow("ExpirationDate") = DBNull.Value



I'm using the strataframe dt picker control.



So, this all seems to work fine for adding records, etc. The problem comes in that if I navigate from a record that has a date to one that is null OR I navigate from a row with a null to a record with a date the buffer is dirty. If I set a breakpoint in the IsDirtyChanged event I see it is the Set Alternate on Null code causing this:





>BayerAcquire.exe!BayerAcquire.DCAReagentsBO.DCAReagentsBO_IsDirtyChanged(Object sender = {BayerAcquire.DCAReagentsBO}, System.EventArgs e = {System.EventArgs}) Line 124Basic

[External Code]

BayerAcquire.exe!BayerAcquire.DCAReagentsBO.set_ExpirationDate(Date value = #1/1/1800#) Line 306 + 0x42 bytesBasic

BayerAcquire.exe!BayerAcquire.DCAReagentsBO.Field_ExpirationDate_Descriptor.SetValue(Object component = {BayerAcquire.DCAReagentsBO}, Object Value = #1/1/1800#) Line 691 + 0x45 bytesBasic

[External Code]

BayerAcquire.exe!BayerAcquire.AppMain.Main() Line 21 + 0x6 bytesBasic

[External Code]





The partial class code looks like this:





'''

''' ExpirationDate

'''


'''


BusinessFieldDisplayInEditor(), _

Description("ExpirationDate"), _

DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)> _

Public Property [ExpirationDate]() As System.DateTime

Get

Dim loValue As Object

loValue = Me.CurrentRow.Item("ExpirationDate")

If loValue Is DBNull.Value Then

Return #1/1/1800#

Else

Return CType(loValue, System.DateTime)

End If

End Get

Set(ByVal value As System.DateTime)

Me.CurrentRow.Item("ExpirationDate") = value

End Set

End Property





How do I handle date fields when the date is optional (not required) and I don't want navigation to dirty the buffer? I also don't want to store 1/1/1800 in the DB.
By Peter Jones - 11/12/2007

Hi Randy,

We use DevExpress for our UI so we are different there but, like you, we mainly disallow nulls in the Db expect some dates and some FK's. In these cases the DB allows nulls of course and in the BO we set the date property to Nullable Generic - this works fine for us.

Cheers, Peter

By Randy Jean - 11/13/2007

Generic Null blows up with the SF datetime control for me. What I don't get is why the "Set" method is firing when I navigate vs. just the "Get" - I'm just trying to translate for display purposes. Seems the set should only fire when the user changes a value in the control or the value is changed programatically. I tried turning off the customization in BO mapper and that blows up with an error too when a Null is read.
By Trent L. Taylor - 11/13/2007

Randy,

This is that same issue that you had posted on another thread.  You need to Return Alternate Value on NULL and provide a #1/1/1800# as the return value.  Here is my other post: http://forum.strataframe.net/FindPost12657.aspx

By Randy Jean - 11/13/2007

Did this and my buffer is still dirty upon navigation when going from a record with a null to a record with a date or vice versa. If I navigate from null to null or date to date, buffer does not dirty. So, yes, the BO mapper "works" as far as translating the value correctly and nothing "blows up" and data is saved correctly, etc. But if the user did not change the date from null or vice versa why should the buffer be dirty prompting them to save? That's what I'm saying. I don't want this "behavior" or side-effect but the underlying data is being handled properly by the Set Alternate as you describe.



I'd be happy to do host a quick Crossloop (see http://www.crossloop.com) session with you to show you first hand what it's doing. And I also re-produced with the CRM sample customer maintenance so I can show you there as well.



Thanks, Randy
By Randy Jean - 11/13/2007

Here is what I wound up doing as a workaround and although its not ideal, it works for now:



In BO Mapper I set "Return Alternate on Null / Set Null on Alternate (value type)" and I put #1/1/1800# as the null replacement - this gets me the exact behavior I want as far as translating and handling nulls in the DB for dates. No more 1/1/1800 values stored in my database. Yay!



To prevent the dirty buffer syndrome when navigating between records with/without date values I set the BindingUpdateMode to OnValidation on the datetimepicker - of course, this means the control must lose focus in order to update the underlying data but I think this is a trade-off I can live with for now.



If you have any better ideas let me know.



Thanks, Randy
By StrataFrame Team - 11/16/2007

The OnValidation is actually the default for .NET binding... it prevents the controls from being so chatty with their underlying data source.  The only reason we switched to the OnPropertyChanged was because the MaintenanceFormToolstrip that we use... toolstrip buttons to not inherit from Control, so when you leave a control to click a toolstrip button (like Save), the focus is not moved from the textbox to the toolstrip button, so the Validating/Validate is not fired on the toolstrip.  It didn't work very well when the last piece of data you entere did not properly update back to the business object Wink, so we defaulted it to OnPropertyChanged. 

Thus, if you're not using toolstrips, then OnValidation will work fine, otherwise, watch out for the date-time picker being the last thing you had focus on when you went to the toolstrip.

By Randy Jean - 11/16/2007

Hi Ben,

It's starting to make sense now... I'm still a newbie at this .NET stuff, however, I'm realizing this is an issue I'm familiar with from my years with VFP. VFP toolbars also do not cause the current control to lose focus and therefore, the bound object doesn't get it's value in the same way the OnValidating binding behaves. In VFP, the framework we used the save methods would call a custom WriteBuffer() method that essentially adds a "dummy" control on the fly, set focus to that (disabling any validation that may occur), perform the save and then remove the dummy control and set focus back to the previous active control. Although it seemed to be quite a hack, it works quite nicely. I wonder if there is a way to add something like this in Strataframe. Not a show stopper for now, but as we get into doing more apps, especially re-engineering several SQL based VFP apps we have where null dates are rampant, this could become more crucial.



Thanks,

Randy


By StrataFrame Team - 11/19/2007

Yes, creating an imaginary control to focus would work, but firstly, I think we'll focus on figuring out why the [Property]Changed event is firing when it shouldn't.
By Randy Jean - 11/21/2007

Works for me! BigGrin



Thanks, Randy