cslaforum icon indicating copy to clipboard operation
cslaforum copied to clipboard

CSLA business objects should not be created outside of a ObjectFactory instance

Open BlagoCuljak opened this issue 6 years ago • 16 comments

Hi there, just started to upgrade an app from 4.7.200 to 5.0. Also changing WCF AppServerHost to AppServerCore.

I have upgraded all the DataAccess project, now using EF Core, etc.

Upgraded to Standard BusinessLibrary, and changed braking issues. However, one error from old BusinessLibrary is constantly reported on all Edits: CSLA0011 CSLA business objects should not be created outside of a ObjectFactory instance.

This part of code is responsible for error, and every single Edit has this Error:

public static void Exists(int id, Action<bool> result)
		{
			var cmd = new AccountExistsCommand(id);
			DataPortal.BeginExecute<AccountExistsCommand>(cmd, (o, e) =>
			{
				if (e.Error != null)
					throw e.Error;
				else
					result(e.Object.AccountExists);
			});
		}
public static bool Exists(int id)
		{
			var cmd = new AccountExistsCommand(id);
			cmd = DataPortal.Execute<AccountExistsCommand>(cmd);
			return cmd.AccountExists;
		}

What am I missing?

Version and Platform CSLA version: 5.00 OS: Windows Platform: WPF, ASP.NET Core

BlagoCuljak avatar Sep 26 '19 08:09 BlagoCuljak

If I understand what I read correctly when I attempted an upgrade to 5.0 you need to follow one of the methods in the Using CSLA eBooks. We use the Encapsulated Invocation Model in our projects.

The ProjectTracker sample project basically shows how this is done, as well.

ghost avatar Sep 26 '19 11:09 ghost

Yes, for a command object do this:

  1. Make sure you have a [Create] method marked as [RunLocal] in the command class (even if it does no work) - though this is also a good place to initialize properties
  2. Use DataPortal.Create<MyCommand>() to get an instance of the command object, remember you can now pass multiple parameters to data portal methods, so you can easily initialize the command object's properties via the Create call

rockfordlhotka avatar Sep 26 '19 14:09 rockfordlhotka

Thank you @rockfordlhotka , I am sure you are way busy to have time for this :) but I was wondering about updating the Csla books. Kind regards

Chicagoan2016 avatar Sep 26 '19 14:09 Chicagoan2016

This is absolutely my plan @Chicagoan2016 !

Keep in mind that the books are nearly 1000 pages of content, so it'll take some months to update all of that material.

rockfordlhotka avatar Sep 26 '19 14:09 rockfordlhotka

Hi guys, thank you for your answers, yes, I have used CSLA 4 (Using CSLA4 materials), and didn't track CSLA's progress, changes, braking changes, and then comes time that you need to move on, and some issues popup. Thanks for your insight.

@rockfordlhotka 's blog was a right place to start with, and I'm getting a hang of it.

New materials would be great, I'd be happy o purchase again updated materials.

BlagoCuljak avatar Sep 27 '19 08:09 BlagoCuljak

Is there any work around to avoid this error ...? ReadOnlyListBase now I am not able to create object using "new " keyword also in ReadOnlyListBase doesn't have DataPortal.Create

SachinPNikam avatar Oct 02 '19 14:10 SachinPNikam

Use DataPortal.Create<T>() and in your business class add this:

    [Create, RunLocal]
    private void Create() { }

rockfordlhotka avatar Oct 03 '19 05:10 rockfordlhotka

okay ! I will check with this .Thanks you Rocky !!!..Actually this is going to be big changes for my Lib ..

SachinPNikam avatar Oct 03 '19 08:10 SachinPNikam

If I have an ObjectFactory attribute declared on a Command object and also have

    [Create, RunLocal]
    private void Create() { }

declared in the Command object. Shouldn't the Create method be called locally instead of attempting to call a Create method on the ObjectFactory? If that is how it's supposed to work, then I can't seem to get it working correctly. If I comment out the ObjectFactory attribute, the local Create method executes. Or am I expected to have both Create and Execute methods defined in the object factory?

kellyethridge avatar Nov 18 '19 22:11 kellyethridge

If your business class has an ObjectFactory attribute then the client-side data portal looks at the factory type to find any RunLocal attributes. It totally ignores methods on your business class itself.

rockfordlhotka avatar Nov 19 '19 20:11 rockfordlhotka

OK, I think I'm getting it now. The ObjectFactory.Create can be marked RunLocal so it will still run on the client side in the ObjectFactory and the unmarked Execute would run on a remote server for example. I was concerned that it would call the remote server for the Create method. I was assuming the ObjectFactory only ran in a remote scenario. Oops.

Thanks Rocky

kellyethridge avatar Nov 19 '19 21:11 kellyethridge

