这样的双where的语句应该怎么写呢:
var test=MyList.Where(a => a.Flows.Where(b => b.CurrentUser == “”)
下面我就说说这个问题,想想有几种方法。先来做一下准备工作,我们使用最简单的模型Category和Post
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
public class Category { public int Id { get ; set ; } public string Name { get ; set ; } public virtual ICollection Posts { get ; set ; } } public class Post { public int Id { get ; set ; } public string Author { get ; set ; } public string Title { get ; set ; } public int CategoryId { get ; set ; } public Category Category { get ; set ; } } |
把上面的问题转换成这个模型解释就是:查询含有某个Author写的Post的Category。
这个问题如果直接使用SQL来写的话很简单:
1
2
3
|
select distinct (c.Id),c. Name from Categories c inner join Posts p on p.CategoryId=c.Id where p.Author=N 'cj' |
下面依次来看EntityFramework的四种实现方法。
第一种,使用Any
1
|
var list = ctx.Categories.Where(t => t.Posts.Any(s => s.Author == "cj" )); |
生成的SQL语句如下:
1
2
3
4
5
6
7
8
9
|
SELECT [Extent1].[Id] AS [Id], [Extent1].[ Name ] AS [ Name ] FROM [dbo].[Categories] AS [Extent1] WHERE EXISTS ( SELECT 1 AS [C1] FROM [dbo].[Posts] AS [Extent2] WHERE ([Extent1].[Id] = [Extent2].[CategoryId]) AND (N 'cj' = [Extent2].[Author]) ) |
第二种,使用Select
1
|
var list = ctx.Posts.Where(t => t.Author == "cj" ).Select(t => t.Category).Distinct(); |
生成的SQL语句如下:
1
2
3
4
5
6
7
8
9
10
|
SELECT [Distinct1].[Id] AS [Id], [Distinct1].[ Name ] AS [ Name ] FROM ( SELECT DISTINCT [Extent2].[Id] AS [Id], [Extent2].[ Name ] AS [ Name ] FROM [dbo].[Posts] AS [Extent1] INNER JOIN [dbo].[Categories] AS [Extent2] ON [Extent1].[CategoryId] = [Extent2].[Id] WHERE N 'cj' = [Extent1].[Author] ) AS [Distinct1] |
第三种,使用SelectMany
1
2
3
4
5
|
var list = ctx.Categories.SelectMany(t => t.Posts, (category, post) => new { category, post }).Where(t => t.post.Author == "cj" ).Select(t => t.category).Distinct(); |
生成的SQL语句如下:
1
2
3
4
5
6
7
8
9
10
|
SELECT [Distinct1].[Id] AS [Id], [Distinct1].[ Name ] AS [ Name ] FROM ( SELECT DISTINCT [Extent1].[Id] AS [Id], [Extent1].[ Name ] AS [ Name ] FROM [dbo].[Categories] AS [Extent1] INNER JOIN [dbo].[Posts] AS [Extent2] ON [Extent1].[Id] = [Extent2].[CategoryId] WHERE N 'cj' = [Extent2].[Author] ) AS [Distinct1] |
第四种,还是使用SelectMany
1
|
var list = ctx.Categories.SelectMany(t => t.Posts).Where(t => t.Author == "cj" ).Select(t => t.Category).Distinct(); |
生成的SQL语句如下:
1
2
3
4
5
6
7
8
9
10
|
SELECT [Distinct1].[Id] AS [Id], [Distinct1].[ Name ] AS [ Name ] FROM ( SELECT DISTINCT [Extent1].[Id] AS [Id], [Extent1].[ Name ] AS [ Name ] FROM [dbo].[Categories] AS [Extent1] INNER JOIN [dbo].[Posts] AS [Extent2] ON ([Extent1].[Id] = [Extent2].[CategoryId]) AND ([Extent2].[CategoryId] = [Extent1].[Id]) WHERE N 'cj' = [Extent2].[Author] ) AS [Distinct1] |
下面分别来说说这四种方法:
第一种方法Any,更符合我们的查询习惯,也就是文章开始提到的问题的查询风格,只不过里面的Where应该换成Any
第二种方法Select,生成的SQL语句,跟我们自己写的SQL语句是一样的,这种方法以Post为查询主体,好处可以看看SQL语句优化方面的知识。
第三种和第四种都是SelectMany,虽然EF的查询写法不同,但生成的SQL语句完全相同, 当然SelectMany是以Category为查询主体。关于SelectMany的用法请参考MSDN。
补充(2014-5-11)
第五种方法,使用Contains
1
|
var list = ctx.Categories.Where(t => t.Posts.Select(s => s.Author).Contains( "cj" )); |
生成的SQL语句如下:
1
2
3
4
5
6
7
8
9
|
SELECT [Extent1].[Id] AS [Id], [Extent1].[ Name ] AS [ Name ] FROM [dbo].[Categories] AS [Extent1] WHERE EXISTS ( SELECT 1 AS [C1] FROM [dbo].[Posts] AS [Extent2] WHERE ([Extent1].[Id] = [Extent2].[CategoryId]) AND (N 'cj' = [Extent2].[Author]) ) |
这种方法和第一种方法Any生成的SQL语句是一样一样的。