Description:
I have a main FamilyMember class. I want to figure out how to define a marriage between two different FamilyMember objects. I also have some more information that I would like to store about a marriage (date, place, etc.). Also the system needs to be able to support multiple marriages for any FamilyMember object. Ideally I would like the system to restrict a marriage relationship to only two FamilyMember objects. How can I define a custom many to many relationship between two different objects in the same class? Also, how can I define these associations?
Answer:
We would advise you to create a many-to-many association between the FamilyMember and Marriage classes and introduce a new class which will control marriages:
C#public class FamilyMember : XPObject {
protected override void BeforeSave() {
base.BeforeSave();
MarriagesController.CheckFamilyMember(this);
}
public string FirstName;
public string LastName;
[Association("FamilyMember-Marriages", typeof(Marriage))]
public XPCollection Marriages { get { return GetCollection("Marriages"); } }
}
public class Marriage : XPObject {
protected override void BeforeSave() {
base.BeforeSave();
MarriagesController.CheckMarriage(this);
}
public string Place;
public DateTime Date;
[Association("FamilyMember-Marriages", typeof(FamilyMember))]
public XPCollection Partners { get { return GetCollection("Partners"); } }
}
public class MarriagesController {
public static MarriagesController CurrentController = new
MarriagesController();
public static void CheckFamilyMember(FamilyMember familyMember) {
CurrentController.Check(familyMember);
}
public static void CheckMarriage(Marriage marriage) {
foreach(FamilyMember partner in marriage.Partners) {
CheckFamilyMember(partner);
}
}
public virtual void Check(FamilyMember familyMember) {}
}
Now you can control the marriage rules via the CurrentController property.
For instance, you can check the number of people participating and count the number of marriages:
C#public class MyMarriagesController : MarriagesController {
public override void Check(FamilyMember familyMember) {
if (familyMember.Marriages.Count > 1) {
throw new Exception("...");
}
foreach(Marriage marriage in familyMember.Marriages) {
if (marriage.Partners.Count != 2) {
throw new Exception("...");
}
}
}
}
Another way is to create your own persistent object for this many-to-many relation and implement the necessary rules within its BeforeSave method:
C#public class FamilyMemberToMarriageLink : XPObject {
protected override void BeforeSave() {
base.BeforeSave();
//...
}
public FamilyMember FamilyMember;
public Marriage Marriage;
}
See also:
How to change the name of the underlying table and columns for a many-to-many relationship
What is the best solution for mapping a many-to-many relation to an existing database?
How to delete an object which is participating in a many-to-many relation