Saya mencoba menggunakan fitur Multimapping necis untuk mengembalikan daftar ProductItems dan Pelanggan terkait.
[Table("Product")]
public class ProductItem
{
public decimal ProductID { get; set; }
public string ProductName { get; set; }
public string AccountOpened { get; set; }
public Customer Customer { get; set; }
}
public class Customer
{
public decimal CustomerId { get; set; }
public string CustomerName { get; set; }
}
Kode necis saya adalah sebagai berikut
var sql = @"select * from Product p
inner join Customer c on p.CustomerId = c.CustomerId
order by p.ProductName";
var data = con.Query<ProductItem, Customer, ProductItem>(
sql,
(productItem, customer) => {
productItem.Customer = customer;
return productItem;
},
splitOn: "CustomerId,CustomerName"
);
Ini berfungsi dengan baik tetapi saya tampaknya harus menambahkan daftar kolom lengkap ke parameter splitOn untuk mengembalikan semua properti pelanggan. Jika saya tidak menambahkan "CustomerName" itu mengembalikan null. Apakah saya salah memahami fungsi inti dari fitur multimapping. Saya tidak ingin setiap kali menambahkan daftar lengkap nama kolom.
Jawaban:
Saya baru saja menjalankan tes yang berfungsi dengan baik:
Parameter splitOn perlu ditentukan sebagai titik pemisah, defaultnya adalah Id. Jika ada beberapa titik pemisah, Anda perlu menambahkannya dalam daftar yang dipisahkan koma.
Katakanlah kumpulan data Anda terlihat seperti ini:
Dapper perlu mengetahui cara membagi kolom dalam urutan ini menjadi 2 objek. Pandangan sepintas menunjukkan bahwa Pelanggan mulai di kolom
CustomerId
, karenanyasplitOn: CustomerId
.Ada peringatan besar di sini, jika urutan kolom dalam tabel yang mendasarinya dibalik karena suatu alasan:
splitOn: CustomerId
akan menghasilkan nama pelanggan nol.Jika Anda menentukan
CustomerId,CustomerName
sebagai titik pemisah, necis berasumsi Anda mencoba untuk membagi hasil set menjadi 3 objek. Pertama dimulai dari awal, kedua dimulai padaCustomerId
, ketiga padaCustomerName
.sumber
spliton
, yaituCustomerId,CustomerName
tidakCustomerId, CustomerName
, karena Dapper tidak melakukanTrim
pemisahan string. Ini hanya akan membuang kesalahan pemisahan umum. Membuatku gila suatu hari nanti.Tabel kami diberi nama yang mirip dengan Anda, di mana sesuatu seperti "ID Pelanggan" mungkin ditampilkan dua kali menggunakan operasi 'pilih *'. Oleh karena itu, Dapper melakukan tugasnya tetapi memisahkan terlalu dini (mungkin), karena kolomnya adalah:
Hal ini membuat parameter spliton: tidak begitu berguna, terutama ketika Anda tidak yakin dengan urutan apa kolom dikembalikan. Tentu saja Anda dapat menentukan kolom secara manual ... tapi ini tahun 2017 dan kami jarang melakukannya lagi untuk objek dasar.
Apa yang kami lakukan, dan berfungsi dengan baik untuk ribuan kueri selama bertahun-tahun, hanyalah menggunakan alias untuk Id, dan tidak pernah menentukan pemisahan (menggunakan 'Id' default Dapper).
... voila! Dapper hanya akan membagi Id secara default, dan Id itu muncul sebelum semua kolom Pelanggan. Tentu saja ini akan menambahkan kolom ekstra ke kumpulan hasil pengembalian Anda, tetapi itu adalah biaya overhead yang sangat minimal untuk utilitas tambahan untuk mengetahui dengan tepat kolom mana yang termasuk dalam objek apa. Dan Anda dapat dengan mudah mengembangkannya. Butuh alamat dan informasi negara?
Yang terbaik dari semuanya, Anda dengan jelas menunjukkan dalam jumlah minimal sql kolom mana yang terkait dengan objek mana. Dapper melakukan sisanya.
sumber
Dengan asumsi struktur berikut di mana '|' adalah titik pemisahan dan Ts adalah entitas tempat pemetaan harus diterapkan.
Berikut ini adalah kueri rapi yang harus Anda tulis.
Jadi kami ingin TF pertama memetakan col_1 col_2 col_3, untuk TSkedua col_n col_m ...
Ekspresi splitOn diterjemahkan menjadi:
Mulailah memetakan semua kolom ke dalam TFrist sampai Anda menemukan kolom bernama atau alias 'col_3', dan juga memasukkan 'col_3' ke dalam hasil pemetaan.
Kemudian mulai memetakan ke dalam TSkedua semua kolom mulai dari 'col_n' dan lanjutkan pemetaan sampai pemisah baru ditemukan, yang dalam hal ini adalah 'col_A' dan menandai dimulainya pemetaan ketiga dan seterusnya.
Kolom dari query sql dan props dari objek pemetaan berada dalam relasi 1: 1 (artinya harus diberi nama yang sama), jika nama kolom yang dihasilkan dari query sql berbeda Anda dapat membuat alias menggunakan 'AS [ Some_Alias_Name] '.
sumber
Ada satu peringatan lagi. Jika field CustomerId adalah null (biasanya dalam query dengan left join) Dapper membuat ProductItem dengan Customer = null. Pada contoh di atas:
Dan bahkan satu peringatan / jebakan lagi. Jika Anda tidak memetakan bidang yang ditentukan dalam splitOn dan bidang itu berisi null, Dapper akan membuat dan mengisi objek terkait (Pelanggan dalam hal ini). Untuk mendemonstrasikan gunakan kelas ini dengan sql sebelumnya:
sumber
Saya melakukan ini secara umum di repo saya, berfungsi dengan baik untuk kasus penggunaan saya. Saya pikir saya akan berbagi. Mungkin seseorang akan memperpanjang ini lebih jauh.
Beberapa kekurangannya adalah:
Kode:
sumber
Jika Anda perlu memetakan entitas besar, menulis setiap bidang pasti menjadi tugas yang sulit.
Saya mencoba jawaban @BlackjacketMack, tetapi salah satu tabel saya memiliki Kolom Id yang lain tidak (saya tahu ini masalah desain DB, tapi ...) lalu ini menyisipkan perpecahan ekstra pada necis, itu sebabnya
Tidak berhasil untuk saya. Kemudian saya akhiri dengan sedikit perubahan, cukup masukkan titik terpisah dengan nama yang tidak sesuai dengan bidang apa pun pada tabel, Jika mungkin diubah
as Id
olehas _SplitPoint_
, skrip sql terakhir terlihat seperti ini:Kemudian di necis tambahkan hanya satu splitOn seperti ini
sumber