问题

你想用LINQ写一个搜索查询,能被转换成更有效率的SQL.另外,你想用EF的CodeFirst方式实现.

解决方案

假设你有如下Figure 13-6所示的模型

Figure 13-6. A simple model with a Reservation entity

 

         首先,这个例子用EFCodeFirst方式实现,Listing 13-10,我们创建实体类Reservation

Listing 13-10. The Reservation Entity Object

public class Reservation

{

public int ReservationId { get; set; }

public System.DateTime ResDate { get; set; }

public string Name { get; set; }

}

接下来,在Listing 13-11,我们创建用CodeFirst方式访问EF功能的DbContext对象.

Listing 13-11. DbContext Object

public class Recipe5Context : DbContext

{

public Recipe5Context()

: base("Recipe4ConnectionString")

{

// disable Entity Framework Model Compatibility

Database.SetInitializer<Recipe5Context>(null);

}

protected override void OnModelCreating(DbModelBuilder modelBuilder)

{

modelBuilder.Entity<Reservation>().ToTable("Chapter13.Reservation");

}

public DbSet<Reservation> Reservations { get; set; }

}

接下来在项目中添加App.config,并把Listing 13-12的代码添加到ConnectionStrings节下.

Listing 13-12. Connection String

<connectionStrings>

<add name="Recipe4ConnectionString"

connectionString="Data Source=.;

Initial Catalog=EFRecipes;

Integrated Security=True;

MultipleActiveResultSets=True"

providerName="System.Data.SqlClient" />

</connectionStrings>

你想用LINMQ写一个搜索查询,通过指定特定的人,或特定日期,或两者一起来获取Reservations(预定),你可能会用let关键字,像我们在Listing 13-13中的第一个查询那样,使得LINQ查询表达式更清晰可读,然而,let关键字会被转换成更复杂效率更低的SQL语句.为替换它,我们明确地在where子句里创建两个条件,像我们在Listing 13-13的第二个查询那样.

Listing 13-13. Using Both the let Keyword and Explicit Conditions in the Query

using (var context = new Recipe4Context())

{

context.Reservations.Add(new Reservation { Name = "James Jordan", ResDate = DateTime.Parse("4/18/10") });

context.Reservations.Add(new Reservation

{

Name = "Katie Marlowe",

ResDate = DateTime.Parse("3/22/10")

});

context.Reservations.Add(new Reservation

{

Name = "Roger Smith",

ResDate = DateTime.Parse("4/18/10")

});

context.Reservations.Add(new Reservation

{

Name = "James Jordan",

ResDate = DateTime.Parse("5/12/10")

});

context.Reservations.Add(new Reservation

{

Name = "James Jordan",

ResDate = DateTime.Parse("6/22/10")

});

context.SaveChanges();

}

using (var context = new Recipe4Context())

{

DateTime? searchDate = null;

var searchName = "James Jordan";

Console.WriteLine("More complex SQL...");

var query2 = from reservation in context.Reservations

let dateMatches = searchDate == null || reservation.ResDate == searchDate

let nameMatches = searchName == string.Empty || reservation.Name.Contains(searchName)

where dateMatches && nameMatches

select reservation;

foreach (var reservation in query2)

{

Console.WriteLine("Found reservation for {0} on {1}", reservation.Name,

reservation.ResDate.ToShortDateString());

}

Console.WriteLine("Cleaner SQL...");

var query1 = from reservation in context.Reservations

where (searchDate == null || reservation.ResDate == searchDate)

&&

(searchName == string.Empty || reservation.Name.Contains(searchName))

select reservation;

foreach (var reservation in query1)

{

Console.WriteLine("Found reservation for {0} on {1}", reservation.Name,

reservation.ResDate.ToShortDateString());

}

}

输出结果如下:

More complex SQL...

Found reservation for James Jordan on 4/18/2010

Found reservation for James Jordan on 5/12/2010

Found reservation for James Jordan on 6/22/2010

Cleaner SQL...

Found reservation for James Jordan on 4/18/2010

Found reservation for James Jordan on 5/12/2010

Found reservation for James Jordan on 6/22/2010

它是如何工作的

在内部写条件,如在Listing 13-13的第二个查询那样,可读性和可维护性不是很好.更具代表性地,可能用let关键字使代码更清晰可读,即使在一些情况下,会导致更复杂和低效的SQL代码.

让我们看一下这两种方式生成的SQL语句.Listing 13-14显示的是第一个查询的SQL语句.注意,在where子句里包含了case语句和一些cast语句等,如果我们的查询有更多的条件,产生的SQL语句会更复杂.

Listing 13-14. SQL Generated When let Is Used in the LINQ Query

SELECT

[Extent1].[ReservationId] AS [ReservationId],

[Extent1].[ResDate] AS [ResDate],

[Extent1].[Name] AS [Name]

FROM [Chapter13].[Reservation] AS [Extent1]

WHERE (

(CASE WHEN (@p__linq__0 IS NULL OR

@p__linq__1 = CAST( [Extent1].[ResDate] AS datetime2))

THEN cast(1 as bit)

WHEN ( NOT (@p__linq__0 IS NULL OR

@p__linq__1 = CAST( [Extent1].[ResDate] AS datetime2)))

THEN cast(0 as bit) END) = 1) AND

((CASE WHEN ((@p__linq__2 = @p__linq__3) OR

([Extent1].[Name] LIKE @p__linq__4 ESCAPE N''~''))

THEN cast(1 as bit)

WHEN ( NOT ((@p__linq__2 = @p__linq__3) OR

([Extent1].[Name] LIKE @p__linq__4 ESCAPE N''~'')))

THEN cast(0 as bit) END) = 1)

