ไวยากรณ์สำหรับการรวมภายในใน LINQ กับ SQL คืออะไร


443

ฉันกำลังเขียนคำสั่ง LINQ ไปยัง SQL และฉันอยู่หลังไวยากรณ์มาตรฐานสำหรับการเข้าร่วมภายในปกติด้วย ONประโยคใน C #

คุณแสดงสิ่งต่อไปนี้ใน LINQ เป็น SQL ได้อย่างไร:

select DealerContact.*
from Dealer 
inner join DealerContact on Dealer.DealerID = DealerContact.DealerID

หากคุณมีคีย์ต่างประเทศระหว่างตารางคุณควรดูคำตอบของ Kirk Broadhurst ด้านล่าง
Guilherme

1
คุณควรเขียนชื่อตารางของคุณ ถือตาราง (รายการเกี่ยวกับ) ตัวแทนจำหน่ายจำนวนมากควรจะเรียกว่าผู้แทนจำหน่ายและตัวแทนจำหน่ายไม่
Aneves

5
@ ANANES มันห่างไกลจากการใช้งานแบบมาตรฐานในการใช้ชื่อตารางพหูพจน์ทั้งเอกพจน์และพหูพจน์เป็นที่ยอมรับอย่างสมบูรณ์ - ฉันเพิ่งเปลี่ยนจากพหูพจน์เป็นเอกพจน์เพื่อจับคู่ชื่อวัตถุ - ที่นี่คำตอบสูงสุดเห็นพ้องต้องกันมาก มีอยู่ - เช่น '1 แกะ 8 ตัว': stackoverflow.com/questions/338156/…
niico

@ Niico นี่ไม่ใช่สถานที่ที่จะพูดถึงว่าฉันเดาว่า ... แต่ Microsoft Entity Framework ทำให้ชื่อตารางเป็นวงกว้างRuby on Rails 'ORM ทำให้เกิดความหลากหลายของตาราง ... มันใกล้เคียงกับมาตรฐานสำหรับคุณหรือไม่ :) Counter-อาร์กิวเมนต์: NHibernate ดูเหมือนว่าจะไม่ได้ pluralize ตาราง
Aneves

2
แน่นอน - บางคนทำแบบเดียว - บางคนทำแบบอื่น ไม่มีการปฏิบัติมาตรฐาน ส่วนตัวผมคิดว่าเอกพจน์มีประโยชน์มากกว่ากัน
niico

คำตอบ:


572

มันไปบางอย่างเช่น:

from t1 in db.Table1
join t2 in db.Table2 on t1.field equals t2.field
select new { t1.field2, t2.field3}

มันจะดีถ้ามีชื่อและเขตข้อมูลที่สมเหตุสมผลสำหรับตารางของคุณสำหรับตัวอย่างที่ดีกว่า :)

ปรับปรุง

ฉันคิดว่าข้อความค้นหาของคุณอาจเหมาะสมกว่า:

var dealercontacts = from contact in DealerContact
                     join dealer in Dealer on contact.DealerId equals dealer.ID
                     select contact;

เนื่องจากคุณกำลังมองหาผู้ติดต่อไม่ใช่ตัวแทนจำหน่าย


11
ขอบคุณจากนี้ไปฉันจะใช้ชื่อที่เหมาะสมว่าเป็นแนวปฏิบัติที่เหมาะสมที่สุดใน linq แทนที่จะเป็นfrom c or from t1
shaijut

231

และเพราะฉันชอบไวยากรณ์ของโซ่นิพจน์นี่คือวิธีที่คุณทำกับสิ่งนั้น:

var dealerContracts = DealerContact.Join(Dealer, 
                                 contact => contact.DealerId,
                                 dealer => dealer.DealerId,
                                 (contact, dealer) => contact);

