Create Relationship At Runtime?

Posts   
 
    
ScottCate
User
Posts: 48
Joined: 11-May-2005
# Posted on: 17-May-2005 18:53:00   

I have an LLBLgen'd DAL that is done and in use today for an application.

We have several projects now, where customers have contracted us to extend the application for them.

So my Goal is to keep my core project as is, and extend it for each customer.

My first guess is this.

Say the core database/application has an Entity Called Product, and our client wants to add extended fields/properties to that entity.

So I add a table to the customer catalog, called ProductExtension. ProductExtensionId - GUID Product - GUID Width Height Weight Color

Now I have a 1:1 extension table for data, but I'm going to have a hard time getting the data back into the LLBLgen'd product. If I add a relationship, then the LLBLGen'd code is going to duplicate my oroginal ProductEntity, so I'm not adding a relationship in the database.

I can use inheritance chain, to help as a facade object.

pseudo ...

public class ClientProduct : ProductEntity
{
   ClientFields ProductExtensionEntity;
}

Then I have a new object that will nicely work for all the data round trip in llblgen, but I have to call all the methods twice, once on product, and once on ProductExtention. Sure I can override the save() and do the code in there, but I'm still calling the code twice, and doing two round trips to the database.

This is all because I don't know how, or if, there is a way to set relationships programatically, after the code has been gen'd.

<summaryQuestion>

Can I add the 1:1 PK/FK relationship in code, after the projects have been created, or am I on the right track with the inheritance style above? Or is there something else that I haven't seen or thought of yet?

</SummaryQuestion>

Thanks for the guidance.

cmartinbot
User
Posts: 147
Joined: 08-Jan-2004
# Posted on: 17-May-2005 21:39:05   

I have a couple of thoughts on this. This is all "in theory" kind of stuff.

  1. Why not just create a seperate table in the original schema that will hold custom properties of Product called ProductProperty. This table would have a 1:n relationship to Product.

Doing this will give you the ability to add custom properties to a Product that you can add on a customer to customer basis. Also, the properties will come back as an EntityCollection and you can just create a custom business layer for the customer.

  1. If you create a new DAL for custom customers, you could override copy the contents of the original DatabaseSpecific.PersistenceInfoFactory into your new DatabaseSpecific.PersistenceInfoFactory. Then, in your new data project, add a referrence to the original data project.

Now in your original business layer you can add save and delete methods to your manager classes that would return a UnitOfWork2 object instead of doing the work themselves.

So you now have a custom business layer that can talk to not only your new data layer but also the original layer and the original business layer. You can grab UnitOfWork2 objects form the original business layer and do your work in the new business layer without calling Save twice.

I would probably go with option 1 because 2 sounds like an awful lot of work to do just to avoid two calls to the DB. wink

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 18-May-2005 11:06:06   

ScottCate wrote:

I have an LLBLgen'd DAL that is done and in use today for an application.

We have several projects now, where customers have contracted us to extend the application for them.

So my Goal is to keep my core project as is, and extend it for each customer.

My first guess is this.

Say the core database/application has an Entity Called Product, and our client wants to add extended fields/properties to that entity.

So I add a table to the customer catalog, called ProductExtension. ProductExtensionId - GUID Product - GUID Width Height Weight Color

Now I have a 1:1 extension table for data, but I'm going to have a hard time getting the data back into the LLBLgen'd product. If I add a relationship, then the LLBLGen'd code is going to duplicate my oroginal ProductEntity, so I'm not adding a relationship in the database.

I'm not understanding the 'duplicate my original ProductEntity' remark, could you explain that a bit?

This is all because I don't know how, or if, there is a way to set relationships programatically, after the code has been gen'd.

Yes you can. You can create an EntityRelation instance in code, which is usable in filters for example. The downside is that you don't have collections like customer.orders in the classes which are mapped on the relations in code.

You can of course add them in a derived class, though with recursive saves it will be a bit problematic.

<summaryQuestion>

Can I add the 1:1 PK/FK relationship in code, after the projects have been created, or am I on the right track with the inheritance style above? Or is there something else that I haven't seen or thought of yet?

</SummaryQuestion>

