2010-10-26 5 views
14

Jest to czysto koncepcyjny i projektowy pomysł związany z EF4.Modyfikowanie modelu struktury obiektu w czasie wykonywania

Przykład/scenariusz to duży system typu ERP lub CRM, w którym firmy mogą potrzebować dodawać tradycyjne "pola zdefiniowane przez użytkownika" w celu przechwytywania dodatkowych danych.

Wiem, że EF ma pewne możliwości wypchnięcia modelu do bazy danych w czasie wykonywania, ale czy naprawdę można użyć EF do modyfikacji modelu i aktualizacji magazynu danych w czasie rzeczywistym?

Innymi słowy, jeśli udostępnię użytkownikowi mechanizm dodawania kolumny zdefiniowanej przez użytkownika, powiązanego typu danych i wymagań null, można to zrobić w locie z EF, a następnie zapamiętać dla wszystkich przyszłych sesji?

Jest tam, ale myślę, że wszyscy zobaczą, do czego zmierzam.

Brent

+0

Więc skończyłeś z którym rozwiązaniem? – Guillaume

+0

Ja nie. Nigdy nie udało się przetestować ani uzyskać niczego do pracy. W końcu i tak chodziłem z kodem na pierwszym planie. –

Odpowiedz

14

Kilka razy zadawano mi to pytanie w przeszłości. Nie ma oczywistego ani łatwego sposobu. Możliwe, że nie ma mowy, że jesteśmy deweloperami i zawsze jest jakiś sposób! Czy wiem, co to jest? Nie. Czy mogę wymyślić jakieś pomysły? .... Mmmm .. w czasie wykonywania, model oparty jest na silnie typowanych klasach z metadataworkspace. Możesz tworzyć je w locie. Ale musisz zmodyfikować plik XML pliku edmx. Do tego istnieje LINQ do XML lub xpath. Modyfikowanie schematu bazy danych ... w jaki sposób model najpierw buduje dbs ... tworzy sql, a następnie go uruchamia. Będziesz musiał utworzyć sql (jak? Wzruszyć ramionami) i wykonać go (objectcontext.executestorecommand()). Wykonalny? Możliwy? Nie mam pojęcia. Naprawdę odpowiedź brzmi: nie ... nie ma niczego w VS ani .NET 4 (EF API), aby z łatwością to umożliwić, o ile wiem. Z pewnością ktoś bardziej sprytny i cierpliwy niż ja spędziłem (zmarnowałem?) Dużo czasu (próbując) przechytrzyć EF, aby to znieść. Opierając się jednak na Twojej odpowiedzi na sugestię dotyczącą posta na blogu Jeremy'ego, szukasz czegoś wbudowanego/podręcznego. Łatwiej jest odpowiedzieć "nie".

Julie

+7

Witaj w SO, Julie! – Yakimych

+0

Myślę, że może to zrobić kombinacja kodu z 'ExpandoObject'. Ale zamiast reifikacji pól zdefiniowanych przez użytkownika, bardziej sensowne wydaje mi się traktowanie ich jako niestandardowych. +1 do Yakimych; Witamy! –

+0

Zgadzam się, że byłoby to łatwiejsze z pierwszym kodem i bez modelu w ogóle, jedną mniejszą warstwą złożoności i regułami do radzenia sobie z wtih Ale trzeba dużo pracy –

1

Jeremy Miller opisuje podobny zestaw w this article. Używa nHibernate, ale może dać ci kilka pomysłów.

+0

Tak, to daje mi pewne pomysły, z których żadna nie jest prosta. Jestem zaskoczony, że ten wymóg nie jest powszechny w przypadku nHibernate lub EF w tej sprawie. Wszelkie inne zasoby lub pomysły? Tak naprawdę nie odpowiedział na pytanie, pod warunkiem tylko odniesienia, trudno zamknąć pytanie na to. –

+0

Myślałem o tym, ale mój scenariusz oznacza, że ​​muszę zezwolić użytkownikowi na dodanie "pracownika" na pierwszym miejscu przed zdefiniowaniem niestandardowych pól ... w pewnym sensie nawet tabela jest niestandardowa. – War

11

Są to często więcej niż jeden sposób, aby rozwiązać problem, a to nie jest wyjątkiem. W tym przypadku to, czego szukasz, pozwala użytkownikom dodawać nowe pola do aplikacji i bazy danych oraz korzystać z tych pól w aplikacji. Oto kilka sposobów:

a) Pozwól użytkownikom modyfikować schemat bazy danych.
b) Utwórz oddzielną strukturę do definiowania "pól zdefiniowanych przez użytkownika" i przechowywania w nich danych.
c) Tworzenie pustych "zarezerwowanych" pól w tabelach, w których użytkownicy częściej potrzebują własnych pól.