8
หากคุณต้องการกรองหรือเลือกในเขตข้อมูลจากทั้งสองตารางที่เข้าร่วมแทนที่จะเป็นเพียงแค่ในเขตข้อมูลของหนึ่งในสองตาราง (ตาราง DealerContact ในตัวอย่างคำตอบนี้) นี่เป็นตัวอย่าง: stackoverflow.com/a/29310640/12484
Jon Schneider

52

ในการขยายคำตอบไวยากรณ์ของนิพจน์เชนโดย Clever Human:

หากคุณต้องการทำสิ่งต่าง ๆ (เช่นตัวกรองหรือเลือก) ในเขตข้อมูลจากทั้งสองตารางที่ถูกรวมเข้าด้วยกัน - แทนเพียงหนึ่งในสองตารางเหล่านี้ - คุณสามารถสร้างวัตถุใหม่ในการแสดงออกแลมบ์ดาของพารามิเตอร์สุดท้ายเป็นวิธีการเข้าร่วม การรวมทั้งสองตารางเหล่านั้นเข้าด้วยกัน:

var dealerInfo = DealerContact.Join(Dealer, 
                              dc => dc.DealerId,
                              d => d.DealerId,
                              (dc, d) => new { DealerContact = dc, Dealer = d })
                          .Where(dc_d => dc_d.Dealer.FirstName == "Glenn" 
                              && dc_d.DealerContact.City == "Chicago")
                          .Select(dc_d => new {
                              dc_d.Dealer.DealerID,
                              dc_d.Dealer.FirstName,
                              dc_d.Dealer.LastName,
                              dc_d.DealerContact.City,
                              dc_d.DealerContact.State });

ส่วนที่น่าสนใจคือการแสดงออกแลมบ์ดาในบรรทัดที่ 4 ของตัวอย่าง:

(dc, d) => new { DealerContact = dc, Dealer = d }

... ที่เราสร้างวัตถุประเภทไม่ระบุชื่อใหม่ซึ่งมีคุณสมบัติเป็นระเบียน DealerContact และตัวแทนจำหน่ายพร้อมกับเขตข้อมูลทั้งหมดของพวกเขา

จากนั้นเราสามารถใช้ฟิลด์จากบันทึกเหล่านั้นในขณะที่เรากรองและเลือกผลลัพธ์ดังตัวอย่างที่เหลือซึ่งใช้dc_dเป็นชื่อสำหรับวัตถุนิรนามที่เราสร้างขึ้นซึ่งมีทั้ง DealerContact และ Dealer records เป็นคุณสมบัติ


9
เข้าร่วมกับ lambdas มีรูปแบบที่แย่มาก ฉันปฏิเสธที่จะใช้มัน ;-)
Mariusz

12
@ aristo ฉันไม่ตำหนิคุณเลย ฉันมักจะต้องอ้างอิงกลับไปที่โพสต์นี้เพื่อเตือนตัวเองเกี่ยวกับไวยากรณ์!
Jon Schneider

2
บางคนอย่างฉันชอบความมั่นคง นั่นเป็นเหตุผลที่ฉันค้นหาไวยากรณ์แลมบ์ดาโดยเฉพาะ
0014

43
var results = from c in db.Companies
              join cn in db.Countries on c.CountryID equals cn.ID
              join ct in db.Cities on c.CityID equals ct.ID
              join sect in db.Sectors on c.SectorID equals sect.ID
              where (c.CountryID == cn.ID) && (c.CityID == ct.ID) && (c.SectorID == company.SectorID) && (company.SectorID == sect.ID)
              select new { country = cn.Name, city = ct.Name, c.ID, c.Name, c.Address1, c.Address2, c.Address3, c.CountryID, c.CityID, c.Region, c.PostCode, c.Telephone, c.Website, c.SectorID, Status = (ContactStatus)c.StatusID, sector = sect.Name };


return results.ToList();

