Hi
I'm developing a small app using CSLA 2.0 where the use case is as follows:
The user selects a date from the calendar, the system then loads the existing record (can only be 1) for that date. If no record exists then a new one is created.
In this scenario, my business object must first check if a record exists and if so, load it (DataPortal_Fetch). If no record exists then a new record is created (DataPortal_Create). Note that when no record exists, I cannot physically create that record until the user has entered the required data.
My question is how do I cater for this scenario within my business objects?
I was thinking of placing the logic within my factory method as follows:
public static MyObj CreateOrLoadObj(DateTime dt)
{
MyObj o = new MyObj();
o.DataPortal.Fetch(new Criteria(dt));
if(o.ID > 0)
{
//We have an existing record
}
else
{
//No existing record so create new one.
o = new MyObj();
o.Create(new Criteria(dt));
}
return o;
}
Does this look like the write approach? I think my main concern is that on calling the factory method, the object is remoted over then network to load the existing object and then returned to the client. If no existing record exists, then the object is again remoted over the network and a new MyObj is created before sending the object back over the network to the client.
Is there a better way of doing this?
TIA
Smeat
Hmm.. I hope I'm right with my idea in my mind...
A suggestion you might use the <RunLocal()> attribute in DataPortal_Create() if you are sure that all creates are to be run in the client.
So it will be something like this
<RunLocal()> _ Private Overloads Sub DataPortal_Create(ByVal criteria As Criteria) ' your implementation here End Sub
I think RunLocal() will force you to run in your client..
P.S. I'll be late in checking your replies because we are in different timezones.
Are you actually doing anything inside your DataPortal_Create()? If not then all you might need is a single call to DataPortal_Fetch().
Surely the criteria passed to the DataPortal_Fetch() will not return any data if there is nothing to get (i.e. there isn't already an item).
If this is the case, then what you have is an object that has already been instantiated (by the DataPortal) with all the default settings for your BO.
You will only need to set the fields within your BO if you actually get data back from the DB.
It's not a "purist' usage of the DataPortal_Fetch(), but there doesn't seem to be any reason why you shouldn't be able to take advantage of this "feature" of a DataPortal_Fetch() when the criteria returns an empty record set.
Perhaps you can try it to see if it works?
Smeat, if your new object doesn't have to retrieve any values from DB proceed to RunLocal() attribute. As what you said if there is an existing record it will return only 1 row. Combining the comments of Bayu and David, you can do it like this
Public Shared Function GetBusBaseName(ByVal id As Integer) As BusBaseName Dim o as BusBaseName = DataPortal.Fetch(Of BusBaseName)(New Criteria(id)) 'Exists is a readonly property name whos value will be set in the DataPortal.Fetch .... mExists = dr.Read() If o.Exists Then Return o Else Return DataPortal.Create(Of BusBaseName)(New Criteria(id)) End If End Function
Copyright (c) Marimer LLC