Hi
I am new to CSLA so please bear with me.
I know how to use editable BO and my understanding is in general you have a valid primary key (say taken from a grid listing valid records) with which to pass into BO.GetBO(myID).
I am having a brain block of how to implement CSLA best when most times you don't expect to find a value in the db each time e.g. scanning in an ISBN into a text box....sometimes the ISBN exists in the db othertimes its a new entry.
So would I do a..... if BO.Exists(ISBN) then...... first to see if the ISBN exists then use either BO.NewBO or BO.GetBO(ISBN) accordingly
or
would I use the BO.GetBO(ISBN) each time and handle inside the DataPortal_Fetch(crit.ISBN) the scenario of not finding a record.....but if I do this how do I implement the DataPortal_Create..can/do I call from within DataPortal_Fetch.
Or is there another way.....Any advice would be welcome.
Richard
I would use a command obect to see if the isbn exists, then fetch or create as required.
Heath
Richard,
I had this exact question 4 years ago when I first started with CSLA. At the time a partial consensus was formed to go ahead and do the check for existence and branch accordingly.
In the intervening years, Rocky decided to change CSLA to automatically call MarkOld() on root BOs as they return through the DataPortal from a Fetch. I discussed my objections with him at the time since it broke my code. This call "saved" the developer one line of code in each root BO. But it does not change the child behavior where the developer still needs to add it. I thought this was inconsistent and would lead to problems. But the CSLA community did not object as strenuously and the change was made. Therefore I have to comment out the calls for MarkOld and MarkNew in the framework.
Interestingly, Rocky got bitten by this implementation while working on WPF in the most recent version. It turns out his problem is identical to my original objection - there are times as a developer when I want the object to be New and other times I want it to be Old. And I need this to happen before returning through the DataPortal - e.g. when calling ValidationRules.CheckRules after a fetch - some rules may depend on if the BO is New or Old. So I have the code for MarkOld() in all my root BOs, just like I always used to. And if I happen to branch and return a New root BO then the framework code which I commented out does not burn me by changing it back to Old.
I think the current community consensus is to throw an Exception from DP_Fetch and handle it in the UI. e.g. the UI asks for a fetch of an ISBN, an exception is thrown because it is not in the DB and the UI catches it and then asks for a New BO by calling DP_Create.
4 years ago we decided to do the check in the BO layer and return a New object if it was not in the DB.
Here is how my Data Access region is currently laid out:
#
Region " Data Access " Protected Overridable Sub SetDefaults()#
Region "DataPortal_Create"<RunLocal()> _
SetDefaults()
MarkNew()
ValidationRules.CheckRules()
#
End Region#
Region " DataPortal_Fetch " Protected Overrides Sub DataPortal_Fetch(ByVal criteria As Object) MarkOld()
ValidationRules.CheckRules()
#
End RegionNote: I store all of my Criteria classes in a separate file and re-use them across all BOs that need them.
e.g.
<Serializable()> _
Note: I use the methodName parameter to branch in the DP if I have many factory methods fetching data and they use the same Criteria class. (If they use different Criteria clsases I can branch on TypeOf criteria.)
e.g.
Public Shared Function GetMyBO(ByVal mycode As String) As MyBOJoe
<Just keep in mind though that this isn't a supported scenario>
which scenario do you mean, ajj3085?
1. BO.Exists and branch
2. Raise error in DP_Fetch and handle in UI
3. Handle branching in DP_Fetch as per Joe
Copyright (c) Marimer LLC