1
สวัสดีคุณช่วยบอกฉันหน่อยได้ไหมว่าส่วนนี้เกี่ยวกับอะไร สถานะ = (ContactStatus) c.StatusID ฉันสนใจเป็นพิเศษในส่วน: (ContactStatus) c.StatusID ขอแสดงความนับถือ Mariusz
Mariusz

1
@ aristo - ดูรหัสฉันเดาว่าContactStatusเป็น enum จริง ๆ และc.StatusIDไม่ใช่รหัส แต่เป็นค่าตัวเลขของ enum ถ้าฉันพูดถูก(ContactStatus)c.StatusIDก็แค่ชี้ไปที่จำนวนเต็ม
Joel Mueller

25

ใช้ตัวดำเนินการLinq Join :

var q =  from d in Dealer
         join dc in DealerConact on d.DealerID equals dc.DealerID
         select dc;

1
จะทำอย่างไรเมื่อฉันต้องการคอลัมน์ทั้ง d & dc?
Kuntady Nithesh

1
@KuntadyNithesh จากนั้นส่งคืนคลาสที่คุณสร้างเช่นเลือก MyCustomer ใหม่ {Id = dc.id, Id2 = d.id} นั่นแหละ!
Elisabeth

25

คุณสร้าง foreign key และ LINQ-to-SQL จะสร้างคุณสมบัติการนำทางสำหรับคุณ Dealerจากนั้นแต่ละคนจะมีคอลเลกชันDealerContactsที่คุณสามารถเลือกกรองและจัดการ

from contact in dealer.DealerContacts select contact

หรือ

context.Dealers.Select(d => d.DealerContacts)

หากคุณไม่ได้ใช้คุณสมบัติการนำทางคุณจะพลาดประโยชน์หลักอย่างใดอย่างหนึ่งของ LINQ-to-SQL - ส่วนที่แมปกราฟวัตถุ


โอ้ชายคุณช่วยประหยัดเวลาของฉันฉันไม่ต้องจัดการกับคนโง่เหล่านี้อีกต่อไป!
Tomas

23

โดยทั่วไปผู้ประกอบการเข้าร่วม LINQ จะไม่มีประโยชน์สำหรับ SQL เช่นแบบสอบถามต่อไปนี้

var r = from dealer in db.Dealers
   from contact in db.DealerContact
   where dealer.DealerID == contact.DealerID
   select dealerContact;

จะส่งผลให้เกิดการเข้าร่วมภายในใน SQL

เข้าร่วมเป็นประโยชน์สำหรับ IEnumerable <> เพราะมันมีประสิทธิภาพมากขึ้น:

from contact in db.DealerContact  

ประโยคจะถูกดำเนินการอีกครั้งสำหรับตัวแทนจำหน่ายทุกคน แต่สำหรับ IQueryable <> มันไม่ใช่กรณี เข้าร่วมยังมีความยืดหยุ่นน้อยลง


12

ที่จริงแล้วมักจะดีกว่าที่จะไม่เข้าร่วมใน linq นั่นคือ เมื่อมีคุณสมบัติการนำทางเป็นวิธีที่สั้นมากในการเขียนคำสั่ง linq ของคุณคือ:

from dealer in db.Dealers
from contact in dealer.DealerContacts
select new { whatever you need from dealer or contact }

มันแปลเป็นข้อที่:

SELECT <columns>
FROM Dealer, DealerContact
WHERE Dealer.DealerID = DealerContact.DealerID

คำสั่ง LINQ ที่มีหลายประโยค "จาก" (ในตัวอย่างนี้) มีลักษณะอย่างไรในไวยากรณ์เชนนิพจน์? เป็นไปได้ไหม?
Jon Schneider

1
SelectMany()เทียบเท่าวิธีไวยากรณ์ของมันคือ
Gert Arnold

3

ใช้การรวม LINQเพื่อดำเนินการเข้าร่วมภายใน

var employeeInfo = from emp in db.Employees
                   join dept in db.Departments
                   on emp.Eid equals dept.Eid 
                   select new
                   {
                    emp.Ename,
                    dept.Dname,
                    emp.Elocation
                   };

