2012-07-24 45 views
7

Sử dụng khung pháp nhân/LINQ, tôi cần trợ giúp với các điều sau.Làm cách nào để truy vấn bảng giao nhau

Cơ sở dữ liệu có bảng Người có cột nhận dạng của PersonId. Ngoài ra còn có một bảng kỹ năng với một cột nhận dạng của SkillId. Cả hai được kết nối thông qua một bảng thứ ba PeopleSkills có cột nhận dạng riêng của nó PeopleSkillsId, một cột nước ngoài tham chiếu đến PersonId và một cột nước ngoài tham chiếu đến SkillId.

Phương pháp mà tôi đang cố viết là thông qua một tham số của loại Danh sách chứa bất kỳ số kỹ năng nào mà chúng tôi đang tìm kiếm. Phương thức này sẽ trả về một List được liên kết với tất cả các kỹ năng trong danh sách tham số đầu vào. Làm cách nào để tạo danh sách loại trừ bất kỳ ai không có tất cả các kỹ năng trong danh sách Kỹ năng?

Vấn đề tôi gặp phải là tôi có rất ít trải nghiệm SQL. Tôi có rất nhiều kinh nghiệm lập trình khác, nhưng SQL luôn là một chút khó khăn đối với tôi. Tôi đã nghĩ đến việc sử dụng một Join, nhưng nó sẽ không hoạt động. tức là nếu người của tôi có kỹ năng A & B và danh sách tìm kiếm có các phần tử cho B & C, tham gia sẽ khớp với chúng trên B và trả về người đó. Tôi cần người này bị loại vì anh ta không có cả B & C.

Tôi cũng nghĩ về việc lặp qua danh sách kỹ năng và xây dựng bộ lọc, nhưng điều đó có vẻ xấu. Điều này dường như chỉ là một vấn đề mà LINQ được xây dựng để xử lý, sử dụng một List để truy vấn một List khác, và rằng cần có một giải pháp thanh lịch.

+1

Tôi muốn đưa ra một số suy nghĩ này; Tôi sẽ liên hệ lại với bạn trong vòng 24 giờ tới với câu trả lời toàn diện, nếu ai đó chưa làm như vậy. –

Trả lời

0

Điều này có thể làm việc:

public List<Person> GetPeopleWithAllSkills(List<Skill> skills) 
{ 
    var skillIds = skills.Select(s => s.SkillId); 

    return context.People.Where(
     p => skillIds.All(id => p.PeopleSkills.Any(ps => ps.SkillId == id))) 
     .ToList(); 
} 

Hãy cho tôi những người thực hiện với điều kiện là tất cả kỹ năng cho tồn tại (Any) trong danh sách các kỹ năng của những người đó. (Họ có thể có nhiều hơn các kỹ năng nhất định nhưng không ít hơn.)

+0

Cả hai câu trả lời đều cho tôi thấy một chút, nhưng đây là cách đơn giản, tao nhã mà tôi đã hình dung ra. Rực rỡ. –

1

Tôi đã sử dụng LinqPad, sử dụng Linq-to-SQL thay cho LINQ to Entities, nhưng các khái niệm phải giống nhau.

Trước tiên, dữ liệu tôi đã sử dụng để kiểm tra.

create table People (PersonID int, Name varchar(100)) 
create table Skills (SkillID int, Skill varchar(100)) 
create table PeopleSkills (PeopleSkillsID int, PersonID int, SkillID int) 

insert People values (1,'Bert'),(2,'Bob'),(3,'Phil'),(4,'Janet') 
insert Skills values (1,'C#'),(2,'Linq'),(3,'SQL') 
insert PeopleSkills values (1,1,1),(2,1,2),(3,1,3),(4,2,1),(5,2,3),(6,3,2),(7,3,3),(8,4,1),(9,4,2),(10,4,3) 

Và giải pháp.

//I don't know how you are specifying your list of skills; for explanatory purposes 
//I just generate a list. So, our test skill set is C#, Linq, and SQL. 
//int? is used because of LinqToSQL complains about converting int? to int 
var skills = new List<int?>(){1,2,3}; 
//This initial query is also a small bow to LinqToSQL; Really I just wanted a plain 
//List so that the Except and Any clauses can be used in the final query. 
//LinqToSQL can apparently only use Contains; that may or may not be an issue with 
//LinqToEntities. Also, its not a bad idea to filter the people we need to look at 
//in case there are a large number anyway. 
var peopleOfInterest = PeopleSkills.Where(p => skills.Contains(p.SkillID)).ToList(); 

//Final query is relatively simple, using the !x.Except(y).Any() method to 
//determine if one list is a subset of another or not. 
var peopleWithAllSkills = 
    //Get a distinct list of people 
    from person in peopleOfInterest.Select(p=>p.PersonID).Distinct() 
    //determine what skills they have 
    let personSkills = peopleOfInterest.Where(x=>x.PersonID == person).Select(x=>x.SkillID) 
    //check to see if any of the skills we are looking for are not skills they have 
    where !skills.Except(personSkills).Any() 
    select person; 
+0

Cảm ơn bạn. Tôi sẽ không bao giờ nghĩ ra! Ngoại trừ bất kỳ. –

Các vấn đề liên quan