[SOLVED] Datetime Conversion

Posts   
 
    
MarcoP avatar
MarcoP
User
Posts: 270
Joined: 29-Sep-2004
# Posted on: 06-Nov-2004 23:43:27   

I'm using the following code to setup my winforms databinding. For some reason, when I go to save my entity, i get an sql exception b/c the LastContact field is trying to send in the DateTime.MinValue, rather than DbNull.Value. The column in the database allows nulls, but I can't figure out why this is trying to send in 1/1/1.

Any ideas?

/// <summary>
/// Initializes the forms control bindings.
/// </summary>
private void InitializeControlBindings(CustomerEntity customer) {
    _customer = customer;
    _bindingManager = this.BindingContext[_customer];

    // take a snapshot of the entity's state.
    _customer.SaveFields(ENTITY_CHECK_POINT);

    // begin our bindings.
    base.BindField(txtFullName, "Text", _customer, "FullName");
    base.BindField(txtJobTitle, "Text", _customer, "JobTitle");
    base.BindField(txtCompany, "Text", _customer, "Company");
    base.BindField(txtEmail, "Text", _customer, "Email");
    base.BindField(txtStreet, "Text", _customer, "Street");
    base.BindField(txtCity, "Text", _customer, "City");
    base.BindField(txtState, "Text", _customer, "State");
    base.BindField(txtZipCode, "Text", _customer, "ZipCode");
    base.BindField(txtBusinessPhone, "Text", _customer, "BusinessPhone");
    base.BindField(txtBusinessFax, "Text", _customer, "BusinessFax");
    base.BindField(txtHomePhone, "Text", _customer, "HomePhone");
    base.BindField(txtMobilePhone, "Text", _customer, "Mobile");
    base.BindField(txtNotes, "Text", _customer, "Notes");
    base.BindField(cbStatus, "Value", _customer, "StatusId");
    base.BindField(cbRating, "Value", _customer, "RatingId");
    base.BindField(cbSource, "Value", _customer, "SourceId");
    base.BindField(cbSaleStage, "Value", _customer, "SaleStageId");

    // we need to hook this up seperately in order to catch out format/parse events.
    cbLastContact.DataBindings.Clear();
    Binding b = new Binding("Text", _customer, "LastContact");
    b.Format += new ConvertEventHandler(FormatDateTime);
    b.Parse += new ConvertEventHandler(ParseDateTime);
    cbLastContact.DataBindings.Add(b);   
}

/// <summary>
/// Formats the datetime value.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FormatDateTime(object sender, ConvertEventArgs e) {
    if (e.DesiredType != typeof(string)) return;
    if (Convert.ToDateTime(e.Value) == DateTime.MinValue) {
        e.Value = String.Empty;
    }
}

/// <summary>
/// Parses the datetime value.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void ParseDateTime(object sender, ConvertEventArgs e) {
    if (e.DesiredType != typeof(DateTime)) return;
    if (Convert.ToString(e.Value).Trim() == String.Empty) {
        e.Value = DateTime.MinValue;
    }
}
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39903
Joined: 17-Aug-2003
# Posted on: 07-Nov-2004 11:04:33   

You set the value to MinValue in the Parse routine. Now, check this scenario: - you set a value for a given date field D - you change your mind and clear the cell for D - because of that, your routine set the field's value to MinValue. - because the field has a value, it's set to MinValue. Would it still have the default value (MinValue) nothing would happen.

So you end up with a changed field which has the value MinValue. Instead of setting it to MinValue, set it to null using entity.SetNewFieldValue(). In your other routine, FormatDateTime, check the CurrentValue property of the Field object FIRST, if that's null, set the field to "" and return, otherwise proceed and format the date. I'm not completely sure (I haven't tested this) but this should not throw an exception.

Frans Bouma | Lead developer LLBLGen Pro
MarcoP avatar
MarcoP
User
Posts: 270
Joined: 29-Sep-2004
# Posted on: 07-Nov-2004 19:31:23   

Hmm, I thought this code would work, but the TestOriginalFieldValueForNull routine is returning false. I'm passing in a new instance of the CustomerEntity. Does this routine only work when pulling an entity from the db?

         /// <summary>
        /// Formats the datetime value.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void FormatDateTime(object sender, ConvertEventArgs e) {
            if (e.DesiredType != typeof(string)) return;
            if (_customer.Fields[(int)CustomerFieldIndex.LastContact].CurrentValue == null || _customer.TestOriginalFieldValueForNull(CustomerFieldIndex.LastContact)) {
                e.Value = String.Empty;
            }
        }
Otis avatar
Otis
LLBLGen Pro Team
Posts: 39903
Joined: 17-Aug-2003
# Posted on: 07-Nov-2004 19:53:27   

TestOriginalFieldValue... tests if the entity's value read from the DB is NULL. You should do:

if(entity.Fields[index (or name))].CurrentValue == null) { // is null, do special action.. }

Frans Bouma | Lead developer LLBLGen Pro
MarcoP avatar
MarcoP
User
Posts: 270
Joined: 29-Sep-2004
# Posted on: 07-Nov-2004 20:30:55   

Otis wrote:

TestOriginalFieldValue... tests if the entity's value read from the DB is NULL. You should do:

if(entity.Fields[index (or name))].CurrentValue == null) { // is null, do special action.. }

I dont think that will work completly because it returns '1/1/1' when the instance is first created, and I want to show an empty string in the date picker.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39903
Joined: 17-Aug-2003
# Posted on: 07-Nov-2004 21:13:56   

MarcoP wrote:

Otis wrote:

TestOriginalFieldValue... tests if the entity's value read from the DB is NULL. You should do:

if(entity.Fields[index (or name))].CurrentValue == null) { // is null, do special action.. }

I dont think that will work completly because it returns '1/1/1' when the instance is first created, and I want to show an empty string in the date picker.

Yes simple_smile

I was talking about the situation when the user has filled in an empty string, so teh field has to be NULL again in the database. In your code you set the field to MinValue, which is not correct, you have to set it to null using SetNewFieldValue(). However, while doing so, you have to check if the field is null when you format the field for displaying of course. That's the snippet I was talking about simple_smile

Frans Bouma | Lead developer LLBLGen Pro