3

ลองสิ่งนี้:

     var data =(from t1 in dataContext.Table1 join 
                 t2 in dataContext.Table2 on 
                 t1.field equals t2.field 
                 orderby t1.Id select t1).ToList(); 

3
var q=(from pd in dataContext.tblProducts join od in dataContext.tblOrders on pd.ProductID equals od.ProductID orderby od.OrderID select new { od.OrderID,
 pd.ProductID,
 pd.Name,
 pd.UnitPrice,
 od.Quantity,
 od.Price,
 }).ToList(); 

ยินดีต้อนรับสู่ Stack Overflow! ในขณะที่ข้อมูลโค้ดนี้อาจแก้ไขคำถามรวมถึงคำอธิบายช่วยปรับปรุงคุณภาพของโพสต์ของคุณ จำไว้ว่าคุณกำลังตอบคำถามสำหรับผู้อ่านในอนาคตและคนเหล่านั้นอาจไม่ทราบสาเหตุของการแนะนำรหัสของคุณ โปรดอย่าพยายามทำให้รหัสของคุณแน่นเกินไปด้วยคำอธิบายที่อธิบายเนื่องจากจะช่วยลดความสามารถในการอ่านของทั้งรหัสและคำอธิบาย!
Goodbye StackExchange

2
OperationDataContext odDataContext = new OperationDataContext();    
        var studentInfo = from student in odDataContext.STUDENTs
                          join course in odDataContext.COURSEs
                          on student.course_id equals course.course_id
                          select new { student.student_name, student.student_city, course.course_name, course.course_desc };

ตำแหน่งที่นักเรียนและตารางเรียนมีความสัมพันธ์ระหว่างคีย์หลักและความสัมพันธ์กับต่างประเทศ





1
var list = (from u in db.Users join c in db.Customers on u.CustomerId equals c.CustomerId where u.Username == username
   select new {u.UserId, u.CustomerId, u.ClientId, u.RoleId, u.Username, u.Email, u.Password, u.Salt, u.Hint1, u.Hint2, u.Hint3, u.Locked, u.Active,c.ProfilePic}).First();

เขียนชื่อตารางที่คุณต้องการและเริ่มการเลือกเพื่อให้ได้ผลลัพธ์ของเขตข้อมูล


var list = (จากคุณใน db.Yourfirsttablename เข้าร่วม c ใน db.secondtablename บน u.firsttablecommonfields เท่ากับฟิลด์ c.secondtablecommon โดยที่ u.Username == ชื่อผู้ใช้เลือกใหม่ {u.UserId, u.CustomerId, u.ClientId, u.ClientId, u.RentId , u.Username, u.Email, u.Password, u.Salt, u.Hint1, u.Hint2, u.Hint3, u.Locked, u.Active, c.ProfilePic}) First ();
Sarfraj Sutar

1

Inner เข้าร่วมสองตารางใน linq C #

var result = from q1 in table1
             join q2 in table2
             on q1.Customer_Id equals q2.Customer_Id
             select new { q1.Name, q1.Mobile, q2.Purchase, q2.Dates }

1

จาก d1 ใน DealerContrac เข้าร่วม d2 ใน DealerContrac บน d1.dealearid เท่ากับ d2.dealerid เลือกใหม่ {dealercontract. *}


ยินดีต้อนรับสู่ Stack Overflow! คำตอบนี้ไม่เพิ่มอะไรเลยกับคำตอบที่มีอยู่แล้ว
Jeroen Heier

-6

หนึ่งตัวอย่างที่ดีที่สุด

ชื่อตาราง: TBL_EmpและTBL_Dep

var result = from emp in TBL_Emp join dep in TBL_Dep on emp.id=dep.id
select new
{
 emp.Name;
 emp.Address
 dep.Department_Name
}


foreach(char item in result)
 { // to do}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.