Listing 13-15显示了第二个查询产生的SQL语句,我们在where内使用条件,这个查询更简单并且在运行时更高效.

Listing 13-15. Cleaner, More Efficient SQL Generated When Not Using let in a LINQ Query

SELECT

[Extent1].[ReservationId] AS [ReservationId],

[Extent1].[ResDate] AS [ResDate],

[Extent1].[Name] AS [Name]

FROM [Chapter13].[Reservation] AS [Extent1]

WHERE (@p__linq__0 IS NULL OR

@p__linq__1 = CAST( [Extent1].[ResDate] AS datetime2)) AND

((@p__linq__2 = @p__linq__3) OR

([Extent1].[Name] LIKE @p__linq__4 ESCAPE N''~''))

Entity Framework 6 Recipes 2nd Edition(13-4)译 - 有效地创建一个搜索查询相关推荐

  1. Entity Framework 6 Recipes 2nd Edition(9-1)译-用Web Api更新单独分离的实体

    第九章 在N层结构的应用程序中使用EF 不是所有的应用都能完全地写入到一个单个的过程中(就是驻留在一个单一的物理层中),实际上,在当今不断发展的网络世界,大量的应用程序的结构包含经典的表现层,应用程, ...

  2. Entity Framework 6 Recipes 2nd Edition(13-2)译 - 用实体键获取一个单独的实体

    问题 不管你用DBFirst,ModelFirst或是CodeFirst的方式,你想用实体键获取一个单独的实体.在本例中,我们用CodeFirst的方式. 解决方案 假设你有一个模型表示一个Paint ...

  3. Entity Framework 6 Recipes 2nd Edition(9-2)译-用WCF更新单独分离的实体

    9-2. 用WCF更新单独分离的实体 问题 你想通过WCF为一个数据存储发布查询,插入,删除和修改,并且使这些操作尽可能地简单 此外,你想通过Code First方式实现EF6的数据访问管理 解决方案 ...

  4. Entity Framework 6 Recipes 2nd Edition(9-7)译-在WCF服务中序列化代理

    9-7. 在WCF服务中序列化代理 问题 从一个查询里返回一个动态代理对象,想要把它序列为一个POCO(Plain-Old CLR Objects)对象. 实现基于POCO实体对象, 在运行时,EF会 ...

  5. Entity Framework 6 Recipes 2nd Edition(10-6)译 - TPT继承模型中使用存储过程

    10-6. TPT继承模型中使用存储过程 问题 想在一个TPT继承模型中使用存储过程 解决方案 假设已有如Figure 10-6所示模型. 在模型里, Magazine(杂志) and DVD继承于基 ...

  6. Entity Framework 6 Recipes 2nd Edition(12-1)译 - 当SaveChanges( ) 被调用时执行你的代码...

    第12章定制EF 在本章的小节里,定制实体对象和EF处理的一些功能.这些小节将涵盖很多"幕后"的事情,能让你的代码更加统一解决一些事情,比如用一个业务规则中心统一地为实体执行验证. ...

  7. Entity Framework 6 Recipes 2nd Edition(10-5)译 - 在存储模型中使用自定义函数

    10-5. 在存储模型中使用自定义函数 问题 想在模型中使用自定义函数,而不是存储过程. 解决方案 假设我们数据库里有成员(members)和他们已经发送的信息(messages) 关系数据表,如Fi ...

  8. Entity Framework 6 Recipes 2nd Edition(10-3)译 - 返回结果是一个标量值

    10-3. 返回结果是一个标量值 问题 想取得存储过程返回的一个标量值. 解决方案 假设我们有如Figure 10-2所示的ATM机和ATM机取款记录的模型 Figure 10-2. 一个ATM机和A ...

  9. Entity Framework 6 Recipes 2nd Edition(11-5)译 - 从”模型定义”函数返回一个匿名类型...

    11-5. 从"模型定义"函数返回一个匿名类型 问题 想创建一个返回一个匿名类型的"模型定义"函数 解决方案 假设已有游客(Visitor) 预订(reserv ...

最新文章

  1. ORA-01940无法删除当前已连接用户
  2. jq鼠标移入移除事件
  3. 存图matlab,matlab中保存图片的方法
  4. 从开源自治,到微服务云化,阿里云的这款产品给了一剂提升微服务幸福感的良药
  5. linux tar 命令使用
  6. potplayer 多个进程_什么是进程
  7. 欧拉系统安装+eSight安装
  8. 大数据处理技术,主要包括哪些基本技术?
  9. C语言编程实现Euclid GCD算法 作业
  10. MTK处理器手机 解锁Bootloader 教程
  11. 如何远程访问 Redis
  12. 什么是深度学习?有哪些相关书籍推荐?
  13. SQL Server Table Spool优化
  14. 看电视剧《天道》一点感想 + 法兰克福美景Opencv聚类分析
  15. 解决错误:Unsatisfied dependency expressed through field ‘XXXService‘
  16. 在自己电脑上搭建一个FTP服务器
  17. Android屏幕密度的深刻理解
  18. 在Photoshop中绘制蜘蛛侠徽标
  19. 2020年9月电子学会C语言等级考试试卷(五级)答案解析
  20. PCB抄板就是一种反向研究技术

热门文章

  1. Stopping ADB server failed(code -1)
  2. JavaFX中将FXML文件自动转换为Java代码
  3. 《Go 语言程序设计》读书笔记 (三) 方法
  4. 详解varint编码原理
  5. win10 mysql 主从复制_win10 使用Docker配置mysql主从复制
  6. Kubernetes-[6]-StatefulSet
  7. vue中$router以及$route的使用
  8. 新手学习嵌入式需要掌握的几点知识点
  9. 《SSM框架实战》 整合 Freemarker
  10. 在 Centos 7 ssh登录出现locale异常