2013-03-18 14 views
8

Mam wiele wystąpień dwie klasy Children i Animal, które mają wiele-do-wielu relacji encji.Jakich struktur danych używam tutaj?

Chcę mieć strukturę danych, tak, że biorąc pod uwagę Children mogę uzyskać listę Animal, które są mapowane do niego i na odwrót. Dla każdego podanego Animal mogę uzyskać listę Children, które są do niej mapowane.

Potrzebuję tej struktury danych, aby była współbieżna, tak aby była dostępna dla dowolnego wątku.

Więc podano przykładowe odwzorowanie:

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

Zapytania na Child1 pragnę uzyskać zwrócony listę: [ Animal1, Animal2, Animal2 ].

Zapytanie o numer Animal2 Chcę otrzymać zwrócony list: [ Child2, Child3 ].

Jedyny sposób, w jaki mogłem to zrobić, to użycie słownika i listy dla każdego elementu w tym słowniku (zarówno dla zwierząt, jak i dla dzieci), ale musiałbym również poradzić sobie z blokowaniem synchronizacji list, co jest kłopotliwe .

+2

Naprawdę powinieneś dodać tablicę odwzorowań, taką jak AnimalChildren, aby pomóc w usunięciu wielu osób. – mattytommo

+0

Używanie rzeczowników w liczbie mnogiej dla nazwy klasy jest złym stylem; rozważ zmianę nazwy swojej klasy na "Dziecko". –

+0

Czy ta relacja wiele do wielu zmienia się z czasem, czy też, gdy masz już dzieci i zwierzęta, ich relacje są stałe? O wiele łatwiej jest wykonać operację threadassy, ​​jeśli nie ma zapisów. –

Odpowiedz

7

Myślę, że trzeba podzielić strukturę danych na trzy poziomy.

Child <- ChildToAnimalRelation -> Animal 

Więc Child i Animal oba mają zbiory ChildToAnimalRelation

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

Pierwsze zwierzęta dzieci byłyby wykonywane w następujący sposób:

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

odwrotnie:

var animals = currentChild.ChildToAnimalRelations.Select(r => r.Animal); 
+0

Należy zauważyć, że dzieląc w ten sposób między różnymi poziomami, każdy rodzaj aktualizacji w ramach systemu musi aktualizować każdy poziom zainteresowania. – Tigran

+0

Dwie linie, na których znajdują się zwierzęta lub dzieci umieszczone na końcu odpowiedzi, zwrócą * wszystkie * zwierzęta lub dzieci, a nie tylko raz dla danego odpowiednika. Będziesz musiał wcześniej dodać klauzulę where ... – Spontifixus

+0

@ Spontifixus: kolekcja znajduje się na odpowiedniku * sama * i nie zawiera * wszystkich * relacji. Edytowałem nazwy zmiennych, aby zapobiec nieporozumieniom. –

2

Co powiesz na używanie listy i użycie Linq do zapytania? Jedna z możliwych implementacji:

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"); 
... 
+0

To, czy to wystarczy, zależy głównie od danych wejściowych. Jego wydajność jest bezpośrednio związana z liczbą powiązań (zamiast liczby dzieci lub zwierząt). Jeśli odwzorowanie między nimi jest gęste i masz dużo obu ... oi. Jeśli to tylko para, zrobi to. – cHao

+0

Czy ChildToAnimalRelation powyżej rozwiązać ten problem? – David

+2

Prawdopodobnie nie sam. Klasa ChildToAnimalRelation służy temu samemu celowi co krotki. Nie zyskujesz niczego oprócz bardziej opisowych nazw. To, co robi inna odpowiedź, to powiązanie relacji z każdym dzieckiem i zwierzęciem, więc musi tylko zapętlić te, które pasują do tej konkretnej rzeczy. – cHao

Powiązane problemy