TypedView VS EntityCollection (let the battle begin)

Posts   
 
    
Sam avatar
Sam
User
Posts: 95
Joined: 30-Jun-2004
# Posted on: 18-Nov-2005 05:15:40   

I am struggling with whether or not to use a TypedView or Collection of entities. Here is a simplified, contrived example of my problem:

I have a table of Foos...a bunch of them...and lets say Foo has columns TypeId, StateId, StatusId...whatever where each of these keys is a foreign key into another table with a description column describing what TypeId 1 and such is. Pretty standard stuff.

Now, in my UI I want to display a list (crap-load) of Foos. Obviously I don't want to display TypeId but the description form Type table, same goes for all other foreign key columns. Now,...I could, and have (it is my current solution) create a database view/TypedView that joins all the stuff up nicely and display that which seemed a perfectly acceptable solution at the time. But, the problem with it is: Lets say a user selects Foo[x] from my nice list and wants to view/edit its properties in a new details window. It would be nice if I could send the new window a reference to Foo[x] to edit but obviously that is not going to work as Foo[x] is of type FooTypedViewRow rather than type FooEntity. So what I have been doing is passing Foo[x].PK to the new window and fetching the entity doing some work on it and saving it. Lets say I change Foo[x].Title in the window. Now my List is inconsistent from the actual data so I would have to re fetch the typed view to keep things consistent. Please tell me there is a better way.

What I would like to do is have my List be a collection of FooEntities that way when I updated Foo[X] the list would be updated as well so I would not have to 1. fetch Foo[x] 2. have to reload the list if Foo[x] was edited. That said I cannot exactly bind my list (again huge list) to a FooCollection and call Foo.Type.Desctiption everytime I row loads into the view. An example...


MyList.Datasouce = FooHelper.GetAllFoos();

OnRowCreated(EventArgs e)
{
    e.Columns["Type"] = Foo.Type.Description;  //Call to database (lazy load) right?
    e.Columns["State"] = Foo.State.Description; //Call to database
    e.Columns["Status"] = Foo.Status.Desctiption; //Call to database
    ...
}
//(3 db calls per row) * (crap-load of rows) = too long to load right?

I am sure that this issue has been solved 300,000,000 times. Am I missing something here? How do you guys do it?

Sam avatar
Sam
User
Posts: 95
Joined: 30-Jun-2004
# Posted on: 18-Nov-2005 05:22:37   

Sorry last post was so long but it comes down to this:


MyList.Datasouce = FooHelper.GetAllFoos();

OnRowCreated(EventArgs e)
{
    e.Columns["Type"] = Foo.Type.Description; //Call to database (lazy load) right?
    e.Columns["State"] = Foo.State.Description; //Call to database
    e.Columns["Status"] = Foo.Status.Desctiption; //Call to database
    ...
}
//(3 db calls per row) * (crap-load of rows) = too long to load right?

VS


MyList.Datasouce = FooHelper.GetFooTypedList;

OnEditFoo(EventArgs e)
{
    FooTypedViewRow row = e.Row as FooTypedViewRow
    FooEntity foo = new foo(row.Id);  //Getting a new foo to edit even though row is essentially a foo
    details.Datasource = foo;
}

OnSaveFoo()
{
    MyList.Datasouce = FooHelper.GetFooTypedList(); //re fetching/messing up my list for no real good reason
}

Which is better?? OR (fingers crossed) is there a better solution to either of these.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 18-Nov-2005 11:19:30   

readonly data in list format: typed list/ dynamic list. If you need (a lot of) preprocessing per row and the data is used in readonly list format: typed view based on a view in the db.

read/write data: use an entity collection.

Ok, that's the core. Now, when to use lazy loading and when to use prefetch paths? use lazy loading if you load a lot of root entities and accidently need to fetch a related entity (like the user of the form needs extra data which is read on the fly. No real scientific proven formula here, but the # of related entities is way lower than teh # of root entities).

use a prefetch path if related data is always used or used a lot together with the root entities.

In your case, as you use the 3 related entities as well, use a prefetch path.

yet another way is to fetch the related entities once, for example in the case of a lookup table, and use databinding technology (setup simple databinding (property to property)) to select for example a Country entity in the list of Countries based on a CountryID in an entity in a collection. The user then selects a country from the country combo, and indirectly sets the countryID in the entity.

Frans Bouma | Lead developer LLBLGen Pro
jeffreygg
User
Posts: 805
Joined: 26-Oct-2003
# Posted on: 18-Nov-2005 22:30:47   

To expand on Frans' suggestions a little: wink

  1. If you use a read-only list and launch a detail form for editing, I would set up a simple Observer pattern that hands the changed entity back to the list upon save. This is really only workable in the simplest of situations, but it sounds like that's what you've got so it might work. Looks like you've got it, although perhaps instead of refetching you can just locate the changed row by ID and update the changes from the saved entity.

  2. Consider "Fields Mapped On Related Fields" as an alternative to creating a typed view. If the entity is simple enough and there aren't many additional columns, this can also be a good solution to avoid the fetch list -> fetch entity -> refetch list problem.

Jeff...