How to fetch related entities?

Posts   
 
    
Posts: 134
Joined: 04-Mar-2005
# Posted on: 12-Apr-2005 20:28:01   

Working with the following simplified model:

Customers have Contacts (1:n) Customers belong to Projects (m:n) Projects have Resources (1:n)

On the addition (or change) of a Customer to a Project I want to add all the Customer's Contacts to the Project as Resources (it's not really this simple but this demonstrates what I'm trying to solve).

So I figured that OnCustomerChanged of the ProjectCustomer entity (the m:n resolver) I'll fetch the Customer Entity, the Project Entity, the Contacts Collection for the Customer, and the Resources Collection for the Project. Then I'll add the Contacts as Resources checking for dupes.

So: 1. Is OnCustomerChanged even the right place to be doing this? 2. How can I fetch the project, etc. in the most efficient way (I would think that I'd construct a PreFetch path with the Project, Customer, Contacts, and Resources and then Fetch the ProjectCustomer but that's going to ditch my changed customer, right)? 3. If I'm using a UnitofWork how am I going to add these changes to that?

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 13-Apr-2005 09:58:50   

ChicagoKiwi wrote:

Working with the following simplified model:

Customers have Contacts (1:n) Customers belong to Projects (m:n) Projects have Resources (1:n)

On the addition (or change) of a Customer to a Project I want to add all the Customer's Contacts to the Project as Resources (it's not really this simple but this demonstrates what I'm trying to solve).

So I figured that OnCustomerChanged of the ProjectCustomer entity (the m:n resolver) I'll fetch the Customer Entity, the Project Entity, the Contacts Collection for the Customer, and the Resources Collection for the Project. Then I'll add the Contacts as Resources checking for dupes.

So: 1. Is OnCustomerChanged even the right place to be doing this?

I assume you're using adapter, so you'll need to supply an adapter object anyway, I'd go for a call to a method which does the fetching at the spot where you set the Project's customer, i.e.: in a routine which assigns a customer to a project and handles this fetching as well.

  1. How can I fetch the project, etc. in the most efficient way (I would think that I'd construct a PreFetch path with the Project, Customer, Contacts, and Resources and then Fetch the ProjectCustomer but that's going to ditch my changed customer, right)?

Fetch with a prefetch path: Project, ProjectCustomer, Customer, Contacts and resources. The m:n relation is readonly, you need the intermediate entities loaded as well.

  1. If I'm using a UnitofWork how am I going to add these changes to that?

The UnitOfWork is a collector for actions performed on entities and offers you a way to postpone all these actions till you call Commit. So every time you have to perform an action on a set of entities (no selects, just save/delete) you add the action to the UnitOfWork.

Frans Bouma | Lead developer LLBLGen Pro
Posts: 134
Joined: 04-Mar-2005
# Posted on: 13-Apr-2005 16:17:17   

Otis wrote:

I assume you're using adapter, so you'll need to supply an adapter object anyway, I'd go for a call to a method which does the fetching at the spot where you set the Project's customer, i.e.: in a routine which assigns a customer to a project and handles this fetching as well.

Setting the project's customer could be done at any spot. I can create a method to do this but there's nothing stop it being done directly so that's why I was going for OnCustomerChanged...

BTW: I am using adapter.

Otis wrote:

Fetch with a prefetch path: Project, ProjectCustomer, Customer, Contacts and resources. The m:n relation is readonly, you need the intermediate entities loaded as well.

Doesn't using a prefetch path mean that I'm going to have to re-fetch the inital (ProjectCustomer) entity? Is this the only way to fetch all of these entities in one call?

On a slightly separate topic: how do I just fetch a parent entity? I'm doing something like:


If Not (currentProjectCustomer.Project.Fields.State = EntityState.Fetched) Then
    'Fetch the project
    Dim adapter As DataAccessAdapter
    adapter.FetchEntity(currentProjectCustomer.Project)

However this isn't quite working as I'd expected it to...

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 14-Apr-2005 09:58:53   

ChicagoKiwi wrote:

Otis wrote:

Fetch with a prefetch path: Project, ProjectCustomer, Customer, Contacts and resources. The m:n relation is readonly, you need the intermediate entities loaded as well.

Doesn't using a prefetch path mean that I'm going to have to re-fetch the inital (ProjectCustomer) entity? Is this the only way to fetch all of these entities in one call?

Prefetch paths fetch a graph, you're fetching the graph again including the root entities/ entity. In 1.0.2004.2, you can use a Context to keep the same instance, and to fetch new entities into an existing graph.

On a slightly separate topic: how do I just fetch a parent entity? I'm doing something like:


If Not (currentProjectCustomer.Project.Fields.State = EntityState.Fetched) Then
    'Fetch the project
    Dim adapter As DataAccessAdapter
    adapter.FetchEntity(currentProjectCustomer.Project)

However this isn't quite working as I'd expected it to...

parent and child are relative things, I don't use them much. Entities are related to eachother, and if you have B and you want a related A, you use the relation they have and fetch A using that info.

Your code will only work if currentProjectCustomer.Project has its PK field(s) set to a value. You'd better use currentProjectCustomer.Project = (ProjectEntity)adapter.FetchNewEntity(new ProjectEntityFactory(), currentProjectCustomer.GetRelationInfoProject());

Frans Bouma | Lead developer LLBLGen Pro