GetIdValue() is being called recursively during DataBinding

GetIdValue() is being called recursively during DataBinding

Old forum URL: forums.lhotka.net/forums/t/1980.aspx


jspurlin posted on Thursday, December 14, 2006

I have a situation where GetIdValue is being called recursively when binding to a data aware control.

The code is a little lengthy, and though I am happy to paste it here, I would like to know if there are "scenarios" where a Recursive Call to GetIdValue() happens during databinding.

Here is the object hierarchy

Office
Office loads:
private OfficeAddresses _addresses
            = OfficeAddresses.NewOfficeAddresses();


OfficeAddress : BaseAddress
OfficeAddress loads:
private OfficeAddressAssignments _assignments
            = OfficeAddressAssignments.NewOfficeAddressAssignments();


OfficeAddressAssignment : BaseAddressAssignments

I know this isn't much detail.  In effect I have Parent, Child which has its own base class, and Grandchild which has its own base class.

The Fetch appears to work fine.  The problem appears to be binding to a data aware control: a recursive call to GetIdValue() throws a StackOverflowException when I click to edit the record.

Any advice is appreciated. Thank you.

xal replied on Thursday, December 14, 2006

What are you returning inside GetIdValue() ? Are you calling GetIdValue yourself inside anywhere in your bo or in a base class?


GetIdValue should return the value of an variable (or combination of variables) inside your BO.
Are you calling a property instead of a variable?


Andrés

jspurlin replied on Thursday, December 14, 2006

Andres, thank you for the quick reply.  I did find that the error was a databinding routine, therefore a repeated call to a property which in turn hung up the app repeatedly calling for the GetIdValue().

But, this does raise some questions for me, and I am glad you asked.  I have a ReadOnly value AddressId in the BaseClass and I call GetIdValue which returns _addressId.

I am surprised by the recursion though, so I do need to ask if this recursion is normal as each property is binding to the page.


xal replied on Thursday, December 14, 2006

In the scenario you mention, it shouldn't be a problem, although, it does seem pointless to call GetIdValue from your property when you can access _addressId directly...
Not that it is a problem, but GetIdValue returns a value of type object, so an unboxing or cast must take place there.

Are you using VB? If you are you should try setting option strict on a project level... It really is amazing how many times it can get you in trouble not to set that on!! I'm not sure it even deserves being called a feature, and it should at least be set to on by default... (you can default it to on inside visual studio's options dialog)

Andrés

Matthew Yost replied on Monday, June 18, 2007

I am also getting this problem.  I have gone thru my code to make sure that ID property was not being used and just the variable but alas it is still causing me headaches.  Here's the "info" class as well as the "List" class that are being used.

using System;

using System.Collections.Generic;

using System.Text;

using Csla;

using Csla.Data;

 

namespace GTM.Compliance.Core.TPL

{

    public class TPLCountryList:ReadOnlyListBase<TPLCountryList, TPLCountryInfo>

    {

        public static TPLCountryList GetCountryList()

        {

            return DataPortal.Fetch<TPLCountryList>(new Criteria(0));

        }

        public TPLCountryList()

        {  /* Require use of factory methods */ }

 

        #endregion

 

        #region Data Access

 

        [Serializable()]

        private class Criteria

        {

            private int mId;

            public int Id

            {

                get

                { return mId; }

            }

            public Criteria(int id)

            { mId = id; }

        }

 

        private void DataPortal_Fetch(Criteria criteria)

        {

            this.RaiseListChangedEvents = false;

            List<TPLCountryInfo> dcl = CoreGlobal.DBInterface.GetCountries();

            this.IsReadOnly = false;

            foreach (TPLCountryInfo d in dcl)

            {

                this.Add(d);

            }

            this.IsReadOnly = true;

            this.RaiseListChangedEvents = true;

        }

 

        #endregion

    }

}

 

using System;

using System.Collections.Generic;

using System.Text;

using Csla;

using Csla.Data;

 

 

namespace GTM.Compliance.Core.TPL

{

    [Serializable]

    public class TPLCountryInfo:ReadOnlyBase<TPLCountryInfo>

    {

        private int _intCountryID;

        private string _strCountryName;

        private string _strISO3;

        private string _strISO2;

 

        public TPLCountryInfo()

        {

 

        }

 

        public TPLCountryInfo(int id, string name, string iso3, string iso2)

        {

            _intCountryID = id;

            _strCountryName = name;

            _strISO3 = iso3;

 

        }

 

        public int CountryID

        {

            get

            {

                return _intCountryID;

            }

        }

 

        public string CountryName

        {

            get

            {

                return _strCountryName;

            }

        }

 

        public string ISO3

        {

            get

            {

                return _strISO3;

            }

        }

 

        public string ISO2

        {

            get

            {

                return _strISO2;

            }

        }

 

        public override string ToString()

        {

            return _strCountryName;

        }

 

        protected override object GetIdValue()

        {

            return _intCountryID;

        }

    }

}

 

RockfordLhotka replied on Monday, June 18, 2007

I don't see anything functionally incorrect in that code. So when you bind the list it locks up, and if you break in the debugger it always breaks in GetIdValue()? That's what would happen if it is a recursive issue - and then eventually you'll get a stack overflow exception.

Matthew Yost replied on Monday, June 18, 2007

It continually jumps back into the GetIdValue() method everytime I click on another item on the screen.  I can click on a text box and it will rebind the list to the binding source.  Do you know what might cause this?

RockfordLhotka replied on Tuesday, June 19, 2007

Well GetIdValue() is called by Equals(), and Equals() is called any time an item must be found in a list. When you click on an item on a form, data binding asks the list to find that item – triggering calls to Equals() and thus to GetIdValue().

 

If you have a parent-child or list-detail binding configuration, clicking on different controls will cause binding to change the target object – that’s by design. I recommend creating some very simple data bound UIs and playing with them to understand how binding does auto-navigation between rows in a data source (in this case a list) – that way you can leverage what they’ve built in an effective manner.

 

Rocky

 

From: Matthew Yost [mailto:cslanet@lhotka.net]
Sent: Monday, June 18, 2007 10:45 PM
To: rocky@lhotka.net
Subject: Re: [CSLA .NET] GetIdValue() is being called recursively during DataBinding

 

It continually jumps back into the GetIdValue() method everytime I click on another item on the screen.  I can click on a text box and it will rebind the list to the binding source.  Do you know what might cause this?

Matthew Yost replied on Tuesday, June 19, 2007

Ok I figured out the problem.  I had the combo box's SelectedItem/SelectedValue set to the ID property of the TPLCountryInfo object which was recursively being called everytime the focus was lost.  Removing this fixed the issue.

Copyright (c) Marimer LLC