2011-08-02 5 views
3

私は正しく構築されたと思ったクエリから奇妙な結果を得ています。ラムダ式が正しくない

このクエリは、正しいれ、2つの値を返します。

int userId = GetUserId(); //Not exactly like this; simplified 
var context = new Entities(); 
//Get the roles 
var relations = (from q in context.UserHasRole 
       where q.UserId == userId 
       select q).ToList(); 
List<Roles> roles = new List<Roles>(); 
foreach (var item in relations) 
{ 
    Roles role = (from r in context.Roles 
        where r.Id == item.RoleId 
        select r).SingleOrDefault(); 
        roles.Add(role); 
} 
return roles; 

このクエリしかし、デシベルで4人の関係が存在しないので、めちゃくちゃ間違っている4つの値を返します!すべての可能な役割を返します。私には、関係が正しいuserIdとroleIdの両方を持つレコードだけを返すかのようにクエリが見えます。

  //Get the roles 
      var roles = (from q in context.Roles 
         where context.UserHasRole.Any(o => o.UserId == userId) 
         && context.UserHasRole.Any(p => p.RoleId == q.Id) 
         select q).ToList(); 

      return roles; 

ラムダクエリはどのように構成すればよいですか?

答えて

7

私は前にこれを行っていませんでしたが、私の推測では、あなたがこのようにそれを行うべきであるということです。

//Get the roles 
var roles = (from q in context.Roles 
    where context.UserHasRole.Any(o => o.UserId == userId && o.RoleId == q.Id) 
    select q).ToList(); 

return roles; 
+0

パーフェクト。私は似たようなことを試しましたが、それは正しくありませんでした。しかし、この1つのスポットです。どうもありがとうございます! – Phil

+0

問題ありません!私はラムダ式が本当に好きです。それらを使ってリストを整理しますが、Linqはまだ使用していません。私は本当にチャンスを得るときにそれをチェックする必要があります。 :) – Paul

2

は試してみてください。

var roles = (from q in context.Roles 
    context.UserHasRole.Any(o => 
     o.UserId == userId 
     && o.RoleId == q.Id) 
    select q).ToList(); 
2

あなた「がある役割のために求めています「UserHasRoleテーブル内の特定のユーザとの関係」および「UserHasRoleテーブル内のロールとの関係があります」を参照してください。最初の条件は、ロールの場合と同じ結果になります。ロールに依存しないためです。

「あなたの役割は、の間に関係があります」という役割が必要です。 ...すべての役割のためにそう

from q in context.Roles 

与えられたとUserHasRole内のエントリが存在する

where context.UserHasRole.Any(o => o.UserId == userId) 

をクエリダウン

var roles = (from q in context.Roles 
     where context.UserHasRole.Any(o => o.UserId == userId && o.RoleId == q.Id) 
     select q).ToList(); 

return roles; 
2

ブレークとは、実際にやって何の領域を参照してくださいユーザーID ...

現在のロールと一致するroleIdを持つUserHasRoleのエントリです。...

select q 

ロールを選択します。

userIDがUserHasRoleのエントリがあり、ロールIDがUserHasRoleのエントリがあるかどうかを個別にチェックしているので、このロジックが望んでいないと感じました。しかし、そこにユーザーIDと、おそらく所望の効果であるロールID、両方とUserHasRoleエントリでないこと:

//Get the roles 
var roles = (from q in context.Roles 
      where context.UserHasRole.Any(o => o.UserId == userId 
              && o.RoleId == q.Id) 
      select q).ToList(); 

return roles; 
2

私はあなたのデータを見ずに確かに言うことはできませんが、私はあなたのクエリを期待しますあなたが探しているよりも多くの役割を返すことができます。ここで

は、既存のクエリのpseduoコードです:

Get all roles 
From those roles, accept only those where these are true: 
    Any mapping exists that matches the user ID 
    Any mapping exists that matches the role ID 

問題は、あなたがそれらのAny句が同じマッピングに煮詰めることを保証していないということです。ユーザーはその特定の役割を持つ必要はありません。ユーザーは何らかの役割を果たすだけで、役割はユーザーにマップされなければなりません。ここで

は、あなたが本当にあなたのクエリが何をしたいです:

Get all roles 
From those roles, accept only those where this is true: 
    Any mapping exists that matches *both* the user ID and the role ID 

このクエリを実装するには:

var roles = (from r in context.Roles 
      where context.UserHasRole.Any(uhr => uhr.UserId == userId 
       && uhr.RoleId == r.Id) 
      select r) 
      .ToList(); 
+0

+1私はクエリを分割する教育的アプローチを示すために – Phil

関連する問題