Menggunakan contoh sederhana di bawah ini, apa cara terbaik untuk mengembalikan hasil dari beberapa tabel menggunakan Linq ke SQL?
Katakanlah saya punya dua tabel:
Dogs: Name, Age, BreedId
Breeds: BreedId, BreedName
Saya ingin mengembalikan semua anjing dengan mereka BreedName
. Saya harus membuat semua anjing menggunakan sesuatu seperti ini tanpa masalah:
public IQueryable<Dog> GetDogs()
{
var db = new DogDataContext(ConnectString);
var result = from d in db.Dogs
join b in db.Breeds on d.BreedId equals b.BreedId
select d;
return result;
}
Tetapi jika saya ingin anjing ras dan coba ini, saya punya masalah:
public IQueryable<Dog> GetDogsWithBreedNames()
{
var db = new DogDataContext(ConnectString);
var result = from d in db.Dogs
join b in db.Breeds on d.BreedId equals b.BreedId
select new
{
Name = d.Name,
BreedName = b.BreedName
};
return result;
}
Sekarang saya menyadari bahwa kompiler tidak akan membiarkan saya mengembalikan satu set jenis anonim karena itu mengharapkan Anjing, tetapi apakah ada cara untuk mengembalikan ini tanpa harus membuat jenis kustom? Atau apakah saya harus membuat kelas sendiri untuk DogsWithBreedNames
dan menentukan jenis itu di pilih? Atau ada cara lain yang lebih mudah?
c#
linq
linq-to-sql
Jonathan S.
sumber
sumber
foreach (var cust in query) Console.WriteLine("id = {0}, City = {1}", cust.CustomerID, cust.City);
Jawaban:
Saya cenderung memilih pola ini:
Ini berarti Anda memiliki kelas tambahan, tetapi cepat dan mudah dikodekan, mudah diperluas, dapat digunakan kembali, dan tipe-aman.
sumber
Anda dapat mengembalikan jenis anonim, tetapi sebenarnya tidak cantik .
Dalam hal ini saya pikir akan jauh lebih baik untuk membuat tipe yang sesuai. Jika itu hanya akan digunakan dari dalam tipe yang berisi metode, buat itu menjadi tipe bersarang.
Secara pribadi saya ingin C # untuk mendapatkan "nama jenis anonim" - yaitu perilaku yang sama dengan jenis anonim, tetapi dengan nama dan deklarasi properti, tetapi hanya itu.
SUNTING: Yang lain menyarankan anjing yang kembali, dan kemudian mengakses nama trah melalui jalur properti dll. Itu pendekatan yang sangat masuk akal, tetapi IME itu mengarah ke situasi di mana Anda telah melakukan kueri dengan cara tertentu karena data yang ingin Anda gunakan - dan meta-informasi itu hilang ketika Anda baru saja kembali
IEnumerable<Dog>
- kueri mungkin mengharapkan Anda untuk menggunakan (katakanlah)Breed
daripadaOwner
karena beberapa opsi muat dll, tetapi jika Anda lupa itu dan mulai menggunakan properti lain, aplikasi Anda mungkin berfungsi tetapi tidak seefisien yang Anda bayangkan. Tentu saja, saya dapat berbicara tentang sampah, atau terlalu mengoptimalkan, dll ...sumber
Hanya untuk menambah nilai dua sen saya :-) Baru-baru ini saya belajar cara menangani objek anonim. Ini hanya dapat digunakan ketika menargetkan kerangka .NET 4 dan itu hanya ketika menambahkan referensi ke System.Web.dll tetapi kemudian cukup sederhana:
Untuk dapat menambahkan referensi ke System.Web.dll Anda harus mengikuti saran rushonerok : Pastikan kerangka kerja target [proyek] Anda adalah ".NET Framework 4" bukan ".NET Framework 4 Profil Klien".
sumber
Tidak, Anda tidak dapat mengembalikan jenis anonim tanpa melalui beberapa tipu daya.
Jika Anda tidak menggunakan C #, apa yang akan Anda cari (mengembalikan beberapa data tanpa tipe konkret) disebut Tuple.
Ada banyak implementasi tuple C #, menggunakan yang ditunjukkan di sini , kode Anda akan berfungsi seperti ini.
Dan di situs panggilan:
sumber
... select Tuple.Create(d, b)
.Anda dapat melakukan sesuatu seperti ini:
sumber
Anda harus menggunakan
ToList()
metode terlebih dahulu untuk mengambil baris dari database dan kemudian memilih item sebagai kelas. Coba ini:Jadi, triknya adalah yang pertama
ToList()
. Segera membuat permintaan dan mendapatkan data dari database. Trik kedua adalah Memilih item dan menggunakan penginisialisasi objek untuk menghasilkan objek baru dengan item dimuat.Semoga ini membantu.
sumber
Di C # 7 sekarang Anda dapat menggunakan tuple! ... yang menghilangkan kebutuhan untuk membuat kelas hanya untuk mengembalikan hasilnya.
Berikut ini contoh kode:
Anda mungkin perlu menginstal paket nuget System.ValueTuple.
sumber
Sekarang saya menyadari bahwa kompiler tidak akan membiarkan saya mengembalikan satu set jenis anonim karena itu mengharapkan Anjing, tetapi apakah ada cara untuk mengembalikan ini tanpa harus membuat jenis kustom?
Gunakan objek gunakan untuk mengembalikan daftar jenis Anonim tanpa membuat jenis kustom. Ini akan berfungsi tanpa kesalahan kompiler (dalam .net 4.0). Saya mengembalikan daftar ke klien dan menguraikannya di JavaScript:
sumber
Cukup pilih anjing, lalu gunakan
dog.Breed.BreedName
, ini akan bekerja dengan baik.Jika Anda memiliki banyak anjing, gunakan DataLoadOptions.LoadWith untuk mengurangi jumlah panggilan db.
sumber
Anda tidak dapat mengembalikan tipe anonim secara langsung, tetapi Anda dapat memutarnya melalui metode generik Anda. Begitu juga sebagian besar metode ekstensi LINQ. Tidak ada sihir di sana, sementara sepertinya mereka akan mengembalikan jenis anonim. Jika parameter anonim, hasilnya juga bisa anonim.
Di bawah ini adalah contoh berdasarkan kode dari pertanyaan asli:
sumber
Nah, jika Anda mengembalikan Anjing, Anda akan melakukannya:
Jika Anda ingin Breed bersemangat dan tidak malas, cukup gunakan konstruksi DataLoadOptions yang sesuai .
sumber
BreedId
dalamDog
tabel jelas merupakan kunci asing ke baris yang sesuai dalamBreed
tabel. Jika database Anda sudah diatur dengan benar, LINQ ke SQL akan secara otomatis membuat hubungan antara dua tabel. Kelas Dog yang dihasilkan akan memiliki properti Breed, dan kelas Breed harus memiliki koleksi Anjing. Menyetelnya dengan cara ini, Anda masih bisa kembaliIEnumerable<Dog>
, yang merupakan objek yang menyertakan properti berkembang biak. Satu-satunya peringatan adalah bahwa Anda perlu memuat objek berkembang biak bersama dengan objek anjing di kueri sehingga mereka dapat diakses setelah konteks data telah dibuang, dan (seperti yang disarankan poster lain) jalankan metode pada koleksi yang akan menyebabkan permintaan yang harus segera dilakukan (ToArray dalam kasus ini):Maka sepele untuk mengakses jenis untuk setiap anjing:
sumber
Jika ide utamanya adalah membuat pernyataan pilih SQL yang dikirim ke server Database hanya memiliki bidang yang diperlukan, dan tidak semua bidang Entitas, maka Anda dapat melakukan ini:
sumber
Coba ini untuk mendapatkan data dinamis. Anda dapat mengonversi kode untuk Daftar <>
sumber
Jika Anda memiliki pengaturan hubungan di basis data Anda dengan pengekangan kunci asing di BreedId, apakah Anda belum mendapatkannya?
Jadi sekarang saya dapat menelepon:
Dan dalam kode yang memanggil itu:
Jadi, dalam contoh Anda, Anda akan memanggil sesuatu seperti anjing.
Seperti yang disebutkan orang lain, DataLoadOptions akan membantu mengurangi panggilan database jika itu masalah.
sumber
Ini tidak persis menjawab pertanyaan Anda, tetapi Google membawa saya ke sini berdasarkan kata kunci. Ini adalah bagaimana Anda dapat meminta jenis anonim dari daftar:
sumber