Saya mencoba melakukan Gabung antara beberapa tabel di LINQ. Saya memiliki kelas-kelas berikut:
Product {Id, ProdName, ProdQty}
Category {Id, CatName}
ProductCategory{ProdId, CatId} //association table
Dan saya menggunakan kode berikut (di mana product
, category
dan productcategory
adalah contoh dari kelas di atas):
var query = product.Join(productcategory, p => p.Id, pc => pc.ProdID, (p, pc) => new {product = p, productcategory = pc})
.Join(category, ppc => ppc.productcategory.CatId, c => c.Id, (ppc, c) => new { productproductcategory = ppc, category = c});
Dengan kode ini saya memperoleh objek dari kelas berikut:
QueryClass { productproductcategory, category}
Di mana kategori produkproduk berjenis:
ProductProductCategoryClass {product, productcategory}
Saya tidak mengerti di mana "tabel" yang tergabung, saya mengharapkan satu kelas yang berisi semua properti dari kelas yang terlibat.
Tujuan saya adalah mengisi objek lain dengan beberapa properti yang dihasilkan dari kueri:
CategorizedProducts catProducts = query.Select(m => new { m.ProdId = ???, m.CatId = ???, //other assignments });
bagaimana saya bisa mencapai tujuan ini?
Jawaban:
Untuk gabungan, saya sangat menyukai sintaks kueri untuk semua detail yang dengan senang hati disembunyikan (tidak sedikit di antaranya adalah pengenal transparan yang terlibat dengan proyeksi perantara di sepanjang jalan yang terlihat dalam padanan sintaks titik). Namun, Anda bertanya tentang Lambdas yang menurut saya Anda memiliki semua yang Anda butuhkan - Anda hanya perlu menggabungkan semuanya.
var categorizedProducts = product .Join(productcategory, p => p.Id, pc => pc.ProdId, (p, pc) => new { p, pc }) .Join(category, ppc => ppc.pc.CatId, c => c.Id, (ppc, c) => new { ppc, c }) .Select(m => new { ProdId = m.ppc.p.Id, // or m.ppc.pc.ProdId CatId = m.c.CatId // other assignments });
Jika perlu, Anda dapat menyimpan join ke variabel lokal dan menggunakannya kembali nanti, namun tidak memiliki detail lain yang sebaliknya, saya tidak melihat alasan untuk memperkenalkan variabel lokal.
Selain itu, Anda bisa melempar
Select
ke lambda terakhir dari yang keduaJoin
(sekali lagi, asalkan tidak ada operasi lain yang bergantung pada hasil gabungan) yang akan memberikan:var categorizedProducts = product .Join(productcategory, p => p.Id, pc => pc.ProdId, (p, pc) => new { p, pc }) .Join(category, ppc => ppc.pc.CatId, c => c.Id, (ppc, c) => new { ProdId = ppc.p.Id, // or ppc.pc.ProdId CatId = c.CatId // other assignments });
... dan melakukan upaya terakhir untuk menjual Anda pada sintaks kueri, ini akan terlihat seperti ini:
var categorizedProducts = from p in product join pc in productcategory on p.Id equals pc.ProdId join c in category on pc.CatId equals c.Id select new { ProdId = p.Id, // or pc.ProdId CatId = c.CatId // other assignments };
Tangan Anda mungkin terikat pada apakah kueri-sintaksis tersedia. Saya tahu beberapa toko memiliki mandat seperti itu - seringkali didasarkan pada anggapan bahwa sintaks-kueri agak lebih terbatas daripada sintaks titik. Ada alasan lain, seperti "mengapa saya harus mempelajari sintaks kedua jika saya dapat melakukan segalanya dan lebih banyak lagi dalam sintaks titik?" Seperti yang ditunjukkan bagian terakhir ini - ada detail yang disembunyikan sintaks-kueri yang dapat membuatnya layak untuk dirangkul dengan peningkatan pada keterbacaan yang dibawanya: semua proyeksi dan pengidentifikasi perantara yang harus Anda masak dengan senang hati tidak front-and-center- stage dalam versi query-syntax - mereka adalah background fluff. Dari kotak sabun saya sekarang - bagaimanapun, terima kasih atas pertanyaannya. :)
sumber
JOIN
pernyataan? Bagaimana kita melakukannya? Misalnya, dijoin pc in productcategory on p.Id equals pc.ProdId
baris, kita perlu menambahkanand p.Id == 1
.p.Id == 1
karena itu lebih merupakan filter di mana daripada itu adalah kriteria gabungan. Cara Anda akan melakukan bergabung pada lebih dari satu kriteria umumnya adalah dengan menggunakan jenis anonim:join pc in productcategory on new { Id = p.Id, Other = p.Other } equals new { Id = pc.ProdId, Other = pc.Other }
. Ini bekerja di Linq-to-Objects, dan saya anggap hal yang sama akan bekerja dengan query database juga. Dengan Database, Anda mungkin dapat mengabaikan kueri penggabungan yang rumit dengan mendefinisikan kunci asing yang sesuai dan mengakses data terkait melalui properti terkait.Apa yang Anda lihat adalah apa yang Anda dapatkan - dan itulah yang Anda minta, di sini:
(ppc, c) => new { productproductcategory = ppc, category = c}
Itu adalah ekspresi lambda yang mengembalikan tipe anonim dengan dua properti tersebut.
Di CategorizedProducts, Anda hanya perlu menggunakan properti tersebut:
CategorizedProducts catProducts = query.Select( m => new { ProdId = m.productproductcategory.product.Id, CatId = m.category.CatId, // other assignments });
sumber
CatId
bekerja dengan baik. UntukProdId
itu harusm.productproductcategory.product.Id
ORm.productproductcategory.productcategory.ProdId
. Kedua tugas tersebut berbeda, pertama pada produk (digabungkan denganproductcategory
) yang kedua adalah denganproductcategory
bergabung dengan keduanyaproduct
dancategory
. Apakah Anda mengikuti alasan saya?lihat kode contoh ini dari proyek saya
public static IList<Letter> GetDepartmentLettersLinq(int departmentId) { IEnumerable<Letter> allDepartmentLetters = from allLetter in LetterService.GetAllLetters() join allUser in UserService.GetAllUsers() on allLetter.EmployeeID equals allUser.ID into usersGroup from user in usersGroup.DefaultIfEmpty()// here is the tricky part join allDepartment in DepartmentService.GetAllDepartments() on user.DepartmentID equals allDepartment.ID where allDepartment.ID == departmentId select allLetter; return allDepartmentLetters.ToArray(); }
dalam kode ini saya bergabung dengan 3 tabel dan saya meludah kondisi join dari klausa mana
catatan: kelas Services hanya membengkokkan (merangkum) operasi database
sumber
public ActionResult Index() { List<CustomerOrder_Result> obj = new List<CustomerOrder_Result>(); var orderlist = (from a in db.OrderMasters join b in db.Customers on a.CustomerId equals b.Id join c in db.CustomerAddresses on b.Id equals c.CustomerId where a.Status == "Pending" select new { Customername = b.Customername, Phone = b.Phone, OrderId = a.OrderId, OrderDate = a.OrderDate, NoOfItems = a.NoOfItems, Order_amt = a.Order_amt, dis_amt = a.Dis_amt, net_amt = a.Net_amt, status=a.Status, address = c.address, City = c.City, State = c.State, Pin = c.Pin }) ; foreach (var item in orderlist) { CustomerOrder_Result clr = new CustomerOrder_Result(); clr.Customername=item.Customername; clr.Phone = item.Phone; clr.OrderId = item.OrderId; clr.OrderDate = item.OrderDate; clr.NoOfItems = item.NoOfItems; clr.Order_amt = item.Order_amt; clr.net_amt = item.net_amt; clr.address = item.address; clr.City = item.City; clr.State = item.State; clr.Pin = item.Pin; clr.status = item.status; obj.Add(clr); }
sumber
var query = from a in d.tbl_Usuarios from b in d.tblComidaPreferidas from c in d.tblLugarNacimientoes select new { _nombre = a.Nombre, _comida = b.ComidaPreferida, _lNacimiento = c.Ciudad }; foreach (var i in query) { Console.WriteLine($"{i._nombre } le gusta {i._comida} y nació en {i._lNacimiento}"); }
sumber
sudah lama tetapi jawaban saya dapat membantu seseorang:
jika Anda sudah mendefinisikan relasinya dengan benar, Anda dapat menggunakan ini:
var res = query.Products.Select(m => new { productID = product.Id, categoryID = m.ProductCategory.Select(s => s.Category.ID).ToList(), }).ToList();
sumber