这样的双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

Demo下载地址

补充(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语句是一样一样的。

EntityFramework嵌套查询的五种方法的更多相关文章

  1. Android之数据存储的五种方法

    1.Android数据存储的五种方法 (1)SharedPreferences数据存储 详情介绍:http://www.cnblogs.com/zhangmiao14/p/6201900.html 优 ...

  2. 顽石系列:CSS实现垂直居中的五种方法

    顽石系列:CSS实现垂直居中的五种方法 在开发过程中,我们可能沿用或者试探性地去使用某种方法实现元素居中,但是对各种居中方法的以及使用场景很不清晰.参考的内容链接大概如下: 行内元素:https:// ...

  3. 【SQL】Oracle分页查询的三种方法

    [SQL]Oracle分页查询的三种方法 采用伪列 rownum 查询前10条记录 ? 1 2 3 4 5 6 7 8 9 10 11 [sql] select * from t_user t whe ...

  4. Java 字符串拼接 五种方法的性能比较分析 从执行100次到90万次

    [请尊重原创版权,如需引用,请注明来源及地址] > 字符串拼接一般使用“+”,但是“+”不能满足大批量数据的处理,Java中有以下五种方法处理字符串拼接,各有优缺点,程序开发应选择合适的方法实现 ...

  5. js去掉字符串前后空格的五种方法

    转载 :http://www.2cto.com/kf/201204/125943.html 第一种:循环检查替换[javascript]//供使用者调用  function trim(s){  ret ...

  6. 实现sticky footer的五种方法

    2017-04-19 16:24:48 什么是sticky footer 如果页面内容不够长的时候,页脚块粘贴在视窗底部:如果内容足够长时,页脚块会被内容向下推送. 用position实现? 如果是用 ...

  7. linux 清空catalina.out日志 不需要重启tomcat(五种方法)【转】

    1.重定向方法清空文件   [root@localhost logs]# du -h catalina.out  查看文件大小17M catalina.out[root@localhost logs] ...

  8. C#中得到程序当前工作目录和执行目录的五种方法

    string str="";str += "\r\n" + System.Diagnostics.Process.GetCurrentProcess().Mai ...

  9. 【转】这五种方法前四种方法只支持IE浏览器,最后一个方法支持当前主流的浏览器(火狐,IE,Chrome,Opera,Safari)

    <!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8&quo ...

随机推荐

  1. Ping-Pong (Easy Version)(DFS)

    B. Ping-Pong (Easy Version) time limit per test 2 seconds memory limit per test 256 megabytes input ...

  2. 主机访问虚拟机中linux上的web服务

    环境:主机windows xp 虚拟机centos 6.4 [root@localhost /]# iptables -I INPUT -p tcp --dport 80 -j ACCEPT[root ...

  3. 使用Codeblock搭建Windows下Objec-c学习环境

    学习Object-c如果使用的是Windows,一般推荐使用虚拟机,但是太重量级了,先要下载OS-X,又要下载x-code.这里推荐一种比较简便的方式,使用code-block来搭建简易的Object ...

  4. springMVC基础

    controllers包写控制器: @Controller @RequestMapping(value="/utils") public class UploadControlle ...

  5. MvvmLight框架使用入门(一)

    MvvmLight是比较流行的MVVM框架,相对较为简单易用.可能正因为简单,对应的帮助文档不多,对初学者就不够友好了.这里会用几篇随笔,就个人对MvvmLight的使用经验,来做一个入门的介绍. 第 ...

  6. Winform开发框架之简易工作流设计

    一讲到工作流,很多人第一反应就是这个东西很深奥,有时候又觉得离我们较为遥远,确实完善的工作流设计很多方面,而正是由于需要兼顾很多方面,一般通用的工作流都难做到尽善尽美.微软也提供了几个版本的WF框架支 ...

  7. BackgroundWorker实现的winfrom中实现异步等待加载图片显示

    BackgroundWorker简介    BackgroundWorker在winfrom中有对应控件,该有三个事件:DoWork .ProgressChanged 和 RunWorkerCompl ...

  8. 解决android引用library project错误

    在andriod项目中引用另一个library project时,报 The container 'Android Dependencies' references non existing libr ...

  9. Python入门笔记(21):Python函数(4):关于函数式编程的内建函数

    一.关于函数式编程的内建函数 apply()逐渐被舍弃,这里不讨论 1.filter() #filter(func,seq) """纯Python描述filter函数&q ...

  10. Python基础:新式类的属性访问

    一.概述 二.准备工作 1.讨论对象 2.名词解释 三.实例绑定的属性访问 1.获取属性 一般规则 参考源码 示例验证 2.设置属性 一般规则 参考源码 示例验证 3.删除属性 一般规则 参考源码 示 ...