4

次のように、データベースに多対多の関係を設定しています。

User
-------
Id (PK, Identity)
First
Last
...various other fields

Skill
-------
Id (PK, Identity)
Description

UserSkill
-----------
UserId (PK, FK on User.Id)
SkillId (PK, FK On Skill.Id)

DbContext でこの LINQ クエリを実行すると、次のようになります。

from u in Users 
from s in u.Skills 
where s.Id == 5 
select new 
{
    u.Id,
    s.Description
})

生成された SQL には、私が望むすべての内部結合が含まれています。

SELECT 
[Extent1].[UserId] AS [UserId], 
[Extent2].[Description] AS [Description]
FROM  [dbo].[UserSkill] AS [Extent1]
INNER JOIN [dbo].[Skill] AS [Extent2] ON [Extent1].[SkillId] = [Extent2].[Id]
WHERE 5 = [Extent2].[Id]

ただし、単純な追加の where 句を追加すると、次のようになります。

from u in Users 
from s in u.Skills 
where s.Id == 5 
    && u.Last == "test"
select new 
{
    u.Id,
    s.Description
})

生成された SQL は、サブクエリを使用するようになりました。

[Extent1].[Id] AS [Id], 
[Filter1].[Description] AS [Description]
FROM  [dbo].[User] AS [Extent1]
INNER JOIN  (SELECT [Extent2].[UserId] AS [UserId], [Extent3].[Description] AS [Description]
    FROM  [dbo].[UserSkill] AS [Extent2]
    INNER JOIN [dbo].[Skill] AS [Extent3] ON [Extent3].[Id] = [Extent2].[SkillId]
    WHERE 5 = [Extent3].[Id] ) AS [Filter1] ON [Extent1].[Id] = [Filter1].[UserId]
WHERE 'test' = [Extent1].[Last]

何かが足りないかもしれませんが、EF はこのクエリの User テーブルに別の結合を追加し、サブクエリを実行する代わりに User.Last で where を実行できると思います。この種の動作を強制する方法はありますか? 私は何か間違ったことをしていますか?

ありがとう。


アップデート

Cosmin さん、クエリを次のようにしてほしいと思っています。

SELECT u.Id, s.Description
FROM [User] u INNER JOIN
        [UserSkill] us ON u.Id = us.UserId INNER JOIN
        [Skill] s ON us.SkillId = s.Id
WHERE s.Id = 2 AND u.Last = 'test'
4

2 に答える 2

3

これは、EF が現在行っていない最適化のようです。個人的には、パフォーマンスが問題にならない限り、それが生成するサブクエリに固執します。

ただし、ユーザーとスキルの直接ナビゲーション プロパティをなくしても構わない場合は、中間テーブルをモデル化して、探しているクエリを取得できます。

public class User
{
    public int Id { get; set; }
    public string First { get; set; }
    public string Last { get; set; }

    public virtual ICollection<UserSkill> UserSkills { get; set; }
}

public class UserSkill
{
    public int Id { get; set; }
    [Required]
    public User User { get; set; }
    [Required]
    public Skill Skill { get; set; }

}

public class Skill
{
    public int Id { get; set; }
    public string Description { get; set; }

    public virtual ICollection<UserSkill> UserSkills { get; set; }
}

次に、次のクエリは、サブクエリの代わりに結合を生成します

 from x in db.UserSkills 
 where x.Skill.Id == 5 && x.User.Last == "test"
 select new {x.User.Id, x.Skill.Description};
于 2014-04-30T21:48:30.233 に答える
0

@ryanulit、あなたの問題は有効であり、すべての Linq to Entities の問題です。投稿された MS フォーラムの URL を確認してください。

MS フォーラムの URL

于 2014-04-30T14:38:56.687 に答える