Wypróbuj moje rozwiązanie . Zapobiega generowaniu migracji dla tabel oznaczonych jako widoki
kogoia
Odpowiedzi:
95
Jeśli tak jak ja interesuje Cię tylko mapowanie encji pochodzącej z innej bazy danych (w moim przypadku ERP), aby powiązać je z encjami specyficznymi dla Twojej aplikacji, możesz korzystać z widoków tak, jak korzystasz z tabeli (mapuj widok w w ten sam sposób!). Oczywiście, jeśli spróbujesz zaktualizować te encje, otrzymasz wyjątek, jeśli widoku nie można zaktualizować. Procedura jest taka sama jak w przypadku normalnych (opartych na tabeli) podmiotów:
Utwórz klasę POCO dla widoku; na przykład FooView
Dodaj właściwość DbSet do klasy DbContext
Użyj pliku FooViewConfiguration, aby ustawić inną nazwę widoku (za pomocą ToTable („Foo”); w konstruktorze) lub ustawić określone właściwości
+1 za nie zakładanie, że „Code First” == automatyczne generowanie bazy danych
onetwopunch
3
@DaveJellison, czy zechciałbyś to rozwinąć lub podać link do dodawania widoku w ramach IDatabaseInitializer
Ralph Shillington
18
Czy to tylko ja, czy wszyscy otrzymują pustą tabelę utworzoną przez migrację? Czy jest sposób, aby tego uniknąć?
Kremena Lalova
4
Tylko upewniając się tutaj, czy to rozwiązanie wymagało od nas wcześniejszego zewnętrznego utworzenia widoku w bazie danych SQL? Czy można zdefiniować widok w kodzie i zapełnić go w bazie danych za pomocą polecenia Add-Migration / Update-Database?
frostshoxx
6
Kilka rzeczy. 1. W tej odpowiedzi nie ma wzmianki o konieczności ręcznego utworzenia widoku za pomocą SQL, można to zrobić za pomocą migracji. 2. Nie musisz konfigurować nazwy widoku, jeśli nazwa klasy jest zgodna z nazwą widoku. 3. Możesz używać adnotacji danych w następujący sposób: [Table("myView")]jest to prawdopodobnie prostsze niż tworzenie pliku EntityTypeConfiguration.
Rudey
23
Może to być aktualizacja, ale aby użyć widoków z kodem EF, najpierw dodaj [Table ("NameOfView")] na początku klasy i wszystko powinno działać poprawnie bez konieczności przechodzenia przez wszystkie obręcze, przez które przechodzą wszyscy inni. Będziesz także musiał zgłosić jedną z kolumn jako kolumnę [klucz]. Oto mój przykładowy kod poniżej, aby go zaimplementować.
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespaceSomeProject.Data
{
[Table("SomeView")]
publicclassSomeView
{
[Key]
publicint NameID { get; set; }
publicstring Name { get; set; }
}
}
A oto jak wygląda kontekst
using System.Data.Entity;
namespaceSomeProject.Data
{
publicclassDatabaseContext : DbContext
{
public DbSet<SomeView> SomeViews { get; set; }
}
}
Jest to to samo, co zaakceptowana odpowiedź, z tą różnicą, że używa DataAnnotations, podczas gdy zaakceptowana odpowiedź używa interfejsu API EF Fluid.
Rudey
4
Właściwie nie, nie jest. Bez powodzenia spróbowałem zaakceptowanej odpowiedzi i nie wyszło mi to dobrze. Ale potem używam migracji, więc może to mieć wpływ na rzeczy. Okazało się, że najpierw muszę wykonać migracje, a NASTĘPNIE dodać moją klasę widoku, ponieważ już istniała w bazie danych. Zrobilibyśmy to dokładnie w ten sam sposób, gdybyśmy mieli już istniejące tabele w bazie danych. Ponieważ widok jest „wirtualną tabelą”, składnia tabeli w Entity Framework nadal działa.
Charles Owen,
11
Jeśli wszystko, czego chcesz, to zbiór zdenormalizowanych obiektów, możesz po prostu utworzyć publiczną IQueryable<TDenormolized>właściwość tylko do pobierania w swojej DbContextklasie.
W getzwracasz wynik Linq, aby rzutować zdenormalizowane wartości na zdenormalizowane obiekty. To może być lepsze niż pisanie DB View, ponieważ programujesz, nie jesteś ograniczony tylko do używania selectinstrukcji. Jest również bezpieczny w czasie kompilacji.
Po prostu uważaj, aby nie wywoływać wyliczeń, takich jak ToList()wywołania, które spowodują przerwanie odroczonego zapytania i możesz skończyć z odzyskaniem miliona rekordów z bazy danych i przefiltrowaniem ich na serwerze aplikacji.
Nie wiem, czy to właściwy sposób, ale próbowałem i to działa.
Jednym z powodów, dla których chciałbym używać widoków, jest to, że kod SQL generowany przez EF nie zawsze jest `` ładny '' - w naszym modelu mamy pewne hierarchie dziedziczenia (o pułapkach dowiedzieliśmy się zbyt późno ...), a użycie widoków pozwala nam aby ręcznie utworzyć SQL. Tylko kontrapunkt, dlaczego widok byłby lepszy
Carl
2
Innym powodem, aby tego nie robić, może być użycie rekurencyjnych wspólnych wyrażeń tabelowych, które nie są dostępne w LINQ. Ale poza tym jest to dobra rada dla prostszych scenariuszy.
Tom Pažourek
1
Używanie właściwości zamiast widoku nie jest opcją, jeśli chcesz skorzystać z zalet widoku indeksowanego .
Rudey
„nie ogranicza Cię używanie wyłącznie instrukcji select”. Co przez to rozumiesz? Wszystko, co możesz zrobić z LINQ, można zrobić za pomocą instrukcji SELECT, tego samego nie można powiedzieć na odwrót.
Rudey
3
Wiem, że to stare pytanie i jest tu wiele odpowiedzi, ale wymusiłem problem, gdy używam tej odpowiedzi i wystąpił błąd, gdy używam polecenia update-database w konsoli menedżera pakietów:
W bazie danych istnieje już obiekt o nazwie „...”.
i wykonuję następujące kroki, aby rozwiązać ten problem:
uruchom to polecenie w konsoli Menedżera pakietów: Początek migracji do dodania
W folderze Migrations możesz znaleźć plik ..._ intial.cs, otworzyć go i skomentować lub usunąć dowolne polecenie związane z klasą, którą chcesz zmapować
teraz możesz normalnie użyć polecenia update-database do wszelkich innych zmian w swoich modelach
Dzięki! To naprawdę pomogło! Dodatkowo, zamiast po prostu usuwać kod wygenerowany za pomocą migracji EF, możesz zamiast tego dodać migrationBuilder.Sql("CREATE OR REPLACE VIEW ...); Aby współpracownicy mogli również użyć go do aktualizacji swojej bazy danych.
Odpowiedzi:
Jeśli tak jak ja interesuje Cię tylko mapowanie encji pochodzącej z innej bazy danych (w moim przypadku ERP), aby powiązać je z encjami specyficznymi dla Twojej aplikacji, możesz korzystać z widoków tak, jak korzystasz z tabeli (mapuj widok w w ten sam sposób!). Oczywiście, jeśli spróbujesz zaktualizować te encje, otrzymasz wyjątek, jeśli widoku nie można zaktualizować. Procedura jest taka sama jak w przypadku normalnych (opartych na tabeli) podmiotów:
Użyj pliku FooViewConfiguration, aby ustawić inną nazwę widoku (za pomocą ToTable („Foo”); w konstruktorze) lub ustawić określone właściwości
public class FooViewConfiguration : EntityTypeConfiguration<FooView> { public FooViewConfiguration() { this.HasKey(t => t.Id); this.ToTable("myView"); } }
Dodaj plik FooViewConfiguration do modelBuilder, na przykład zastępując metodę OnModelCreating metody Context:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new FooViewConfiguration ()); }
źródło
[Table("myView")]
jest to prawdopodobnie prostsze niż tworzenie plikuEntityTypeConfiguration
.Może to być aktualizacja, ale aby użyć widoków z kodem EF, najpierw dodaj [Table ("NameOfView")] na początku klasy i wszystko powinno działać poprawnie bez konieczności przechodzenia przez wszystkie obręcze, przez które przechodzą wszyscy inni. Będziesz także musiał zgłosić jedną z kolumn jako kolumnę [klucz]. Oto mój przykładowy kod poniżej, aby go zaimplementować.
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema; namespace SomeProject.Data { [Table("SomeView")] public class SomeView { [Key] public int NameID { get; set; } public string Name { get; set; } } }
A oto jak wygląda kontekst
using System.Data.Entity; namespace SomeProject.Data { public class DatabaseContext : DbContext { public DbSet<SomeView> SomeViews { get; set; } } }
źródło
Jeśli wszystko, czego chcesz, to zbiór zdenormalizowanych obiektów, możesz po prostu utworzyć publiczną
IQueryable<TDenormolized>
właściwość tylko do pobierania w swojejDbContext
klasie.W
get
zwracasz wynik Linq, aby rzutować zdenormalizowane wartości na zdenormalizowane obiekty. To może być lepsze niż pisanie DB View, ponieważ programujesz, nie jesteś ograniczony tylko do używaniaselect
instrukcji. Jest również bezpieczny w czasie kompilacji.Po prostu uważaj, aby nie wywoływać wyliczeń, takich jak
ToList()
wywołania, które spowodują przerwanie odroczonego zapytania i możesz skończyć z odzyskaniem miliona rekordów z bazy danych i przefiltrowaniem ich na serwerze aplikacji.Nie wiem, czy to właściwy sposób, ale próbowałem i to działa.
źródło
Wiem, że to stare pytanie i jest tu wiele odpowiedzi, ale wymusiłem problem, gdy używam tej odpowiedzi i wystąpił błąd, gdy używam polecenia update-database w konsoli menedżera pakietów:
i wykonuję następujące kroki, aby rozwiązać ten problem:
mam nadzieję, że to pomoże.
źródło
migrationBuilder.Sql("CREATE OR REPLACE VIEW ...
); Aby współpracownicy mogli również użyć go do aktualizacji swojej bazy danych.