2016-08-05 3 views
0

getUsers (list IDs)와 같은 쿼리를 만들어야합니다. ID로 검색 할 필요가있는 경우 목록에서 ID를 가진 사용자를 찾거나 찾지 못하면 모든 사용자를 반환하거나 하나만 찾으면 하나의 사용자 만 반환해야합니다.복잡한 쿼리 인 경우

어떻게하면이 쿼리를 작성할 수 있습니까?

이것은 내가 시작하는 방법이다 : 함수의 반환 형식은 항상 동일해야하기 때문에

public List<User> getUsers (List<int> ids)   
{ 
    using(var uow = _repository.CreateUnitOfWork()) 
    {    
     var u = uow.GetEntities<User>().Where(c => c.Id in ids); 
     if (u == null) 
     u.ToList();      
    } 
} 
+0

을 사용하는 것입니다 그리고 난 엔티티 프레임 워크 – Ovidiu

답변

2

귀하의 질문이 이해가되지 않습니다. 일부 시간은 List이고 나머지 시간은 User입니다.

나는이 같은 제안 : IEnumerable의 사용이 작업은 게으른하게, 따라서보다 효율적인 것을

var matchingUsers = GetUsersByIdOrAllUsers(ids); 

if (matchingUsers.Any() && !matchingUsers.Skip(1).Any()) 
{ 
    var singleUser = matchingUsers.Single(); 

    // Do stuff with the single user... 
} 

참고 : 한 사용자를 발견하는 경우

public IEnumerable<User> GetUsersByIdOrAllUsers(IEnumerable<int> ids) 
{ 
    using (var uow = _repository.CreateUnitOfWork()) 
    { 
     var users = uow.GetEntities<User>(); 

     if (users.Any(c => ids.Contains(c.ID))) 
     { 
      return users.Where(c => ids.Contains(c.ID)); 
     } 

     return users; 
    } 
} 

그런 다음 테스트 할 수 있습니다 . 당신이 정말List을 원하는 경우에, 다만 수행

var matchingUsersList = matchingUsers.ToList() 
0

그것을 할 수있는 적은 수다스러운 방법이 확실 있지만 논리적으로 어쩌면 이런 일이 내가 믿고있어

if (uow.GetEntities<User>().Any(u => ids.Contains(u.ID)) 
    return uow.GetEntities<User>().Where(u => ids.Contains(u.ID)).ToList(); 
return uow.GetEntities<User>().ToList(); 

을? : 여기서 uow.GetEntities<User>()은 단순히 쿼리 가능을 반환하고 데이터베이스 자체에서 아무 것도 구체화하거나 중요한 성능상의 불이익을주지 않습니다. 그렇지 않은 경우이 작업의 코드를 DAL에 더 깊게 배치해야 할 수 있습니다. 하나 AnyWhere 하나 - 목록에서 ID를 가진 사용자가, 제안 된 솔루션은 구축 및 데이터베이스에 두 번 ids 목록을 통과,이 비싼 IN (...) SQL 쿼리를 실행하는 것을 포함이 있습니다 uow.GetEntities<User>() 반환 IQueryable<User> 가정

+0

를 사용해야하지만, 두 번, – Sherlock

+1

@Sherlock을 조건을 실행하는 것처럼이 보인다 대안 나는 그것이 보는 바와 같이 데이터 소스에 대해 두 번 확인하지 않고 항상 전체 사용자 목록을 구체화하고 메모리 내 조건을 확인합니다. 그건 나에게 덜 이상적인 것처럼 보인다. 이 두 가지 사이에서 불필요한 레코드를 구체화하는 것보다 상태를 확인하는 것이 비용이 적게 듭니다. – David

+0

하지만 두 번째 검사가 첫 번째 출력에서 ​​수행되고 (불필요한 모든 레코드가 필터링 됨), 역시 이상적입니다. – Sherlock

2

.

차라리 다르게 구조화하려고합니다. 나는 ids.Contains을 기초로 Where이라는 쿼리를 실행하고 메모리에 결과를 구체화합니다. 그렇다면 데이터가 포함되어 있는지 로컬로 확인하고, 그렇다면 결과를 반환합니다. 필터 없이는 otherwice가 두 번째 쿼리를 실행하므로 훨씬 효율적입니다. 이 같은

뭔가 : 요약하자면

public List<User> getUsers (List<int> ids)   
{ 
    using(var uow = _repository.CreateUnitOfWork()) 
    {    
     var allUsers = uow.GetEntities<User>(); 
     var matchingUsers = allUsers 
      .Where(user => ids.Contains(user.Id)) 
      .ToList(); 
     return matchingUsers.Any() ? matchingUsers : allUsers.ToList(); 
    } 
} 

, 당신은 당신이 하나의 데이터베이스 쿼리로 원하는 작업을 수행 할 수 없습니다. 적어도 두 개의 쿼리를 실행해야하며 유일한 질문은 가장 효율적인 접근 방식을 사용하는 것입니다.

1

간단한 방법은 Join

public List<User> getUsers (List<int> ids)   
{ 
    using(var uow = _repository.CreateUnitOfWork()) 
    {    
     var u = uow.GetEntities<User>() 
         .Join(ids,x=>x.Id,y=>y,(x,y)=>x).ToList(); 
     if (u.Count==0) 
       return uow.GetEntities<User>().ToList() 
     return u;   
    } 
} 
0
public IList<User> getUsers (List<int > ids = null) 
{      
     var query = _repository.GetEntities<User>(); 

     if (ids == null)     
      return query.ToList();     

     if (ids.Count()==1) 
     {      
      var singleUser = query.FirstOrDefault(user => ids.Contains(user.Id)); 
      if (singleUser!= null)          
       return new List<User>{ singleUser; };   

      return new List<User>();     
     } 

     return query.Where(user => ids.Contains(user.Id)).ToList();              
}