MishMash wrote:
I'm a bit confused about adding new items to collections that are defined using an m:n relationship.
Here is an example:
I have a User entity/table, Role entity/table, UserRole m:n link table (with it's own primary key). All primary keys are GUIDs.
So when I look up a user, I can retrieve a Role collection by accessing the User.Role property. I can also User.Role.Add(Role r) to add a new role to my user.
If I do this, then iterate through the Role collection for my user, the new role is in the list, but when I do User.Save() no record is generated in the UserRole table, nor when I do User.Role.SaveMulti().
This is correct. The reason for this is is that LLBLGen Pro doesn't support recursive saves. Look at this example:
Department:
DepartmentID * | DepartmentName
Employee:
EmployeeID * | EmployeeName | DayOfBirth
DepartmentEmployee:
DepartmentID * | EmployeeID * | DateStarted
Now, Department and Employee have an m:n relationship. However doing this: Employee.Departments.Add(newDepartment); will never be able to be saved, because 'DateStarted' will not have a value. (the result of the objectified relationship)
Similar example: Order - Product. Have an m:n relationship via Order Line.
This way, you have to do the saving yourself, so you can set the proper values for the fields in the intermedate table, in your case UserRole.
We could have decided to allow you to update recursively in some occasions and not in other occasions. This however would also confuse developers and would break code when an intermediate table suddenly would get a non-PK field, like the 'DateStarted' field in my example: code which would save the related entity automatically would not work anymore since it requires a value for DateStarted. Now you have the mechanism in place in your code, you know what's going on.
I have maybe presumed too much, but if I can navigate to Role in this way from User for lookup, I'd expect to be able to add/update in the same way too...
You can walk the relations because the data is in the database. Fetching data is something else than writing it: as I've tried to illustrate above in my silly example is that writing data can be hard to do in an automatic scenario, but reading will always be the same.
Is the only way to add the Role by making an entry specifically in the UserRole collection (which of course exists owing to the data model)?
Correct. That's also the reason why the intermediate table is made available as an entity. M:n relations between entities is always seen as the same kind of relation, no matter what the intermediate table is: a table with just the PK fields, or also non-PK fields (like 'Order' in the m:n relation between Customer and Employee)