In order for a relationship to be recognized as a Many to Many by EntitySpaces, it must be defined in the database using the standard associative table technique. If it is not, then the hierarchical Many to Many sub-object and the Associate/Dissociate methods will not be generated.
Most relational databases (including all five we support) do not have a Many to Many foreign key constraint. To handle this relationship, an artificial table (formally known as an associative table) is added to the database. It contains the links between the two tables. Northwind's EmployeeTerritories is the classic example. An Employee can be assigned to many Territories, and a Territory can have many Employees assigned to it. These links are all maintained in the EmployeeTerritories table.
Here is how the associative table must be defined:
1) It must have a composite primary key made of 2 or more columns.
2) Part of the composite key must contain a foreign key constraint to the primary key of a second table.
3) The other part of the composite key must contain a foreign key constraint to the primary key of a third table.
Code:
Employees EmployeeTerritories Territories
------------- ------------------- --------------
PK EmployeeID <-- PK EmployeeID
PK TerritoryID -------> PK TerritoryID
This is a simple cross-reference table. There are no other fields in it other than the composite key.
EntitySpaces will generate the following for the Employees class (with corresponding properties/methods in the Territories class):
- Many to Many -
UpToTerritoriesCollection - lazy-loads the Territories associated with the Employee.
AssociateTerritoriesCollection(terr) - Adds a row to EmployeeTerritories that links the Employee with the Territory.
DissociateTerritoriesCollection(terr) - Deletes the row in EmployeeTerritories that links the Employee to the Territory.
- Zero to Many -
EmployeeTerritoriesCollectionByEmployeeID - lazy-loads the EmployeeTerritories rows related to the Employee.
If an employee is re-assigned from one Territory to another, do not think of this as having to try to update a primary key in the EmployeeTerritories table. (EntitySpaces will not directly update primary keys.) This is easily handled by Associating the new Territory and Dissociating the old.
So, that seems to cover everything. What is that Zero to Many doing there? Not all Many to Many are simple cross-references. Northwind's OrderDetails is a Many to Many between Orders and Products. It is generally not thought of that way because it is not a simple cross-reference. It has fields for Quantity, Unit Price, and Discount. When you are dealing with an Order, do not use the Many to Many methods. Use the Zero to Many to retrieve and manipulate the OrderDetails table directly.
Hierarchical sample code can be found here.
Example associative table definition for a Many to Many:
Code:
CREATE TABLE [dbo].[EmployeeTerritories]
(
[EmployeeID] [int] NOT NULL,
[TerritoryID] [nvarchar](20) NOT NULL,
CONSTRAINT [PK_EmployeeTerritories] PRIMARY KEY NONCLUSTERED
(
[EmployeeID] ASC,
[TerritoryID] ASC
)WITH (PAD_INDEX = OFF, ...) ON [PRIMARY]
) ON [PRIMARY]
ALTER TABLE [dbo].[EmployeeTerritories] WITH CHECK ADD
CONSTRAINT [FK_EmployeeTerritories_Employees]
FOREIGN KEY([EmployeeID])
REFERENCES [dbo].[Employees] ([EmployeeID])
ALTER TABLE [dbo].[EmployeeTerritories] WITH CHECK ADD
CONSTRAINT [FK_EmployeeTerritories_Territories]
FOREIGN KEY([TerritoryID])
REFERENCES [dbo].[Territories] ([TerritoryID])
David Neal Parsons
www.entityspaces.net