HOWTO: Make a ReadOnlyChildList

HOWTO: Make a ReadOnlyChildList

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


Zoreloth posted on Tuesday, October 31, 2006

I'm needing to implement a ReadOnlyChildList. Specifically, I need a collection that instantiates as the EditableChildCollection does (accepting a SafeDataReader) but has the 'readonly' functionality of the ReadOnlyList. The only way I'm seeing to do this is to actually implement an EditableChildList and override the Add/Remove/etc... methods. Is that my only option, or is there something better I'm missing?

guyroch replied on Tuesday, October 31, 2006

Noooooooooooooooooooooo......

 

Just add a readonly property in you Editable Root Object.

 

c# (in your editable root object...)

 

private SomeListBO _someList = null;

 

public SomeListBO SomeList
{
   get
   {
      if (this._ someList == null)
      {
         this._someList = SomeListBO.GetList();
      }

      return (this._someList);
   }
}

 

Thas is it.  You now have a readonly list tied to your editable root object.

 

Hope this helps

 

Zoreloth replied on Tuesday, October 31, 2006

guyroch,

Yes, thank you and understood...but doesn't the implementation you're suggesting allow me to still:

editableRootObject.SomeList.Add(anItem);

I don't want a UI client to be able to do that, therefore my thinking that a ReadOnlyList is in order. But, I also need to instantiate that collection by passing it a SafeDataReader (containing a second result set).

guyroch replied on Tuesday, October 31, 2006

No. it won't allow you to add an item.  By default, ReadOnlyList in CSLA will not let you do this.

The only time you can _add_ objects in your ReadOnlyList is when its IsReadOnly variable is set to false.  Typically you will set the IsReadOnly variable to false in the dp_fetch method and then set it back to true before leaving the dp_fetch.

ReadOnlyList means just that, READONLY, so it won't allow you to add an item other than inside your dp_fetch method... unless of course you forget to set it back to IsReadOnly = false at the end of your dp_fetch.  But if you do, its a bug :)

 

guyroch replied on Tuesday, October 31, 2006

...and... make sure your list (SomeListBO) inherits from ReadOnlyListBase and not BusinessListBase...

Zoreloth replied on Tuesday, October 31, 2006

guyroch,

Ok then, now I'm back where I started. I had presumed that ReadOnlyList was necessary in order to get the behavior I require. But, I'm struggling with how to implement ReadOnlyList as a "child" ReadOnlyList where I pass the GetReadOnlyList factory method a SafeDataReader as opposed to Criteria arguments. Or, is that just it...do I pass the SafeDataReader through the Criteria class?

(Edit: This "child" behavior is desired because my SafeDataReader already contains the result set for the ReadOnlyList retrieved when I went to the db in dp_fetch for the EditableRootObject)

guyroch replied on Tuesday, October 31, 2006

Why do you want to pass the SafeDataReader? 

Doing it this way will _lazy_load_ your list - a great performance improvement IMHO.  By that I mean it will get loaded only when you make a call to it.  Your db_fetch inside your ReadOnlyList will create it own instance of SafeDataReader and will load itself.

public SomeListBO SomeList
{
   get
   {
      if (this._ someList == null)
      {
         this._someList = SomeListBO.GetList();
      }

      return (this._someList);
   }
}

 

Nothing prevents you to create a Criteria class (and Factory mehtod) that take in your Editable Root Object ID so that you dp_fetch inside your ReadOnlyList loads only what it needs.

 

this._someList = SomeListBO.GetList(MyRootBO.ObjectId);

JoeFallon1 replied on Tuesday, October 31, 2006

"This child behavior is desired because my SafeDataReader already contains the result set for the ReadOnlyList retrieved"

And change your query to only return the Root BO data.

Then when your request the ROC you can either get all records or pass in a simple criteria to it like Root.ID to narrow down the list.

Joe

 

 

Zoreloth replied on Tuesday, October 31, 2006

Good point...and, even more applicable when considering the ReadOnlyList contains application security permissions read from the database. In reality, the ReadOnlyList will be called each time CanAddObject, CanEditObject, CanDeleteObject on any business object is called. That's a lot of trips to the database - but, it also guarantees current security is in effect (in case rights are changed while user is logged in). So, will definitely consider the options. Thanks for the help...much appreciated!

JoeFallon1 replied on Tuesday, October 31, 2006

Based on the lazy load code above your ROC will only be fetched once and then you can use it multiple times. I think this is a better solution than hitting the DB everytimeCanAddObject is called. Most users are used to logging out and back in to "pick up" any new permissions/rights. I do not think the perms need to be live 100% of the time.

Joe

 

Zoreloth replied on Tuesday, October 31, 2006

Doh! I totally missed the "load if null reference" in that code snippet! Thanks gents, I will use the implementation suggested.

Copyright (c) Marimer LLC