Fetch a particular object without criteria

Fetch a particular object without criteria

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


Michael Hildner posted on Tuesday, July 11, 2006

Hello,

I'm a little unsure how to accomplish this, looking for some help.

Let's say I have an object, CustomerReadOnlyRoot, that I need to fetch. The data access is done through stored procedures. I don't know anything about the Customer, like primary key etc. Instead I need to use a stored procedure such as SelectMostActiveCustomer or SelectMostRecentCustomer.

I'm thinking I'd like to have public methods in my BO like .GetMostActive() and .GetMostRecent(). How do I set up the DataPortal_Fetch method(s) so I can specify which sproc to use?

I haven't delved into this part of CSLA, so not sure if I'd use some sort of Criteria or not.

Thanks,

Mike

skagen00 replied on Tuesday, July 11, 2006

Your logic for selecting the customer doesn't really change, right? You still are going to want to fetch the same information for a customer by ID - you don't know the ID up front. You need to get it first.

One option might be to have a couple command objects that are used to get the most active and most recent id, respectively. You might have factory methods on your object for Customer.GetCustomer(id), along with two for these purposes Customer.GetCustomerMostActive() and Customer.GetCustomerMostRecent(). The first task of the two new factory methods would be to invoke a command object needed to get the appropriate Id, and then delegate the call to Customer.GetCustomer() with the right Id.

That would be my suggestion...

Hope this helps.

Chris

... or, you could embed the extra fields into your Criteria object and then populate it differently for each factory method - one would assign the Id, one a flag for MostRecent, and one for MostActive. In your fetch if the Id doesn't exist you could just call the stored procedure based on which flag was checked and then utilize that Id returned by the stored procedure.

hurcane replied on Wednesday, July 12, 2006

skagen00:

One option might be to have a couple command objects that are used to get the most active and most recent id, respectively. You might have factory methods on your object for Customer.GetCustomer(id), along with two for these purposes Customer.GetCustomerMostActive() and Customer.GetCustomerMostRecent(). The first task of the two new factory methods would be to invoke a command object needed to get the appropriate Id, and then delegate the call to Customer.GetCustomer() with the right Id.



I would vote for the command objects myself, but I would have the command objects return a concrete editable customer rather than an ID. Consider the case of a remote data portal. If you fetch the ID, you're making a round trip. A second round trip is needed to get the customer.

If the command object returns the customer object, the call to the customer object's factory method is done from within the command object's DataPortal_Execute method. With a remote data portal, the object is already running on the server, and an extra round trip is not necessary.

SonOfPirate replied on Friday, July 14, 2006

I agree with hurcane and he very aptly stated exactly what I was thinking.  However, I won't discount Fabio's solution either.  What it really boils down to is WHERE you want your logic to exist.  The command object approach allows you to encapsulate the logic of each method into your BO - at least as far as the sproc name is concerned in this case.  Going with the enumerated parameter approach means that your sproc is a little more complicated, a single sproc is handling three different duties, etc.

Either way is valid, but I like the command object approach for consistency's sake.

btw - we have implemented this type of construct for many dynamic features in web apps such as "Recent News" or "Today's Headlines" where the query is different than the standard.  In these cases the methods and command objects are on the collection and return the collection, but the logic/approach is the same.

Hope that helps.

Fabio replied on Tuesday, July 11, 2006

Your criteria can look like (in your bo):
public enum MostMode
{
MostRecent,
MostActive
}

public class CriteriaMost
{
private MostMode _mostMode= MostMode.MostRecent;
public CriteriaMost(MostMode aMostMode)
{_mostMode = aMostMode;}
public MostMode Mode
{get {return _mostMode;}}
}

And your factory look like:
    public static Customer GetMostActive()
    {
      return Csla.DataPortal.Fetch<Customer>(new CriteriaMost(MostMode.MostActive));
    }


Then you must have a DataPortal_Fetch ....
Bye.
Fabio.

RockfordLhotka replied on Tuesday, July 11, 2006

Version 2.0.2 introduced the idea of a parameterless DataPortal.Fetch() call. Which means no criteria is passed to the DataPortal_Fetch() method at all. So if you can figure out what to do in that method with no criteria at all, then you can do this:

Factory:

Public Shared Function GetObj() As Obj
  Return DataPortal.Fetch(Of Obj)()
End Function

Data access:

Protected Overrides Sub DataPortal_Fetch(ByVal criteria As Object)
  ' criteria is Nothing/null - just ignore it
End Sub

 

Michael Hildner replied on Tuesday, July 11, 2006

Thanks all for the replies.

Just checking things out for now, but using something similar to Fabio's suggestion. Then in the _Fetch, using a switch (Select Case) to set the stored procedure name. Seems strait-forward and easy to read.

Regards,

Mike

Copyright (c) Marimer LLC