Well, I think you can also use a new DAL for the new customer. I say this because your code will be custom anyway (i.e. will not work with the original dal, as that dal doesn't have a definition for the new tables for this customer). If you keep a set of tables fixed, which are shared among every customer's installation and you then add per customer, new tables in a new dal, you can get it working like this: 1) create a schema with the fixed set of tables. This is your starting point. Create a project with this schema/catalog. Save it 2) create per customer their own catalog/schema. Add the tables using DDL created from the fixed set schema. 3) copy for each customer, the fixed set .lgp. 4) per customer, open its own .lgp file, and refresh the catalog on that customer's own schema. 5) Generate code. As the fixed set is setup the same for every customer in the same way, your code targeting that fixed set is the same. Though the per-customer code is different per customer.

Frans Bouma | Lead developer LLBLGen Pro
ScottCate
User
Posts: 48
Joined: 11-May-2005
# Posted on: 18-May-2005 19:20:55   

What I'm trying to avoid is duplication of the original entities on a per project basis. I agree that your final solution would work, in that I can duplicate the entire DAL for each customer.

But this kills my forward compatibility. I can no longer add a field to the base database, give the entire world an upgrade, and not break anything.

With the idea that I can create a new DAL for each customer, with only that customers extension data, I can maintain forward compatibility, as long as my PK field names don't change.

So I think I'm stuck with what CMartinBot talked about, which was pretty much the same as my original idea, having to make 2 calls to the database.

I was hoping (and may still be able to with a little work) set the relationship at run time, and then when I instantiated an Entity, with the proper prefetch, it would give me the wholly populated object. And the save would know to do the same.

ScottCate
User
Posts: 48
Joined: 11-May-2005
# Posted on: 18-May-2005 21:53:22   

Otis wrote:

I'm not understanding the 'duplicate my original ProductEntity' remark, could you explain that a bit?

I'm trying to avoid the Code being generated twice, in two different projects.

My Original project already has a ProductEntity.

Generating another project, if I set the relationship up for ProductExtension to ProductEntity will recreate all the code again.

So ideally I want (and it's what i Have working now) is two projects. One originally gen'd project, and a new project for the extension data.

Now if I can figure out the

Otis wrote:

You can create an EntityRelation instance in code

I should be in good shape.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 18-May-2005 22:19:20   

(I'll answer the other posting in the morning, I'll just answer this one so you can continue simple_smile )

ScottCate wrote:

Otis wrote:

I'm not understanding the 'duplicate my original ProductEntity' remark, could you explain that a bit?

I'm trying to avoid the Code being generated twice, in two different projects. My Original project already has a ProductEntity.

Generating another project, if I set the relationship up for ProductExtension to ProductEntity will recreate all the code again.

So ideally I want (and it's what i Have working now) is two projects. One originally gen'd project, and a new project for the extension data.

Aha simple_smile . Well, you could opt to throw away some classes in the second project of course, which are filled in by the original, if you keep the second project in the same namespace, it would be fine.

Now if I can figure out the

Otis wrote:

You can create an EntityRelation instance in code

I should be in good shape.

Please check the RelationClasses for each entity. The properties in there show you how to create an EntityRelation object in code simple_smile . It's a few lines.

Frans Bouma | Lead developer LLBLGen Pro
ScottCate
User
Posts: 48
Joined: 11-May-2005
# Posted on: 19-May-2005 01:46:12   

That makes sense. I can fully generate the second project, and then remove the base entities and base relations.

A little more work, but worth the trouble to maintain fwd compatibility.

Sometimes the best answer is also the easiest simple_smile

Thank you.

Otis avatar
Otis
LLBLGen Pro Team
Posts: 39933
Joined: 17-Aug-2003
# Posted on: 19-May-2005 10:27:44   

ScottCate wrote:

That makes sense. I can fully generate the second project, and then remove the base entities and base relations.

A little more work, but worth the trouble to maintain fwd compatibility.

Sometimes the best answer is also the easiest simple_smile

Thank you.

simple_smile . Glad it's solved in a way you can live with simple_smile

Frans Bouma | Lead developer LLBLGen Pro