Coba solusi saya . Ini mencegah pembuatan migrasi untuk tabel yang ditandai sebagai tampilan
kogoia
Jawaban:
95
Jika, seperti saya, Anda hanya tertarik dalam memetakan entitas yang berasal dari database lain (dalam kasus saya erp) untuk menghubungkannya dengan entitas khusus aplikasi Anda, maka Anda dapat menggunakan tampilan saat menggunakan tabel (memetakan tampilan di cara yang sama!). Jelas, jika Anda mencoba memperbarui entitas itu, Anda akan mendapatkan pengecualian jika tampilan tidak dapat diperbarui. Prosedurnya sama seperti dalam kasus entitas normal (berdasarkan tabel):
Buat kelas POCO untuk tampilan; misalnya FooView
Tambahkan properti DbSet di kelas DbContext
Gunakan file FooViewConfiguration untuk menyetel nama yang berbeda untuk tampilan (menggunakan ToTable ("Foo"); di konstruktor) atau untuk menyetel properti tertentu
+1 untuk tidak berasumsi bahwa "Code First" == pembuatan database otomatis
onetwopunch
3
@DaveJellison maukah Anda menjelaskannya, atau memberikan tautan tentang menambahkan tampilan sebagai bagian dari IDatabaseInitializer
Ralph Shillington
19
Apakah hanya saya, atau semua orang mendapatkan tabel kosong yang dibuat oleh migrasi? Apakah ada cara untuk menghindarinya?
Kremena Lalova
4
Hanya memastikan di sini, apakah solusi ini mengharuskan kami membuat View di database SQL sebelumnya secara eksternal? Apakah mungkin untuk menentukan tampilan dalam kode dan mengisinya dalam database melalui perintah Add-Migration / Update-Database?
frostshoxx
6
Beberapa hal. 1. Jawaban ini gagal menyebutkan Anda harus membuat tampilan secara manual menggunakan SQL, ini dapat dilakukan dengan menggunakan migrasi. 2. Anda tidak perlu mengkonfigurasi nama tampilan jika nama kelas cocok dengan nama tampilan. 3. Anda dapat menggunakan DataAnnotations seperti:, [Table("myView")]ini bisa dibilang lebih sederhana daripada menggunakan membuat file EntityTypeConfiguration.
Rudey
23
Ini mungkin pembaruan tetapi untuk menggunakan tampilan dengan Kode EF pertama cukup tambahkan [Tabel ("NameOfView")] ke bagian atas kelas dan semua harus bekerja dengan benar tanpa harus melalui semua rintangan yang orang lain lalui. Anda juga harus melaporkan salah satu kolom sebagai kolom [key]. Berikut adalah contoh kode saya di bawah ini untuk menerapkannya.
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespaceSomeProject.Data
{
[Table("SomeView")]
publicclassSomeView
{
[Key]
publicint NameID { get; set; }
publicstring Name { get; set; }
}
}
Dan seperti inilah konteksnya
using System.Data.Entity;
namespaceSomeProject.Data
{
publicclassDatabaseContext : DbContext
{
public DbSet<SomeView> SomeViews { get; set; }
}
}
Ini sama dengan jawaban yang diterima, kecuali ini menggunakan DataAnnotations sedangkan jawaban yang diterima menggunakan EF Fluid API.
Rudey
4
Sebenarnya tidak. Saya mencoba, tanpa hasil, pada jawaban yang diterima dan itu tidak berhasil untuk saya. Tapi kemudian saya menggunakan Migrasi jadi ini mungkin memengaruhi banyak hal. Saya menemukan saya harus melakukan migrasi saya terlebih dahulu KEMUDIAN tambahkan kelas tampilan saya karena sudah ada di database. Kami akan menanganinya dengan cara yang persis sama jika kami sudah memiliki tabel yang ada di database. Karena tampilan adalah "tabel virtual", sintaks tabel di Entity Framework masih berfungsi.
Charles Owen
12
Jika yang Anda inginkan hanyalah sekumpulan objek yang tidak dinormalisasi, Anda mungkin saja membuat IQueryable<TDenormolized>properti hanya-get publik di DbContextkelas Anda .
Dalam getAnda mengembalikan hasil Linq untuk memproyeksikan nilai de-normoalisasi ke dalam objek yang dinormalisasi. Ini mungkin lebih baik daripada menulis Tampilan DB karena Anda memprogram, Anda tidak dibatasi hanya dengan menggunakan selectpernyataan. Juga kompilasi tipe waktu aman.
Berhati-hatilah agar tidak memicu enumerasi seperti ToList()panggilan, yang akan merusak kueri yang ditangguhkan dan Anda mungkin akan mendapatkan satu juta catatan kembali dari database dan memfilternya di server aplikasi Anda.
Saya tidak tahu apakah ini cara yang benar, tetapi saya mencoba dan berhasil untuk saya.
Salah satu alasan saya ingin menggunakan tampilan adalah karena SQL yang dihasilkan oleh EF tidak selalu 'bagus' - kami memiliki beberapa hierarki pewarisan dalam model kami (terlambat mengetahui tentang jebakan ...) dan menggunakan tampilan memungkinkan kami untuk membuat SQL secara manual. Sekadar tandingan tentang mengapa pemandangan lebih disukai
Carl
2
Alasan lain untuk tidak melakukan ini mungkin karena penggunaan ekspresi tabel umum rekursif, yang tidak tersedia di LINQ. Tetapi sebaliknya, ini adalah saran yang bagus untuk skenario yang lebih sederhana.
Tom Pažourek
1
Menggunakan properti dan bukan tampilan bukanlah pilihan jika Anda ingin memanfaatkan manfaat tampilan yang diindeks .
Rudey
"Anda tidak dibatasi hanya dengan menggunakan pernyataan pilih". Apa yang Anda maksud dengan ini? Apa pun yang Anda lakukan dengan LINQ dapat dilakukan menggunakan pernyataan SELECT, hal yang sama tidak dapat dikatakan sebaliknya.
Rudey
3
Saya tahu ini adalah pertanyaan lama dan ada banyak jawaban di sini, tetapi saya memaksakan masalah ketika saya menggunakan jawaban ini dan kesalahan terjadi ketika saya menggunakan perintah update-database di Package Manager Console:
Sudah ada objek bernama '...' di database.
dan saya menggunakan langkah-langkah ini untuk mengatasi masalah ini:
jalankan perintah ini di Package Manager Console: Tambahkan-migrasi awal
Di bawah folder Migrasi, Anda dapat menemukan file ..._ intial.cs, membukanya dan memberi komentar atau menghapus perintah apa pun yang terkait dengan kelas Anda yang ingin Anda petakan
sekarang Anda biasanya dapat menggunakan perintah update-database untuk setiap perubahan lain pada model Anda
Terima kasih! Ini sangat membantu! Sebagai tambahan, alih-alih hanya menghapus kode yang dihasilkan dengan Migrasi EF, Anda dapat menambahkannya di sana migrationBuilder.Sql("CREATE OR REPLACE VIEW ...); Sehingga rekan kerja juga bisa menggunakannya untuk mengupgrade database mereka.
Jawaban:
Jika, seperti saya, Anda hanya tertarik dalam memetakan entitas yang berasal dari database lain (dalam kasus saya erp) untuk menghubungkannya dengan entitas khusus aplikasi Anda, maka Anda dapat menggunakan tampilan saat menggunakan tabel (memetakan tampilan di cara yang sama!). Jelas, jika Anda mencoba memperbarui entitas itu, Anda akan mendapatkan pengecualian jika tampilan tidak dapat diperbarui. Prosedurnya sama seperti dalam kasus entitas normal (berdasarkan tabel):
Gunakan file FooViewConfiguration untuk menyetel nama yang berbeda untuk tampilan (menggunakan ToTable ("Foo"); di konstruktor) atau untuk menyetel properti tertentu
public class FooViewConfiguration : EntityTypeConfiguration<FooView> { public FooViewConfiguration() { this.HasKey(t => t.Id); this.ToTable("myView"); } }
Tambahkan file FooViewConfiguration ke modelBuilder, misalnya ovveriding metode OnModelCreating dari Konteks:
protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Configurations.Add(new FooViewConfiguration ()); }
sumber
[Table("myView")]
ini bisa dibilang lebih sederhana daripada menggunakan membuat fileEntityTypeConfiguration
.Ini mungkin pembaruan tetapi untuk menggunakan tampilan dengan Kode EF pertama cukup tambahkan [Tabel ("NameOfView")] ke bagian atas kelas dan semua harus bekerja dengan benar tanpa harus melalui semua rintangan yang orang lain lalui. Anda juga harus melaporkan salah satu kolom sebagai kolom [key]. Berikut adalah contoh kode saya di bawah ini untuk menerapkannya.
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; } } }
Dan seperti inilah konteksnya
using System.Data.Entity; namespace SomeProject.Data { public class DatabaseContext : DbContext { public DbSet<SomeView> SomeViews { get; set; } } }
sumber
Jika yang Anda inginkan hanyalah sekumpulan objek yang tidak dinormalisasi, Anda mungkin saja membuat
IQueryable<TDenormolized>
properti hanya-get publik diDbContext
kelas Anda .Dalam
get
Anda mengembalikan hasil Linq untuk memproyeksikan nilai de-normoalisasi ke dalam objek yang dinormalisasi. Ini mungkin lebih baik daripada menulis Tampilan DB karena Anda memprogram, Anda tidak dibatasi hanya dengan menggunakanselect
pernyataan. Juga kompilasi tipe waktu aman.Berhati-hatilah agar tidak memicu enumerasi seperti
ToList()
panggilan, yang akan merusak kueri yang ditangguhkan dan Anda mungkin akan mendapatkan satu juta catatan kembali dari database dan memfilternya di server aplikasi Anda.Saya tidak tahu apakah ini cara yang benar, tetapi saya mencoba dan berhasil untuk saya.
sumber
Saya tahu ini adalah pertanyaan lama dan ada banyak jawaban di sini, tetapi saya memaksakan masalah ketika saya menggunakan jawaban ini dan kesalahan terjadi ketika saya menggunakan perintah update-database di Package Manager Console:
dan saya menggunakan langkah-langkah ini untuk mengatasi masalah ini:
semoga membantu.
sumber
migrationBuilder.Sql("CREATE OR REPLACE VIEW ...
); Sehingga rekan kerja juga bisa menggunakannya untuk mengupgrade database mereka.