zoukankan      html  css  js  c++  java
  • 《Entity Framework 6 Recipes》中文翻译系列 (17) 第三章 查询之分页、过滤和使用DateTime中的日期部分分组

    翻译的初衷以及为什么选择《Entity Framework 6 Recipes》来学习,请看本系列开篇

    3-12 分页和过滤

    问题

      你想使用分页和过滤来创建查询。

    解决方案

      假设你有如图3-13所示的模型,模型中有一个Custormer实体类型。

    图3-13 包含一个Customer实体类型的模型

      你有一个基于过滤条件来显示客户信息的应用。你的公司有许多客户(也许数百万!),为了保证尽可能响应的用户体验,你想在每一页上只显示一定数量的客户。创建一个查询,它能过虑客户并按页返回可控数量的结果集。如代码清单3-26所示。

    代码清单3-26. 一个包含过滤和分页的查询

     1 using (var context = new EFRecipesEntities())
     2             {
     3                 // 删除之前的数据
     4                 context.Database.ExecuteSqlCommand("delete from chapter3.customer");
     5                 // 添加新的测试数据
     6                 context.Customers.Add(new Customer
     7                 {
     8                     Name = "Roberts, Jill",
     9                     Email = "jroberts@abc.com"
    10                 });
    11                 context.Customers.Add(new Customer
    12                 {
    13                     Name = "Robertson, Alice",
    14                     Email = "arob@gmail.com"
    15                 });
    16                 context.Customers.Add(new Customer
    17                 {
    18                     Name = "Rogers, Steven",
    19                     Email = "srogers@termite.com"
    20                 });
    21                 context.Customers.Add(new Customer
    22                 {
    23                     Name = "Roe, Allen",
    24                     Email = "allenr@umc.com"
    25                 });
    26                 context.Customers.Add(new Customer
    27                 {
    28                     Name = "Jones, Chris",
    29                     Email = "cjones@ibp.com"
    30                 });
    31                 context.SaveChanges();
    32             }
    33 
    34 
    35             using (var context = new EFRecipesEntities())
    36             {
    37                 string match = "Ro";
    38                 int pageIndex = 0;
    39                 int pageSize = 3;
    40 
    41                 var customers = context.Customers.Where(c => c.Name.StartsWith(match))
    42                 //var customers = context.Customers.Where(c => c.Name.Contains(match))
    43                                     .OrderBy(c => c.Name)
    44                                     .Skip(pageIndex * pageSize)
    45                                     .Take(pageSize);
    46                 Console.WriteLine("Customers Ro*");
    47                 foreach (var customer in customers)
    48                 {
    49                     Console.WriteLine("{0} [email: {1}]", customer.Name, customer.Email);
    50                 }
    51             }
    52 
    53             using (var context = new EFRecipesEntities())
    54             {
    55                 string match = "Ro%";
    56                 int pageIndex = 0;
    57                 int pageSize = 3;
    58 
    59                 var esql = @"select value c from Customers as c 
    60                  where c.Name like @Name
    61                  order by c.Name
    62                  skip @Skip limit @Limit";
    63                 Console.WriteLine("\nCustomers Ro*");
    64                 var customers = ((IObjectContextAdapter)context).ObjectContext.CreateQuery<Customer>(esql, new[]
    65                       {
    66                         new ObjectParameter("Name",match),
    67                         new ObjectParameter("Skip",pageIndex * pageSize),
    68                         new ObjectParameter("Limit",pageSize)
    69                       });
    70                 foreach (var customer in customers)
    71                 {
    72                     Console.WriteLine("{0} [email: {1}]", customer.Name, customer.Email);
    73                 }
    74             }
    75 
    76             Console.WriteLine("\nPress <enter> to continue...");
    77             Console.ReadLine();

    代码清单3-26的输出如下:

    Customers Ro*
    Roberts, Jill [email: jroberts@abc.com]
    Robertson, Alice [email: arob@gmail.com]
    Roe, Allen [email: allenr@umc.com]
    Customers Ro*
    Roberts, Jill [email: jroberts@abc.com]
    Robertson, Alice [email: arob@gmail.com]
    Roe, Allen [email: allenr@umc.com]

    原理

      在代码清单3-26中,针对这个问题,我们展示了不同的方法。在第一种方法中,我们使用了LINQ to Entities扩展方法创建了一个LINQ查询。我们使用Where()方法过滤结果集,过虑条件为,姓以“Ro“开头。因为我们在lambda表达工中使用了扩展方法StartsWith()。我们不需要使用SQL的通配符表达式“Ro%"。

      过滤后,我们使用OrderBy()方法对结果集排序,排序后的结果集通过方法Skip()来获取。我们使用Skip()方法跳过PageIndex页,每页的大小为PageSize. 使用Take()方法来获取受限的结果集(译注:从结果集获取指定页大小的记录数),我们只需要获取结果集中的一页。

      注意,在代码块中,我们使用LINQ扩展方法创建了一个完整的查询,而不是我们之前看到的SQL查询表达式。Skip()和Take()方法只在扩展方法中公布,不是查询语法。

      第二种方法,我们构建了一个完整的参数化的Entity SQL表达式,这也许是你最熟悉的方式,但是这在使用字符串和可执行代码(C#)来表示查询的两种方式间产生了固有的不匹配风险。

    3-13 按日期分组

    问题

      你有一个包含DateTime类型属性的实体,你想通过DateTime类型属性的Date部分来对实体的实例进行分组。

    解决方案

      假设你有如图3-14所示的模型,模型中有一个Registration实体类型,该实体类型包含一个DateTime类型的属性。

    图3-14 模型中有一个Registration实体类型,该实体类型包含一个DateTime类型的属性

      该示例使用Code-First方法,在代码清单3-27中,我们创建了一些实体。

    代码清单3-27. Registration实体类型

    1 public class Registration
    2 {
    3     public int RegistrationId { get; set; }
    4     public string StudentName { get; set; }
    5     public DateTime? RegistrationDate { get; set; }
    6 }

      接下来,代码清单3-28中创建了上下文对象,它是用Code-First方法访问实体框架功能的入口。

    代码清单3-28.  上下文对象

     1 public class EFRecipesEntities : DbContext
     2 {
     3     public EFRecipesEntities()
     4         : base("ConnectionString") {}
     5     public DbSet<Registration> Registrations { get; set; }
     6     protected override void OnModelCreating(DbModelBuilder modelBuilder)
     7     {
     8         modelBuilder.Entity<Registration>().ToTable("Chapter3.Registration");
     9         base.OnModelCreating(modelBuilder);
    10     }
    11 }        

      我们使用RegistrationDate属性的Date部分对所有的registrations进行分组,你可能会对LINQ中的 group by RegistrationDate.Date动心.虽然能过编译,但是你仍会得到一个运行时错误,该错误描述Date不能转换成SQL。 为了能使用RegistrationDate属性的Date部分来分组,请看代码清单3-29.

    代码清单3-29. 使用DateTime类型属性的Date部分对实例进行分组

     1 using (var context = new EFRecipesEntities())
     2             {
     3                 // 删除之前的测试数据
     4                 context.Database.ExecuteSqlCommand("delete from chapter3.registration");
     5                 // 添加新的测试数据
     6                 context.Registrations.Add(new Registration
     7                 {
     8                     StudentName = "Jill Rogers",
     9                     RegistrationDate = DateTime.Parse("12/03/2009 9:30 pm")
    10                 });
    11                 context.Registrations.Add(new Registration
    12                 {
    13                     StudentName = "Steven Combs",
    14                     RegistrationDate = DateTime.Parse("12/03/2009 10:45 am")
    15                 });
    16                 context.Registrations.Add(new Registration
    17                 {
    18                     StudentName = "Robin Rosen",
    19                     RegistrationDate = DateTime.Parse("12/04/2009 11:18 am")
    20                 });
    21                 context.Registrations.Add(new Registration
    22                 {
    23                     StudentName = "Allen Smith",
    24                     RegistrationDate = DateTime.Parse("12/04/2009 3:31 pm")
    25                 });
    26                 context.SaveChanges();
    27             }
    28 
    29             using (var context = new EFRecipesEntities())
    30             {
    31                 var groups = from r in context.Registrations
    32                              // 凭借内置的TruncateTime函数提取Date部分
    33                              group r by DbFunctions.TruncateTime(r.RegistrationDate)
    34                                  into g
    35                                  select g;
    36                 foreach (var element in groups)
    37                 {
    38                     Console.WriteLine("\nRegistrations for {0}",
    39                            ((DateTime)element.Key).ToShortDateString());
    40                     foreach (var registration in element)
    41                     {
    42                         Console.WriteLine("\t{0}", registration.StudentName);
    43                     }
    44                 }
    45             }
    46 
    47             Console.WriteLine("\nPress <enter> to continue...");
    48             Console.ReadLine();

    代码清单3-29输出如下:

    Registrations for 12/3/2009
    Jill Rogers
    Steven Combs
    Registrations for 12/4/2009
    Robin Rosen
    Allen Smit

    原理

      对registrations分组的分组键是通过Truncate()函数提RegistrationDate属性中的Date部分。这是实体框架的内置函数,包含在DbFunctions类中,它只提取DateTime中的Date部分。内置的DbFunctions类,包含着大量的,格式化、聚合、字符串操作、日期和数字服务。它在命名空间System.Data.Entity中。遗留类,EntityFunctios,是在EF6之前的版本中使用的,它仍然能在EF6中使用,但你会得到一个编译警告,它建议你使用最亲的DbFunctions类。我们将在11章继续讨论它。

    实体框架交流QQ群:  458326058,欢迎有兴趣的朋友加入一起交流

    谢谢大家的持续关注,我的博客地址:http://www.cnblogs.com/VolcanoCloud/

    版权所有,转载请注明出处 付灿的技术博客
  • 相关阅读:
    java中动态给sql追加?号
    在java中构建json对象,返回给前端页面
    java中的文件下载
    Session和Cookie
    处理全站请求编码,无论是GET还是POST,默认是UTF-8
    配置Spring的用于初始化容器对象的监听器
    在web.xml中配置struts2拦截器
    java生成一次性验证码
    tab------左右布局
    java使用Base64编码
  • 原文地址:https://www.cnblogs.com/VolcanoCloud/p/4513791.html
Copyright © 2011-2022 走看看