Entity Framework返回IEnumerable还是IQueryable?

在使用EF的过程中,我们常常使用repository模式,本文就在repository层的返回值是IEnumerable类型还是IQueryable进行探讨。

一, 什么是Repository模式?

Repository是隔离在数据访问层和业务逻辑层之间的。它提供业务逻辑各种对象,使得业务逻辑代码不需要关心数据是如何存储和获取的。

下图,是MVC中使用Repository模式的图。Controller调用Repository来获取数据,而Repository调用EF来访问。

Repository模式的好处是它为逻辑和数据访问解耦,使得它们之间没有互相依赖。Repository可以挑选不同的数据来源,比如MySql, WCF, Web Service等,都不会影响到业务逻辑的改动。

这里写图片描述

一段典型的Repository代码类似于:

public class DailyReportRepository : IDailyReportRepository
{       
private readonly Context _context;       
public DailyReportRepository(Context context) 
{          
 _context = context;       
}       

public IQueryable<dailyreport> GetAllDailyReports()     
 {           
    return from report in _context.dailyreports select report;       
 } 

 public IEnumerable<dailyreport> GetAllDailyReports(DateTime start, DateTime end)       
 {   
   var query = from report in GetAllDailyReports() where   report.EntryDate >= start &&  report.EntryDate < end select report;  
   return query;       
 }
}

二,IEnumerable还是IQueryable的区别

上面的代码中的返回值一个是IEnumerable类型,一个是IQuerable类型,它们有什么不同呢? 那个更好?

IQueryable继承自IEnumerable,所以对于数据遍历来说,它们没有区别。

但是IQueryable的优势是它有表达式树,所有对于IQueryable的过滤,排序等操作,都会先缓存到表达式树中,只有当真正发生的时候,才会将表达式树由IQueryProvider执行获取数据操作。

而使用IEnumerable,所有对于IEnumerable的过滤,排序等操作,都是在内存中发生的。也就是说数据已经从中获取到了内存中,只是在内存中进行过滤和排序操作。

三,实际检验IEnumerableIQueryable的效率差别

Repository的代码如下, 返回同样的数据,一个使用IEnumerable,一个使用IQueryable

public class StudentRepository : IStudentRepository
{      
 private readonly SchoolContext _context;      
 public StudentRepository(SchoolContext context)
 {          
  _context = context;       
 } 

 public IEnumerable<Student> GetIEnumerableStudents() 
 {       
    return _context.Students;       
 } 

 public IQueryable<Student> GetIQueryableStudents()  
 {        
   return _context.Students;    
 }
}

在Controller中分别调用, 从Repository中返回的数据中,取2条显示在页面上。

public class HomeController : Controller 
{
    private readonly IStudentRepository _studentRepository;
    public HomeController(IStudentRepository studentRepository) 
    {
        _studentRepository = studentRepository;
    }
    public ActionResult Index() 
    {
        //Repository使用IEnumerable返回结果          
        var students = _studentRepository.GetIEnumerableStudents().Take(2);
        //Repository使用IQueryable返回结果          
        //var students = _studentRepository.GetIQueryableStudents().Take(2);          
        return View(students);
    }
}

呈现的页面如下:
这里写图片描述

但是通过MiniProfiler检测到的结果,使得真相水落石出。

前面一张是使用IEnumerable返回值的,后面一张是使用IQueryable返回值。

对比能够发现,使用IQueryable的查询,Take(2)的操作是通过Sql在数据库中完成的。

试想在数据较多的情况下或者操作比较复杂的情况下,IEnumerable的效率会比IQueryable低很多。

四,总结

结论应当非常明显,使用IQueryable作为Repository的返回值是我们最终的选择。

同时对于IQueryable有兴趣,不妨多深入研究。里面涉及的表达式树,是.net中的非常重要的概念。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值