8

I have lots of instances two classes Children and Animal which have a many-to-many entity relationship.

I want to have a data structure such that given a Children I can get a list of Animal that are mapped to it and vice versa. For any given Animal I can get a list of Children that are mapped to it.

I need this data structure to be concurrent such that it can be accessed by any thread.

So given an example mapping:

Child1 -> Animal1 Child1 -> Animal2 Child1 -> Animal3 Child2 -> Animal2 Child2 -> Animal3 Child3 -> Animal3 

Querying for Child1 I wish to get a returned list: [ Animal1, Animal2, Animal2 ].

Querying forAnimal2 I wish to get a returned list: [ Child2, Child3 ].

The only way I could think to do this was using a dictionary and a list for each item in this dictionary (both Animals and Children) but I would then also have to deal with locking an synchronization of the lists which is troublesome.

7
  • 2
    You should really add a mapping table, such as AnimalChildren to help remove that many to many. Commented Mar 18, 2013 at 13:07
  • Using plural nouns for a class name is bad style; consider renaming your class to "Child". Commented Mar 18, 2013 at 13:52
  • Can this many-to-many relationship change over time, or once you have a set of children and animals, their relations are fixed? It is a lot easier to make an operation threadsafe if there are no writes. Commented Mar 18, 2013 at 13:53
  • @EricLippert yes the relationship can change. Commented Mar 18, 2013 at 14:01
  • OK, imagine that you have a graph data structure. Nodes are children and animals, and the relation is edges between them. Does the code doing the querying have a reference to just a node, or a node and the whole graph that the node is in? What I'm getting at is: is there some "database" object that you're querying, or do you have to have all the information in each individual object? Commented Mar 18, 2013 at 14:43

2 Answers 2

7

I think you have to split up your data structure into three tiers.

Child <- ChildToAnimalRelation -> Animal 

So Child and Animal both have collections of ChildToAnimalRelation

public class ChildToAnimalRelation { public Child Child { get; set; } public Animal Animal { get; set; } } 

Getting an animals children would be done as follows:

var children = currentAnimal.ChildToAnimalRelations.Select(r => r.Child); 

vice versa:

var animals = currentChild.ChildToAnimalRelations.Select(r => r.Animal); 
Sign up to request clarification or add additional context in comments.

3 Comments

Consider that by splitting in this way between different tiers, any type of update in your framework has to cary on updating every tier of interest.
The two lines getting the animals or children you put at the end of your answer will return all animals or children, not just the once for a given counterpart. You will have to add a where-clause beforehand...
@Spontifixus: the collection is on the counterpart itself and does not contain all relations. I edited the variable names to prevent confusion.
2

How about using a list and then use Linq for query? One possible implementation:

List<Tuple<string, string>> allItems=new ... allItems.Add(Tuple.Create("Child1", "Animal1"); ... var child1RelatedItems=allItems.Where(entry =>entry.Item1=="Child1"); var animal1RelatedItems=allItems.Where(entry =>entry.Item2=="Animal1"); ... 

2 Comments

Whether this will suffice depends mostly on the input. Its performance is directly related to how many relations there are (rather than how many children or animals). If the mapping between the two is dense, and you have lots of both...oi. If it's just a couple, this will do.
Probably not alone. The ChildToAnimalRelation class is serving the same purpose as your tuples. You don't gain anything but more descriptive names. What the other answer is doing is attaching the relations to each child and animal, so it only has to loop over the ones that match that particular thing.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.