Preferuję podejście (b) i czasami (c), gdy w aplikacji są wymagane niestandardowe pola zdefiniowane przez użytkownika. Oto niektóre plusy minusy/dla każdego z trzech:

Zmienić schemat

Risky: Jeśli pozwalają użytkownikom na modyfikowanie schematu bazy danych, gdzie można narysować linię? Jeśli mogą dodawać pola, mogą również przejść do zmiany definicji istniejących pól, dodawać lub usuwać indeksy itp. Może to prowadzić do koszmaru wsparcia z błędami, problemami z wydajnością itp. Wywołanymi przez modyfikacje schematu wykonywane przez użytkowników.
Performant: przechowywanie nowych zdefiniowanych przez użytkownika pól wstawianych w istniejących tabelach zwykle zapewnia przewagę wydajności nad oddzielną strukturą, ale tylko tak długo, jak długo nie zostaną one przesadzone ze zmianami.
Clunky : EF określa schemat w czasie projektowania, więc aby to działało w czasie wykonywania, będziesz musiał wygenerować nowe klasy encji w czasie wykonywania z elementami reprezentującymi nowe pola, a będziesz musiał zaktualizować metadane odwzorowania na środowisko wykonawcze. Klasa jednostek generowanych przez środowisko wykonawcze może dziedziczyć po klasach generowanych w czasie projektowania, więc wystarczy dodać elementy i odwzorowania dla nowych pól zdefiniowanych przez użytkownika. Chociaż jest to możliwe, jest przyziemne. Kod zużywający klasy generowane przez środowisko wykonawcze będzie musiał użyć odbicia, aby uzyskać dostęp do nowych członków tworzonych w środowisku wykonawczym.

oddzielna struktura

Przyjazny dla użytkownika: Tworząc oddzielną strukturę do przechowywania pól niestandardowych, można zbudować aplikację logiki dla użytkowników do dodawania/usuwania tych pól itd. Oni nie muszą bałagan z bazą danych, zamiast tego możesz mieć formularze konserwacji w aplikacji do dodawania nowych pól.
Przyjazne dla EF: Nie trzeba mieszać z klasami jednostek i mapować metadanych w czasie wykonywania. Wszystko jest zdefiniowane w czasie projektowania, a pola zdefiniowane przez użytkownika to tylko dane.
Nieco mniej wydajne: Posiadanie osobnych tabel do definiowania i przechowywania pól zdefiniowanych przez użytkownika może sprawić, że wyszukiwanie będzie nieco droższe z powodu dodatkowych wizyt w obie strony lub dodatkowych połączeń.

Separate table structure for user defined fields

Reserved pola

dość często: W wielu sytuacjach, pola niestandardowe są wykorzystywane wyłącznie do jednego lub kilku dodatkowych pól. Zarezerwowanie kilku kolumn często pokrywa 99% potrzeb użytkowników. Nawet ogólne pole "uwagi" w każdej tabeli często wystarcza w aplikacjach LOB.
Ograniczenia: Ograniczenia:
Jeśli użytkownicy chcą więcej pól, niż zarezerwowali, lub innych typów danych, niż zarezerwowali, może to stanowić ograniczenie.
Performant: Kolumny wbudowane, odzyskane bez dodatkowych zwrotów lub złączeń.
Zdefiniowane w czasie projektowania: Brak środowiska wykonawczego zakłócającego definicje lub odwzorowania typów jednostek.

Reserved fields

2

Brent ping me on Twitter dzisiaj (prawie 2 lata po tym poście), aby sprawdzić, czy coś się zmieniło. Ten scenariusz nadal nie jest wspierany przez EF. Jednak Rowan Miller ma interesujący post jak to zrobić za pomocą Code First: http://romiller.com/2012/03/26/dynamically-building-a-model-with-code-first/

To może, ale nie musi, zrobić to, czego potrzebujesz, ale warto rzucić okiem.

0

To jest wersja Reserved fields z @KristoferA Odpowiedź, której używałem w przeszłości.

Możesz dodać jedną dodatkową kolumnę XML (lub JSON) na każdej tabeli, która prawdopodobnie będzie wymagać danych niestandardowych, a następnie odczytać/zapisać ją z db przy użyciu EF.Po przeczytaniu deserializacji XML (JSON) i przekazaniu jej do mechanizmu, który ma obsłużyć odwzorowania, przedstaw go użytkownikowi. To samo dotyczy zapisywania danych, które czytasz z interfejsu użytkownika -> mapuj do obiektu -> serializuj do XML (JSON) -> i napisz do tych dodatkowych pól.