Doing some initial prototyping with CSLA...
How might one best handle a call to the static factory method GetMyClass(...) when no results are returned (often a real scenario). As I have it coded now (using CodeSmith templates as a starting point), an InvalidOperationException is thrown when trying convert data that doesn't exist in the SafeDataReader into the private members of the class.
One could catch the InvalidOperationException and handle it (return null?), but I'm worried that this might mask other problems throwing the same exception. How do you experts do it?
This has likely come up before, but I was unable to find it by searching the forum.
TIA,
Glenn
Generally, I have users select an object from a list, so it's existance is almost guaranteed. I could see a MRU List or opening the last open object situation where the object could have been deleted in the mean time. In those cases, I would problaby do a if (MyClass.Exists(classId)) first rather than a check for a null return value or exception.
Also, most of the examples do a simple dr.Read(); and then get the values, simply checking the return value from that would allow you to gracefully exit. You might have to set a private flag to allow the Factory method to return null instead of an empty object
E
When this question came up 4 years ago the community was split between returning an exception and returning a New object. I went with returning a New object. It works out for me.
But Rocky is in the Exception camp and so subsequent changes to CSLA have caused me a little pain. e.g. Rocky moved MarkOld into the frameowrk instead of leaving it as a developer step to implement for Root objects. This has caused timing issues and so I have had to comment it out and use my older style. Rocky has run into a problem with it in WPF too so it may not have been the best move. But it is there now so...
I recommend you throw some sort of exception when you check If dr.Read = True. This seems to be the current consensus.
Joe
JoeFallon1:But Rocky is in the Exception camp and so subsequent changes to CSLA have caused me a little pain. e.g. Rocky moved MarkOld into the frameowrk instead of leaving it as a developer step to implement for Root objects. This has caused timing issues and so I have had to comment it out and use my older style. Rocky has run into a problem with it in WPF too so it may not have been the best move. But it is there now so...
See Page 100 of Using CSLA 3.0 (VB edition).
In DataPortal_Update Rocky calls MarkOld() explicitly. This is because it needs to be marked old *before* ExecuteWorkflow is called. So the framework call to MarkOld happens *too late* in the process.
This is similar to my logic which says I need to explicitly call MarkOld on my root BOs because when I call CheckRules some of the rules need to know if the object is New or Old. So again, the framework call hapens too late in the process.
Therefore, I think the call to MarkOld should be removed from the framework as it interferes with the correct working of many scenarios. Or if I call it explicitly then the call is redundant.
Joe
Hmmm.
We just return null rather than an object (from our factory "getter") I'm not sure why this would be bad, but it makes writing code quite simple (e.g.)
if (ObjectClass.Get(criteria) == null)...
^^^^^
After I posted the above, I remembered that null causes us issues if it's for a child of a bound root object. It's not too bad, but we have to test for it and substitute an "empty" object for the bindingsource when it happens , so it does have some consequences.
ajj3085:Oh... WF. I looked up that sample in the ebook. Given the explaination, it seems that the call to ExecuteWorkflow could be moved to the DataPortal_OnDataPortalInvokeComplete override, and that would remove the need for the explicit MarkOld.
Of course, this also seems to be an edge case, and calling MarkOld explicitly in the DataPortal method doesn't hurt anything. In the normal case, its one less thing for me and other Csla-ers to forget.
Joe's going to love 3.5 - or not...
In 3.5 the data portal now supports saving child objects - which simplifies your code a lot - no need to override DP_U in a list, and much more standard coding in editable child objects.
But of course the data portal now calls MarkOld() (, etc.) on the child objects just like it does for root objects. That's part of making the code more standard, which I think is a powerful benefit.
Fortunately, you don't have to use the child management - the 2.0/3.0 style coding approach works fine.
I made sure to support both because the new way is slower, but oh so much nicer - but I wanted to make sure people could choose between performance/flexibility and simplicity/productivity
Andy
That's really funny:
"there is a case where I create a new object when one doesn't exist. In the end, the object must be New, but also Not Dirty. "
This is exactly my coding style. I test for existence and then branch to DP_Create or stay in DP_Fetch. The problem is that the Framework now calls MarkOld for you because it started in DP_Fetch and doesn't care that you don't want an old object - you now want a new one.
This is why manually coding the MarkOld and MarkNew in the classes is a "better way to go" in my opinion. At least for this coding style. I would have to re-write hundreds of classes and do a massive amount of re-testing to "get in alignment" with the currently accepted way of handling this.
That isn't going to happen. I think I will just continue to comment out the calls to MarkOld in the framework and call it a day. <g>
Joe
Copyright (c) Marimer LLC