Suppose I have 2 tables in a database. eg: Dog & Boss This is a many to many relationship, cause a boss can have more than 1 dog, and a dog can have more than 1 owner. I am the owner of Bobby, but so is my wife.
But many to many is not allowed, so there is a helpertable: DogsPerBoss
How to model this in code?
Class Boss can have a collection of Dogs. Class Dog can have a collection of Bosses. --> at least, that is what I think. Perhaps there are better solutions?
How about extra data that is in the helper-table? Should that be in de Boss-class or in the Dog-class? eg: Nickname (I call the dog "good boy" and my wife calls him "doggie")
I hope my question is kinda clear? Are there any best-practices on what is the best way to achieve this? Can you give me some references?
An ORM (like NHibernate) is not an option.
The many-to-may relationship can be achieved using HasMany and WithMany methods. The default conventions for many-to-many relationships creates a joining table with the default naming conventions. You can customize a joining table name and column names using Fluent API.
When you have a many-to-many relationship between dimension-type tables, we provide the following guidance: Add each many-to-many related entity as a model table, ensuring it has a unique identifier (ID) column. Add a bridging table to store associated entities. Create one-to-many relationships between the three tables.
When you need to establish a many-to-many relationship between two or more tables, the simplest way is to use a Junction Table. A Junction table in a database, also referred to as a Bridge table or Associative Table, bridges the tables together by referencing the primary keys of each data table.
Why are you talking about tables? Are you creating an object model or a database model?
For an object model, there's no reason a Dog can't have a List<Owner>
and an owner have a List<Dog>
. Only if you have attributes on the relationship do you need an intermediate class (what UML calls an Association Class). That's when you'd have a DogOwnership class with extra properties, and each Owner would have a List<DogOwnership>
, and so would each Dog. The DogOwner would have a Dog, an Owner, and the extra properties.
public class Boss { private string name; private List<Hashtable> dogs; private int limit; public Boss(string name, int dogLimit) { this.name = name; this.dogs = new List<Hashtable>(); this.limit = dogLimit; } public string Name { get { return this.name; } } public void AddDog(string nickname, Dog dog) { if (!this.dogs.Contains(nickname) && !this.dogs.Count == limit) { this.dogs.Add(nickname, dog); dog.AddBoss(this); } } public void RemoveDog(string nickname) { this.dogs.Remove(nickname); dog.RemoveBoss(this); } public void Hashtable Dogs { get { return this.dogs; } } } public class Dog { private string name; private List<Boss> bosses; public Dog(string name) { this.name = name; this.bosses = new List<Boss>(); } public string Name { get { return this.name; } } public void AddBoss(Boss boss) { if (!this.bosses.Contains(boss)) { this.bosses.Add(boss); } } public void RemoveBoss(Boss boss) { this.bosses.Remove(boss); } public ReadOnlyCollection<Boss> Bosses { get { return new ReadOnlyCollection<Boss>(this.bosses); } } }
The above maintains the relationship of Bosses can have multiple dogs (with a limit applied) and dogs having multiple bosses. It also means that when a boss is adding a dog, they can specify a nickname for the dog which is unique to that boss only. Which means other bosses can add the same dog, but with different nicknames.
As for the limit, I would probably have this as an App.Config value which you just read in before instantiating the boss object(s). So a small example would be:
var james = new Boss("James", ConfigurationManager.AppSettings["DogsPerBoss"]); var joe = new Boss("Joe", ConfigurationManager.AppSettings["DogsPerBoss"]); var benji = new Dog("Benji"); var pooch = new Dog("Pooch"); james.AddDog("Good boy", benji); joe.AddDog("Doggy", benji); james.AddDog("Rover", pooch); joe.AddDog("Buddy", pooch); // won't add as the preset limit has been reached.
You can obviously tweak this as you see fit, however, I think the fundamentals of what you are looking for are there.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With