Update foreign key does not work

Posts   
 
    
shekar
User
Posts: 327
Joined: 26-Mar-2010
# Posted on: 10-Nov-2010 10:45:13   

LLBLGEN 3.0 October 22 release Oracle 9i/10g Framework 2.0

Hi

I have table ledger with colum banker_id [which references table banker] along with other columns.

When I save the data, I update banker_id as 23 it inserts fine. Now in update, if I pass null, it does not update this column as null and previous value 23 remains. I checked the generated query and found that banker_id is missing in update query.

Not sure why this is happening

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 10-Nov-2010 11:15:41   

Please post the Update code. And is the FK a nullable field?

shekar
User
Posts: 327
Joined: 26-Mar-2010
# Posted on: 10-Nov-2010 12:02:55   

Walaa wrote:

Please post the Update code. And is the FK a nullable field?

Yes. FK is nullable field,

Here is the code which is pretty simple

private void Updatedata() { var adapterledger = new DataAccessAdapter(); try { string message; var ledger = new LedgerEntity(); ledger.LedgerId = Convert.ToInt32(GlobalVariable.searchledgerid); ledger.IsNew = false;

            **ledger.BankerId = ValidateUI.GetComboboxNullable(cmbbankerid.SelectedValue);**            
            bool succeeded = adapterledger.SaveEntity(ledger);
            if (succeeded)
            {
                message = StandardMessage.dataupdatesuccess; // just a message to inform user
                DoRefresh(); // just calls the refresh function to clear UI
            }
            else
            {
                message = StandardMessage.datasavefailure;
            }
            MessageBox.Show(message);
        }
        catch (Exception ex)
        {
            GlobalErrorHandler.LogMessage(ex.Message + ex.StackTrace);
            MessageBox.Show(StandardMessage.datasavefailure);
        }
        finally
        {
            adapterledger.CloseConnection();
            adapterledger.Dispose();

ValidateUI.GetComboboxNullable is just a function where am returning null if combobox is not selected by user

public static int? GetComboboxNullable(object value) { if (value == null) { return null; } int number; bool valid = int.TryParse(value.ToString(), out number); if (!valid) { return null; } return number; }

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 10-Nov-2010 14:11:59   

As you haven't fetched the entity from the database the FK sa alrady a default value of null, so when you set it to null, the framework doesn't see that it has been changed, and thus it's not emitted in the update statement.

Please set the IsChanged property of the field to true;

shekar
User
Posts: 327
Joined: 26-Mar-2010
# Posted on: 10-Nov-2010 15:26:06   

Walaa wrote:

As you haven't fetched the entity from the database the FK sa alrady a default value of null, so when you set it to null, the framework doesn't see that it has been changed, and thus it's not emitted in the update statement.

Please set the IsChanged property of the field to true;

  1. How do I set IsChanged?
  2. I have fetched the entity before entering update function.

Also I dont think that I havent fetched. Because in same table I have another column called, narration. only diff is this narration is not foreign key.

When I add ledger.Narration = null; it sets the value to null overriding the value which existed before. So am not convinced why only foreign key values cannot be set to null in same code what i have written ? the same thing happens to date field. but in varcar field i have no issues

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 10-Nov-2010 15:50:22   

How come you are saying you have fetched the entity before entering the function, while the following code shows that you enstantiate a new entity.

            var ledger = new LedgerEntity();
            ledger.LedgerId = Convert.ToInt32(GlobalVariable.searchledgerid);
shekar
User
Posts: 327
Joined: 26-Mar-2010
# Posted on: 10-Nov-2010 16:09:26   

Walaa wrote:

How come you are saying you have fetched the entity before entering the function, while the following code shows that you enstantiate a new entity.

            var ledger = new LedgerEntity();
            ledger.LedgerId = Convert.ToInt32(GlobalVariable.searchledgerid);

Hmmm, but still updates ! by setting is new=false !

If am doing wrong, what is the alteration i need to do in my code, walaa

Walaa avatar
Walaa
Support Team
Posts: 14995
Joined: 21-Aug-2005
# Posted on: 10-Nov-2010 16:20:40   

Just set IsChanged as follows:

ledger.Fields["BankerId"].IsChanged = true;
shekar
User
Posts: 327
Joined: 26-Mar-2010
# Posted on: 11-Nov-2010 04:54:03   

Walaa wrote:

Just set IsChanged as follows:

ledger.Fields["BankerId"].IsChanged = true;

Hi Walaa, This worked.

But still my question remains unanswered. The code earlier I had written updates the field narration even without setting ischanged property. Why only banker_id does not update ?

Secondly, do I have to set is changed for every field which is being updated? it results in lengthy code right !

The reason is steps I had followed in my code was exactly as per your documentation which states

CustomerEntity customer = new CustomerEntity(); customer.CustomerID="CHOPS"; customer.IsNew=false; customer.Phone = "(605)555-4321"; customer.Save();

daelmo avatar
daelmo
Support Team
Posts: 8245
Joined: 28-Nov-2005
# Posted on: 11-Nov-2010 06:48:03   

shekar wrote:

But still my question remains unanswered. The code earlier I had written updates the field narration even without setting ischanged property. Why only banker_id does not update ?

The normal entity life cycle works like this: - You fetch the entity - You make changes to entity - You save back Example:

// fetch entity
var ledgerId = Convert.ToInt32(GlobalVariable.searchledgerid);
var ledger = new LedgerEntity(ledgerId);
adapter.FetchEntity(ledger);

// make changes
ledger.BankerId = ValidateUI.GetComboboxNullable(cmbbankerid.SelectedValue);            

// save it back
bool succeeded = adapterledger.SaveEntity(ledger);

If, for some reason you don't want to fetch the entity but you still want to update an existing record on your db, you can do the IsNew=false trick. This has the downside of the update fields to null. In the normal behavior (entity life cycle) this isn't a problem as if the field is not null, when you set to null, a change is detected and the column is updated. In your approach, you set the field to null, but the field is already null because you didn't fetch it, so you have to do the IsChanged trick mentioned by Walaa:

// IsNew trick (without fetch)
var ledger = new LedgerEntity();
ledger.LedgerId = Convert.ToInt32(GlobalVariable.searchledgerid);

// make changes (use IsChanged trick when set to null)
ledger.BankerId = ValidateUI.GetComboboxNullable(cmbbankerid.SelectedValue);            
ledger.Fields["BankerId"].IsChanged = true;

// save it back
bool succeeded = adapterledger.SaveEntity(ledger);

shekar wrote:

Secondly, do I have to set is changed for every field which is being updated? it results in lengthy code right !

You just need to do IsChanged=true if the new value of the field is null and you are using the second approach (don't fetch the entity first).

In the documentation there is a note as well about this:

Setting a field to the same value it already has will not set the field to a value (and will not mark the field as 'changed') unless the entity is new.

Which is your case, as the value is null at first (you didn't fetch it so the original value is unknown), then you set it to null, so no change is detected.

Hope that makes sense to you wink

David Elizondo | LLBLGen Support Team
shekar
User
Posts: 327
Joined: 26-Mar-2010
# Posted on: 11-Nov-2010 07:18:49   

daelmo wrote:

shekar wrote:

But still my question remains unanswered. The code earlier I had written updates the field narration even without setting ischanged property. Why only banker_id does not update ?

The normal entity life cycle works like this: - You fetch the entity - You make changes to entity - You save back Example:

// fetch entity
var ledgerId = Convert.ToInt32(GlobalVariable.searchledgerid);
var ledger = new LedgerEntity(ledgerId);
adapter.FetchEntity(ledger);

// make changes
ledger.BankerId = ValidateUI.GetComboboxNullable(cmbbankerid.SelectedValue);            

// save it back
bool succeeded = adapterledger.SaveEntity(ledger);

If, for some reason you don't want to fetch the entity but you still want to update an existing record on your db, you can do the IsNew=false trick. This has the downside of the update fields to null. In the normal behavior (entity life cycle) this isn't a problem as if the field is not null, when you set to null, a change is detected and the column is updated. In your approach, you set the field to null, but the field is already null because you didn't fetch it, so you have to do the IsChanged trick mentioned by Walaa:

// IsNew trick (without fetch)
var ledger = new LedgerEntity();
ledger.LedgerId = Convert.ToInt32(GlobalVariable.searchledgerid);

// make changes (use IsChanged trick when set to null)
ledger.BankerId = ValidateUI.GetComboboxNullable(cmbbankerid.SelectedValue);            
ledger.Fields["BankerId"].IsChanged = true;

// save it back
bool succeeded = adapterledger.SaveEntity(ledger);

shekar wrote:

Secondly, do I have to set is changed for every field which is being updated? it results in lengthy code right !

You just need to do IsChanged=true if the new value of the field is null and you are using the second approach (don't fetch the entity first).

In the documentation there is a note as well about this:

Setting a field to the same value it already has will not set the field to a value (and will not mark the field as 'changed') unless the entity is new.

Which is your case, as the value is null at first (you didn't fetch it so the original value is unknown), then you set it to null, so no change is detected.

Hope that makes sense to you wink

Perfect. Thanks