StrataFrame Forum
Home      Members   Calendar   Who's On
Welcome Guest ( Login | Register )
      


12»»

Best practices for retrieving lookup values...Expand / Collapse
Author
Message
Posted 02/27/2008 3:52:43 PM
StrataFrame Novice

StrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame Novice

Group: StrataFrame Users
Last Login: 07/31/2008 2:53:17 PM
Posts: 53, Visits: 217
Hi,

I'm trying to figure out the best way to handle descriptive lookup values associated with foreign keys on a business object.  I've read some of the past discussions (e.g. http://forum.strataframe.net/Topic12507-7-1.aspx?Highlight=RowPopulating+browse) and it is looking like custom field properties may be the way to go in many cases. 

For example, I have a staffBO for all teachers in a school district.  Each record has an FK_School foreign key pointing to the teacher's school.  On my StaffMaintenanceForm Browse Dialog I want the school title (not FK) to show in the results column.  So I added a cSchoolTitle custom field to StaffBO as shown below (using a call to SchoolBO.FillByPrimaryKey()). 

This works fine, but I'm concerned about the speed and network demands of repeatedly doing a FillByPrimaryKey() each time a staff record is retrieved.  I'm also trying to better understand what is going on behind the scenes, so please bear with me...

Does the FillByPrimaryKey() actually query the backend School table for each staff record?... or is some fancy buffering going on?  I know doing this for a few hundred staff records may be trivial, but other tables with similar lookup requirements may have 10,000 records.

Is there a better way to just pull the entire School table into a local BO one time (using FillAll()) and look up the school titles there?  Would this alternate approach be preferable for small lookup tables?

I've considered using a multi-table BO (based on SQL views that have joins to needed lookup tables) but was stymied by how to make these updatable.

Thanks in advance,

Larry

Public ReadOnly Property [CSCHOOLTITLE]() As System.String

Get

Dim schoolbo As New SchoolBO

schoolbo.FillByPrimaryKey(Me.FK_SCHOOL)

If schoolbo.Count = 1 Then

Return schoolbo.CTITLE

Else

Return String.Empty

End If

schoolbo.Dispose()

End Get

End Property

Post #14580
Posted 02/27/2008 5:22:09 PM
StrataFrame Novice

StrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame Novice

Group: StrataFrame Users
Last Login: 08/18/2008 6:57:39 PM
Posts: 64, Visits: 543
Larry,

FillByPrimaryKey will just fill a BOs datatable with a single row, the hard work is done by the SQL server which with a primary key can go straight to the row very efficiently.

You could always make the schoolbo global, populate it once with all records, and then instead of FillByPrimaryKey use NavigateToPrimaryKey, but this is only going to be better for small tables where every row is likely to be accessed many times.

Peter

Post #14587
Posted 02/27/2008 6:54:48 PM
StrataFrame Novice

StrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame Novice

Group: StrataFrame Users
Last Login: 07/31/2008 2:53:17 PM
Posts: 53, Visits: 217
Peter,

This is exactly the kind of alternate approach I was wondering about.  How do you make a BO global?

Larry

Post #14591
Posted 02/27/2008 7:54:54 PM
StrataFrame Novice

StrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame Novice

Group: StrataFrame Users
Last Login: 08/18/2008 6:57:39 PM
Posts: 64, Visits: 543
Larry,

To make a BO Global, there are a couple of options, drop it on your form, or declare it in the global section of your form. You then have to populate it, either within the bo itself in the parent form loading event handler, or within the form in the form loading event handler.

Another thing to note is that if you are just going to use a bo for a lookup, you only need the Primary key, and whatever you want to display, anyhting else just uses extra memory for no good purpose. So you might want a lookup BO that is different to your maintenance/update/transactional BO.

Peter

Post #14592
Posted 02/28/2008 6:36:51 AM
StrataFrame Novice

StrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame Novice

Group: StrataFrame Users
Last Login: 07/31/2008 2:53:17 PM
Posts: 53, Visits: 217
Thanks Peter,

I will try this.  Thinking about it, my lookup based on the FillByPrimaryKey() is probably more than efficient enough.  It also has the benefit of immediately incorporating any new or edited lookup records that some other user may have created while the original user was active.  (The retrieved global BO would not "know" about these unless it was requeried). 

Larry

Post #14598
Posted 02/28/2008 9:28:06 AM


StrataFrame Developer

StrataFrame Developer

Group: StrataFrame Developers
Last Login: Today @ 5:44:29 PM
Posts: 4,366, Visits: 4,393
This works fine, but I'm concerned about the speed and network demands of repeatedly doing a FillByPrimaryKey() each time a staff record is retrieved.  I'm also trying to better understand what is going on behind the scenes, so please bear with me...

Filling the entire row is not a good idea in this scenario.  You can take two approaches.  First, I would put the load on SQL Server and include the field in the query versus making another trip to the server.  The fewer trips the better, and this can always be included in your query if necessary:

SELECT Staff.*, SchoolTitles.TitleName FROM Staff INNER JOIN SchoolTitles ON Staff.ForeignKey = SchoolTitles.PrimaryKey

Using this, you can create a custom property in the BO that uses the TitleName (which will already be retrieved from the initial query:

Public Readonly Property SchoolTitleName As String
   Get
      Return CType(me.CurrentRow.Item("TitleName"), String)
   End Get
End Property

The other way, which you may need to do within the BrowseResults, is to use the PopulatedThroughEvent and RowPopulating event (lots of samples and docs on this).  It is the same as a ListView.  In this case, you would want to use a Scalar method to retrieve the value...MUCH faster than pulling a full query as there is no TDS (tabular data stream) when pulling back a scalar method:

Public Function GetSchoolTitleName(Byval SchoolPkValye as Integer)
    Dim cmd As New SqlCommand("SELECT TitleName FROM SchoolTitles WHERE TitlePrimaryKey = @titlePrimaryKey")
    cmd.Parameters.AddWithValue("@titlePrimaryKey",SchoolPkValue).SqlDbType = SqlDbType.Int

    Return Me.ExecuteScalar(cmd)
End Function

Post #14603
Posted 02/29/2008 7:24:44 AM
StrataFrame Novice

StrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame Novice

Group: StrataFrame Users
Last Login: 07/31/2008 2:53:17 PM
Posts: 53, Visits: 217
Trent,

First, I would put the load on SQL Server and include the field in the query versus making another trip to the server.  The fewer trips the better, and this can always be included in your query if necessary:
SELECT Staff.*, SchoolTitles.TitleName FROM Staff INNER JOIN SchoolTitles ON Staff.ForeignKey = SchoolTitles.PrimaryKey

This is a very nice way to solve the lookup problem efficiently, with one trip to the server no matter how many staff records are pulled.  It is like using a multi-table view for my BO (joining staff and schools), but without the headache of dealing with an updatable SQL view. 

Thanks very much,

Larry

Post #14625
Posted 02/29/2008 8:29:58 AM


StrataFrame Developer

StrataFrame Developer

Group: StrataFrame Developers
Last Login: Today @ 5:44:29 PM
Posts: 4,366, Visits: 4,393
Thanks very much,

Glad to help

Post #14628
Posted 07/01/2008 9:31:53 AM
StrataFrame Novice

StrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame NoviceStrataFrame Novice