5

Mam trudny problem, w którym chciałbym użyć refleksji na temat mapowania mojego Entity Framework, aby znaleźć wszystkie klucze obce odnoszące się do tabeli, i chcę, aby nazwy kolumn są to klucze obce.Entity Framework - Refleksje na temat zagranicznych kluczy i relacji/stowarzyszeń

Zgodnie z another post on SO mogę łatwo znaleźć właściwości nawigacji na stole za pomocą odbicia. Ale to nie daje mi nazwy właściwości lub kolumny, która zawiera wartość klucza obcego.

Powodem, dla którego próbuję to zrobić, jest duża liczba tabel (prawie 40), które odnoszą się do jednej tabeli elementów. Powiedzmy, że użytkownik wprowadza nową wartość w tabeli elementów o nazwie "Andew", a później administrator zauważy, że jest to właściwie tylko literówka dla już istniejącego elementu "Andrew". Teraz chcę znaleźć wszystkie odniesienia do "Andew" i zmienić te odniesienia do "Andrew". Wolałbym zrobić to sprawnie, więc użycie właściwości nawigacji wstecznej byłoby zbyt wolne, ponieważ trzeba wczytać wartości przed ich modyfikacją. Co chciałbym zrobić, to móc odzwierciedlić listę tabel i kolumn, a następnie wydać polecenia aktualizacji bezpośrednio do bazy danych. Byłoby to wyglądać mniej więcej tak:

var command = String.Format("UPDATE [{0}] SET [{1}] = {{1}} WHERE [{1}] = {{0}}; ", fk.FromTableName, fk.FromColumnName); 
dataContext.ExecuteStoreCommand(command, new Object[] { oldID, newID }); 

w LINQ to SQL to było rzeczywiście bardzo proste ... 20 linii refleksji na LINQ auto-wygenerowany kod i skończyłam, ale przełącza się EF niedawno i ja nie może znaleźć nazw kolumn klucza obcego przez EF.

Uproszczony przykład tego, czego szukam: jeśli mam obiekt o nazwie Pracownik z właściwością nawigacji o nazwie Menedżer i klucz obcy z MenedżeraID, to chcę wiedzieć, że Menedżer jest moją właściwością nawigacji i bazą przechowywania jest właściwością ManagerID. Chcę to zrobić ściśle poprzez odbicie lub metadane, dzięki czemu mogę zbudować od niego zapytanie dynmaiczne.

+1

Masz głos w dół, więc zakładam, że nie jestem jedynym, który ma problem z rozumieniem, o co ci chodzi. możesz po prostu zrobić 'employee.managerId' lub' employee.manager.id'? musisz wiedzieć, co to jest konwencja, twój DBA nie może po prostu zmienić DB bez wpływu na twój projekt w inny sposób. – Eonasdan

+0

@Eonasdan - dzięki. Zastanawiałem się, dlaczego mnie nie doceniono. Przepisałem całkowicie, aby miejmy nadzieję, uczynić to znacznie bardziej przejrzystym. Niestety teraz jest znacznie dłuższy i starałem się go krótko. – pbarranis

Odpowiedz

1

Po wykorzystane pomysły w połączonej pytanie dostać się do EntityType jesteś zainteresowany, trzeba pamiętać, że EntityType dziedziczy z EntityTypeBase, który ma właściwość KeyMembers, która jest zbiorem wszystkich EdmMembers które uczestniczą w klucz podmiotu.

Każdy EdmMember ma Name, który będzie ciągiem "ManagerID", którego szukasz.

+1

To dobra myśl, ale muszę uzyskać nazwę obcego klucza na bieżącym obiekcie, a nie klucz obcego obiektu. Jest to różnica między wartościami myObject.ManagerID i myObject.Manager.ID. Nie używamy konwencji Managera.ManagerID - używamy Menedżera.ID - dlatego kolumny mają różną nazwę na każdym końcu. – pbarranis

1

Aby zaoszczędzić czas, chcę wyrzucić, to jest , a nie poprawna odpowiedź, ale możesz zrobić to, o co pytam poprzez widoki systemowe w SQL. Próbowałem tego i działa, ale to mi przeszkadza, że ​​mogę tak łatwo uzyskać te dane przez LINQ do SQL, ale nie mogę go znaleźć w ogóle w EF. Jeśli nie ma alternatywy, będę musiał użyć poniższego rozwiązania. (Ale EF musi mieć te dane wewnętrznie gdzieś ... Po prostu chcę do niego dostęp.)

select K.name as RelationshipName, T1.name as FromTable, C1.name as FromColumn, T2.name as ToTable, C2.name as ToColumn 
from sys.foreign_keys as K 
join sys.foreign_key_columns as C on K.object_id = C.constraint_object_id 
join sys.columns as C1 on K.parent_object_id = C1.object_id 
join sys.tables as T1 on K.parent_object_id = T1.object_id 
join sys.columns as C2 on K.referenced_object_id = C2.object_id 
join sys.tables as T2 on K.referenced_object_id = T2.object_id 
where C1.column_id = C.parent_column_id 
and C2.column_id = C.referenced_column_id 
and T2.Name = 'Employee' 
order by T1.Name, C1.Name 

Mam nadzieję delegowania to zła odpowiedź jest co najmniej przydatny do kogoś innego niż mnie ... (również tylko FYI , to rozwiązanie wymaga dużo więcej kodu do pracy z wielokolumnowymi PK - moje są wszystkie jednokolumnowe).