[Create, RunLocal] private void Create() { }

Method can be marked as private,public is not ok

angtianqiang avatar Nov 28 '19 02:11 angtianqiang

I upgraded to csla 5.1.0 and I got a bunch of 'CSLA business objects should not be created outside of a ObjectFactory instance.' errors. Is there a place where I can download the whole project tracker that reflect this changes? It seems like in GitHub I can only download a single file by a single file. Also the ebook CSLA 2019 is only current to version CSLA 4.9.

Meanwhile here is one example of my code that chokes in CSLA 5.1.0

internal static PO GetPO(SafeDataReader dr) { return new PO(dr); }

where PO is a CSLA object in my project.

What should be the equivalent code in CSLA5.1.0?

Thanks very much.

KC7465128305 avatar Feb 25 '20 04:02 KC7465128305

Two quick things.

First, clone the repo from GitHub to get all the code. That's the easiest answer. Alternately GitHub has a way to download the repo as a zip file (I think from the releases page).

Second, use Data Portal.Create instead of the new keyword to create new instances.

rockfordlhotka avatar Feb 25 '20 05:02 rockfordlhotka

Thanks Rocky! Never expect you responsed to me almost 12 O'clock in the morning.😀


From: Rockford Lhotka [email protected] Sent: Monday, February 24, 2020 11:35 PM To: MarimerLLC/cslaforum [email protected] Cc: KC7465128305 [email protected]; Comment [email protected] Subject: Re: [MarimerLLC/cslaforum] CSLA business objects should not be created outside of a ObjectFactory instance (#817)

Two quick things.

First, clone the repo from GitHub to get all the code. That's the easiest answer. Alternately GitHub has a way to download the repo as a zip file (I think from the releases page).

Second, use Data Portal.Create instead of the new keyword to create new instances.

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/MarimerLLC/cslaforum/issues/817?email_source=notifications&email_token=AOUZK6QC6XTWFTWGANAKKTLRESUZLA5CNFSM4I2XCSCKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEM2UBXA#issuecomment-590692572, or unsubscribehttps://github.com/notifications/unsubscribe-auth/AOUZK6SN7BF5ZFDXYLDLPRLRESUZLANCNFSM4I2XCSCA.

KC7465128305 avatar Feb 25 '20 05:02 KC7465128305

Hi Rocky here is my issue. I migrated my project from .NET framework 4.7.2 with CSLA 4.10.0 to .NET Core 3.1 and CSLA-Core 4.11.2. I noticed that I got a null reference when I attempt to save my root object. For background information all my csla objects has a parent reference that pass in to the child when the child is created. This way given any csla object I can always 'walk up' to its parent, to its parent's parent....etc. until I got a null reference to which I know I have reached the root object. This way I can walk up and down the object tree to do things. Here is the variable/property for the parent reference in the child object.

    [NotUndoable]
    private IPOXEParent mobjIPOXEParent;
    public IPOXEParent IPOXEParent
    {
        get
        {
            return mobjIPOXEParent;
        }
    }

I marked it as [NotUndoable] so the reference won't participate in N Level Undo. Here is where I pass in the parent to the POXE child object:

    internal static POXE NewPOXE(IPOXEParent objIPOXEParent)
    {
          return new POXE(objIPOXEParent);
    }

    private POXE(IPOXEParent objIPOXEParent)
    {
          MarkAsChild();
          mobjIPOXEParent = objIPOXEParent;
          ……………...
   }

This has been working fine all along. Trouble begins when I upgraded to CSLA-Core 4.11.2. I noticed that when I attempt to save the root object, I noticed that the parent reference of the POXE child object became null. Here is the code:

    [Transactional(TransactionalTypes.TransactionScope)]
    protected override void DataPortal_Update()
    {           
         RereferenceMethod();
         if (base.IsDirty)
         {
                ……………...
                // update child objects
                if (FieldManager.FieldExists(POXEsProperty)) POXEs.Update(this, cm);
                ……………...
           }
     }

If I put a break point at the line

if (base.IsDirty)

and look at POXEs child object collection the POXE's parent reference IPOXEParent is null. So I upgraded to CSLA5.1.0 but the problem persists.

Please help me. Thanks!!!

Hi Rocky, can you confirm whether what I described above is a difference between CSLA 4.10.0 and CSLA 5.2.0? As a workaround I call a method (called RereferenceMethod()) at the location marked above to re-reference all the objects and it works for now but it is ugly and error prone because I have to manually use code to re-reference all the old references. Am I the only one of having this issue of losing reference after Save and do you have any plan to make the 5.2.0 version behave the same as the 4.10.0 version? Please let me know even if you are not going to do anything about it so I can plan ahead. Thanks very much!

KC7465128305 avatar Feb 26 '20 00:02 KC7465128305