Adding new child to collection property without setting property?

Adding new child to collection property without setting property?

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


preludecrazy posted on Sunday, March 30, 2008

Hi.

My CompanyCollection (BusinessListBase) class contains Company children which derives from LiteCompany (BusinessBase).  My Company child class has a member/property of type WebsiteCollection (BusinessListBase).  The WebsiteCollection member/property looks like this in my Company class:

private WebsiteCollection mobjWebsiteCollection = null;

[MyDataMemberAttribute(true)]
public WebsiteCollection WebsiteCollection
{
 [System.Runtime.CompilerServices.
MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
 get
 {
  CanReadProperty(
true);
  return (mobjWebsiteCollection == null) ? WebsiteCollection.NewWebsiteCollection() : mobjWebsiteCollection;
 
}
 
[System.Runtime.CompilerServices.
MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.NoInlining)]
 set
 {
  if (mobjWebsiteCollection != value)
  {
   mobjWebsiteCollection =
value;
   PropertyHasChanged();
  }
 }
}

The DataPortal_Fetch method in Company contains the following, which populates the WebsiteCollection:

WebsiteCollection objWebsiteCollection = WebsiteCollection.GetWebsiteCollection(criteria.CompanyID, criteria.WebsiteID);
for (int ii = 0; ii <= this.Count; ii++)
{
 foreach (Website objWebsite in objWebsiteCollection)
 {
  if (objWebsite.CompanyID == this[ii].CompanyID)
  {
   WebsiteCollection objWC = this[ii].WebsiteCollection;
   objWC.Add(objWebsite);
   this[ii].WebsiteCollection = objWC;
  }
 }
}

This works fine, except, due to the line above in red; the child's IsDirty flag is set to true in WebsiteCollection, this is because I'm setting the Company.WebsiteCollection property.  How can I add to the current Company child's WebsiteCollection without setting the property?  I was hoping I could do something like 'this[ii].WebsiteCollection.Add(objWebsite);', but that doesn't work.

Please can somebody tell me where I'm going wrong?

Thanks.

RockfordLhotka replied on Sunday, March 30, 2008

Normally the property for a child object is read-only. You don't want the UI developer to accidentally alter your child out from under you! CSLA doesn't support that by itself - you'd have to make very sure to handle that event properly!!!

If the property is read-only as recommended, then your data portal code won't compile - which is good - you shouldn't be setting the property. Instead, you should be setting the backing field for the property. Look at Chapters 7/8 and ProjectTracker.Library for numerous examples.

tmg4340 replied on Sunday, March 30, 2008

Using something like this:

return (mobjWebsiteCollection == null) ? WebsiteCollection.NewWebsiteCollection() : mobjWebsiteCollection;

presents a problem, since you create a new collection but never assign it to "mobjWebsiteCollection".  Thus, every time you try to "get" your collection, you're potentially getting a new one.  I'm guessing that's why your original code doesn't work.

On another note, you're using an old property construct that you shouldn't be using anymore.  The "NoInlining" method of property coding has proven to be too quirky and unstable for general use, so Rocky has deprecated its use in newer versions of the framework.  The recommended practice is to not use the "NoInlining" attribute and use the method overloads of "CanReadProperty" and "PropertyHasChanged" that take a property name.

However, I'm wondering why you have a "set" for this property anyway.  It's pretty unusual to have one for collection properties.  If you have it because of your issue, then I'd suggest you get rid of it once we get your "get" routine cleaned up.  If you do need to keep it, then you should add a call to "CanWriteProperty" in there as well, so that your security is maintained.  Again, that call should have your property name in it.

So - assuming you don't need the "set", your property should look something like this:

[MyDataMemberAttribute(true)]
public WebsiteCollection WebsiteCollection
{
 get
 {
  CanReadProperty("WebsiteCollection",
true);

  if (mobjWebsiteCollection == null)
    mobjWebsiteCollection = WebsiteCollection.NewWebsiteCollection();

  return mobjWebsiteCollection;
 
}
}

And if you do need the "set", it should look something like this:

 set
 {
  CanWriteProperty("WebsiteCollection", true);

  if (mobjWebsiteCollection != value)
  {
   mobjWebsiteCollection =
value;
   PropertyHasChanged("WebsiteCollection");
  }
 }

All your BO properties should be constructed similarly.

HTH

- Scott

preludecrazy replied on Monday, March 31, 2008

tmg4340:

Using something like this:

return (mobjWebsiteCollection == null) ? WebsiteCollection.NewWebsiteCollection() : mobjWebsiteCollection;

presents a problem, since you create a new collection but never assign it to "mobjWebsiteCollection".

 

LOL.  What an idiot I am! :)

Cheers, Scott.

Copyright (c) Marimer LLC