NullReferenceException if AddNew() called on BusinessListBase

NullReferenceException if AddNew() called on BusinessListBase

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


rsbaker0 posted on Sunday, April 12, 2009

I've just been experimenting with the index support in BusinesListBase, and I'm finding I can't call AddNew() on the list if I do this. (CSLA 3.5.1)

I think I can work around it by creating the item with a valid property value before inserting it, but I wouldn't think that indexing should cause AddNew() to fail.

It's failing here in index.cs, presumably because it's not anticipating the null property value...

private void DoAdd(T item)

{

if (_theProp != null)

{

int hashCode = _theProp.GetValue(item, null).GetHashCode();

if (_index.ContainsKey(hashCode))

_index[hashCode].Add(item);

else

{

List<T> newList = new List<T>(1);

newList.Add(item);

_index.Add(hashCode, newList);

}

_countCache++;

}

}

 

ajj3085 replied on Sunday, April 12, 2009

Are you trying to insert null into a BusinessListBase subclass? I don't think that's supported. BLB expects to contain actual Csla business objects.. and even without indexing, I have a feeling code would break elsewhere in Csla if you try to push a null into the list.

rsbaker0 replied on Sunday, April 12, 2009

No, I'm just calling AddNew() on the BLB itself, which ends up calling AddNewCore() which will manufacture the child BO for you (dataportal_create, the works). The return value from AddNew() is the new BO. 

The child BO contains a string property which I intended to set immediately on the returned child -- this is the property that is indexed.

However, since the string is null at the actual insert time, the code above causes a null reference exception since it dereferences the null property value without checking for null first. I fixed this in my CSLA code, but then I ran into problem #2 (my other post on property changes not causing re-indexing -- http://forums.lhotka.net/forums/thread/32521.aspx).

ajj3085 replied on Monday, April 13, 2009

Hmm... what does your AddNewCore override look like?   You should be able to set the property on the child prior to inserting it into the list.  Also.. maybe it'd be a good idea to default the property value to String.Empty instead of null.  At least that way you wouldn't have to maintain a change to Csla yourself if this is going to get fixed by Rocky.

mamboer replied on Monday, April 13, 2009

Er,maybe you can provide a overrided AddNewCore method in your BLB,like
 
public class ProjectList:Csla.BusinessListBase<ProjectList,Project>
...
{
   protected override object AddNewCore(){
      var item=Project.NewProject();
      //Your custom processes on the new project go here
      ...
      Add(item);
      return item;
   }
}

RockfordLhotka replied on Monday, April 13, 2009

I did add this to the bug list, but I know Aaron is very busy right now, so I can't say when it will get looked at.

bniemyjski replied on Friday, October 30, 2009

Hello,

Has this been fixed because I am currently experiencing this error with CSLA 3.7.1..


Profile profile2 = Profile.NewProfile();
            profile2.ApplicationName = "PetShop 4.0";
            profile2.IsAnonymous = true;
            profile2.LastActivityDate = DateTime.Now;
            profile2.LastUpdatedDate = DateTime.Now;
            profile2.Username = Guid.NewGuid().ToString();

            Account account = profile2.Accounts.AddNew();
            account.Address1 = "100 main street";

private static readonly PropertyInfo< AccountList > _accountsProperty = RegisterProperty<AccountList>(p => p.Accounts, Csla.RelationshipTypes.Child | Csla.RelationshipTypes.LazyLoad);
        private readonly AccountList _accounts = _accountsProperty.DefaultValue;
        public AccountList Accounts
        {
            get
            {
                if(!FieldManager.FieldExists(_accountsProperty))
                {
                    if(this.IsNew)
                        LoadProperty(_accountsProperty, AccountList.NewList());
                    else
                        LoadProperty(_accountsProperty, AccountList.GetByUniqueID(UniqueID));
                }

                return GetProperty(_accountsProperty, _accounts);
            }
        }



internal static AccountList NewList()
        {
            return DataPortal.CreateChild< AccountList >();
        }


private AccountList()
        {
            AllowNew = true;
            MarkAsChild();
        }

#region Business Methods
       
        protected override object AddNewCore()
        {
            Account item = PetShop.Business.Account.NewAccount();
            this.Add(item);
            return item;
        }
       
        #endregion

Thanks
-Blake Niemyjski

bniemyjski replied on Tuesday, November 03, 2009

Hello,

Has this been fixed because I am currently experiencing this error with CSLA 3.7.1..

Thanks
-Blake Niemyjski

RockfordLhotka replied on Tuesday, November 03, 2009

fwiw, Aaron is on a gig that involves flying to China on a regular basis, so his time to devote to this is relatively limited.

I'm totally open to one of you who are having the problem suggesting a solution, though the door for 3.8.0 is closing in about 48 hours...

RockfordLhotka replied on Tuesday, November 03, 2009

I should take a step back.

I'm not even sure what the problem is here?

Is it that you are adding a null item to the collection and that breaks indexing?

Or are you adding an item with a null property value, where that property is marked Indexable and that breaks indexing?

Or something completely different?

I look at the code snippets in the posts and I fail to see a complete enough unit test or code flow on which to base a unit test that illustrates the problem.

RockfordLhotka replied on Tuesday, November 03, 2009

As long as I'm digging around in this thing (got a bit of a fever and can't concentrate on any one thing for long - total PITA), does this change to Csla.Linq.Index help?

    private void DoAdd(T item)
    {
      if (_theProp != null)
      {
        object value = _theProp.GetValue(item, null);
        if (value != null)
        {
          int hashCode = value.GetHashCode();
          if (_index.ContainsKey(hashCode))
            _index[hashCode].Add(item);
          else
          {
            List<T> newList = new List<T>(1);
            newList.Add(item);
            _index.Add(hashCode, newList);
          }
          _countCache++;
        }
      }
    }

Perhaps one of you who are having the issue can give this a go?

RockfordLhotka replied on Thursday, November 05, 2009

Did this fix your issues?

I have checked this in, because it doesn't cause a problem with existing code, and I think it will fix your issues, and I'm closing down everything in preparation for the 3.8.0 final release.

http://www.lhotka.net/cslabugs/edit_bug.aspx?id=387

rsbaker0 replied on Thursday, November 05, 2009

The fix you posted matches the one I implemented almost exactly... :)

// CSLA FIX HERE -- don't index null values?
object propValue = _theProp.GetValue(item, null);
if (propValue != null)
{
int hashCode = propValue.GetHashCode();
...

RockfordLhotka replied on Thursday, November 05, 2009

Good, thanks!

bniemyjski replied on Friday, November 06, 2009

Hello,

I'll see if this fixes my issues as well.

Thanks
-Blake

Copyright (c) Marimer LLC