2012-07-24 5 views
7

Entity Framework/LINQ를 사용할 때 다음과 같은 도움이 필요합니다.접합 테이블을 쿼리하는 방법

데이터베이스에는 PersonId의 식별 컬럼이있는 사람 테이블이 있습니다. SkillId의 ID 열이있는 Skills 테이블도 있습니다. 이 둘은 세 번째 테이블 인 PeopleSkills를 통해 연결됩니다. PeopleSkills는 고유 ID 열 PeopleSkillsId, PersonId를 참조하는 외부 열 및 SkillId를 참조하는 외부 열을 가지고 있습니다.

작성하려는 메소드에는 List 유형의 매개 변수가 전달됩니다.이 매개 변수에는 원하는 스킬이 포함되어 있습니다. 메서드는 입력 매개 변수 목록에있는 모든 기술에 연결된 List를 반환해야합니다. 기술 목록에 모든 기술이없는 사람을 제외한 목록을 작성하려면 어떻게합니까?

내가 가지고있는 문제는 SQL의 경험이 거의 없다는 것입니다. 다른 프로그래밍 경험은 많이 있지만 SQL은 항상 나에게 조금 어이가 있습니다. Join을 사용하는 것에 대해 생각했지만 작동하지 않습니다. 즉 내 사람이 기술 A & B를 보유하고 있고 검색 목록에 B & C의 요소가있는 경우 조인은 B에서 조인하고 해당 사람을 반환합니다. 두 사람이 모두 제외 되었기 때문에이 사람을 제외시켜야합니다.

스킬 목록을 반복하고 필터를 만드는 방법에 대해 생각했지만 추한 것처럼 보입니다. 이것은 LINQ가 처리하기 위해 작성된 List와 다른 List를 질의하는 것과 같은 멋진 솔루션처럼 보일 것입니다.

+1

나는 이것을 약간의 생각을하고 싶다; 다른 누군가가 이미 그렇게하지 않았다면 나는 포괄적 인 대답으로 다음 24 시간 이내에 다시 연락 할 것입니다. –

답변

0

이 일할 수 :

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(); 
} 

나에게 그 사람의 능력 목록에서 모든 주어진 능력 ( Any를) 존재한다는 조건을 충족 사람들을주십시오. (그들은 주어진 기술보다 더 많은 것을 가지고 있을지도 모른다.)

+0

두 답변 모두 저에게 상당히 많은 것을 보여주었습니다. 그러나 이것은 제가 구상하고있는 우아하고 간단한 방법입니다. 훌륭한. –

1

Linq to Entities 대신 Linq-to-SQL을 사용하는 LinqPad를 사용했지만 개념은 동일해야합니다.

먼저 테스트 할 때 사용한 데이터.

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) 

그리고 해결책.

//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

고맙습니다. 나는 결코 갈 수 없었을 것이다! Any를 제외하고. –

관련 문제