2016-08-05 13 views
0

getUsers(リストID)のようなクエリを作成する必要があります。 idsで検索する必要があります。見つかった場合はリスト内のidsを返し、見つからない場合はすべてのユーザーを返します。複雑なクエリの場合

このクエリはどのように記述できますか?

これは私が始めた方法です:関数の戻り値の型が常に同じでなければならないので、

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のより深いところに配置する必要があります。リストからIDを持つユーザーが存在する場合には、uow.GetEntities<User>()戻りIQueryable<User>を想定し

+0

を使用する必要がありますが、あなたは二度の条件を実行しているように、これは思える、 – Sherlock

+1

@Sherlock:私はそれは見るように代替データソースに対して2回チェックするのではなく、ユーザーの完全なリストを常に実体化し、メモリー内の状態をチェックする必要があります。それは私にはあまり理想的ではないようです。この2つの間で、条件のチェックは不要なレコードのマテリアライズよりもおそらく安価です。 – David

+0

しかし、最初の(そしてすべての不要なレコードが除外された)出力で2回目のチェックが実行されますが、それは理想的です。 – Sherlock

2

、提案されたソリューションも構築し、データベースに二度idsリストを渡し、2つの高価IN (...) SQLクエリを実行関与 - Any用とWhereのための1。

私はむしろそれを異なって構成したいと思います。 ids.Containsに基づいてWhereというクエリを実行し、その結果をメモリに具体化します。その後、データが含まれているかどうかをローカルにチェックし、そうであれば結果を返します。フィルタなしでもう1つのクエリを実行します。これははるかに効率的です。このような

何か:要約すると

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

、あなたは、単一のデータベースクエリでやりたいことはできません。少なくとも2つのクエリを実行する必要があり、唯一の問題は最も効率的なアプローチを使用することです。

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