ObjectFactory and Child Objects.

ObjectFactory and Child Objects.

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


bniemyjski posted on Monday, April 05, 2010

Hello,

How should one treat Child Fetch calls when using the ObjectFactory? I have an EditableChild or a ReadOnlyChild and my code looks like this:

 

  internal static SettingGroupList GetByApplicationID(System.Int32 applicationID)

        {

            return DataPortal.FetchChild< SettingGroupList >(

                new SettingGroupCriteria{ApplicationID = applicationID});

        }

It doesn't work because ChildPortal methods are never invoked but I need to call the ObjectFactory Implementation. Should I always just have them call the Regular Fetch? Is there a best practice for this?

        internal static SettingGroupList GetByApplicationID(System.Int32 applicationID)

        {

            return DataPortal.Fetch< SettingGroupList >(

                new SettingGroupCriteria{ApplicationID = applicationID});

        }

 

Thanks

-Blake Niemyjski

RockfordLhotka replied on Monday, April 05, 2010

The child data portal is not compatible with the object factory.

When using the object factory model, the factory is responsible for creating and initializing child objects as well as root objects.

You might consider having the root object factory create and invoke other "child" object factories - but this isn't something the data portal will do for you. When you are in object factory land, you are on your own.

bniemyjski replied on Wednesday, April 14, 2010

Hello,

I understand this completely. What I'm asking about is if you are lazy loading children and you know how you want to load the child during runtime (not during compile time). Would the best approach be to call Fetch<>() instead of FetchChild<>() in your children's Get Methods as this will invoke Object Factory.

Thanks

-Blake Niemyjski

RockfordLhotka replied on Wednesday, April 14, 2010

The simplest way to lazy load child objects is to use a command object (or readonlybase object) to do the work. Basically create it as a unit of work - where that work is to run to the server, load the child object(s) and return the result.

Then the lazy load code can just Fetch() the ROB, and grab its Results property value to get the child objects. This way the child objects don't get complex - they remain purely children, and any complexity is shifted up into the ROB parent that is retrieving them - and even that isn't complex right, just open the database, do the query and call FetchChild() to get each child.

bniemyjski replied on Wednesday, April 14, 2010

Hello,

It wouldn't be that hard to update this to use that method of retrieval, just seems like a lot of extra work for preexisting functionality.

Thanks

-Blake Niemyjski

RockfordLhotka replied on Wednesday, April 14, 2010

The only alternative though, is to implement the fetch (DP_F or factory) and manually call MarkAsChild to make the object a child. Doing that in genned code is probably fine, but doing it manually is not fine because people forget and then have hard to resolve bugs. Those bugs drove me to create the child data portal concept - it was just such a common issue that I felt it needed solving Smile

bniemyjski replied on Wednesday, April 14, 2010

 

Hello,

Thats what I'm currently doing Smile. I think I'll just detect if they are using object factory and if they are I'm going to output a comment saying this normally is FetchChild<>() but were calling Fetch<>() so the data portal is invoked. If your class is not marked as a child then you changed the object factory implementation Smile.

Thanks

-Blake Niemyjski

 

bniemyjski replied on Monday, December 20, 2010

Hello,

This has been fixed in the latest nightly build of the CSLA templates.

Thanks

-Blake Niemyjski

bniemyjski replied on Thursday, March 15, 2012

Can we do something to change this behavior in CSLA 4.5? I just ran into this again where ChildPortal (CreateChild) wasn't using the ObjectFactory method which I thought it would use (it's been a while). Instead of calling the Create Method in OF it created a new instance locally. I understand that these ChildPortal calls should only happen locally...

My idea is that if you say all my creation logic is going to be in this assembly (which is more than likely on the client), then make the call to object factory for the creation.

RockfordLhotka replied on Thursday, March 15, 2012

You are suggesting that the child data portal look for the ObjectFactory attribute and route the call through the regular data portal to the factory if it is present?

csmith1 replied on Thursday, March 15, 2012

I slight aside but think I am on the same subject. I ran in to this bug when unit testing some generated code. I changed the property of the parent that held Identification for the child to a different child. The test was to check if the load child was now the new value but it failed.

The copy of the example from "Using CSLA" leaves out that there is usually a query for children by a property value.

If it is a Many to One relationship something like ChildId with a backing field _childIdProperty.

I suggest it read something like:

if((!FieldManager.FieldExists(AddressesProperty)) || (!FieldManager.IsFieldDirty(_childIdProperty))

Thanks,

Charles

 

Example

In Creating Business Objects you have:

public static readonly PropertyInfo<AddressEditList> AddressesProperty =

RegisterProperty<AddressEditList>(c => c.Addresses,

RelationshipTypes.Child | RelationshipTypes.LazyLoad);

public AddressEditList Addresses

{

  get

{

if (!FieldManager.FieldExists(AddressesProperty))

{

LoadProperty(AddressesProperty, null);

AddressListCreator.GetAddressListCreator((o, e) =>

{

if (e.Error != null) throw e.Error; else Addresses = e.Object.Result; });

}

return GetProperty(AddressesProperty);

}

 

 

 

 

 

 

Copyright (c) Marimer LLC