实体框架Async与Task.FromResult

时间:2014-08-08 10:14:38

标签: entity-framework asynchronous task

使用Entity Framework中的System.Data.Entity提供的异步方法与使用Task.FromResult包装相同的非异步方法之间有什么区别吗?

例如:

    private Task<int> GetCountAsync()
    {
        return this._myDbContext.Set<MyEntity>().CountAsync();
    }

    private Task<int> GetCountAsync()
    {
       return Task.FromResult(this._myDbContext.Set<MyEntity>().Count());
    }

1 个答案:

答案 0 :(得分:7)

是的,因为如果ADO驱动程序使用IOCP线程池实现异步方法(并且确实如此),则不会使用工作线程等待操作,而是使用{{3}的特殊等待机制以这种方式,服务器应该能够最好地扩展,当有很多争用对数据库查询执行长期运行的IO操作时。

检查一些文章,你可以找到谷歌搜索:

I/O Completion Ports

I/O Completion Ports

IOCP Thread Pooling in C#

从最后一个链接开始:

  

在以前版本的.NET Framework中,可以通过使用异步委托或ThreadPool类来模拟非阻塞执行;但是,这些解决方案只是在背景中阻止了另一个线程,这使得它们远非理想,以避免阻塞线程...

     

ADO.NET/SqlClient异步命令执行支持基于真正的异步网络I / O(或共享内存中的非阻塞信令)。

     

...没有阻塞的后台线程等待特定的I / O操作完成,我们使用Windows 2000 / XP / 2003操作系统的重叠I / O和输入/输出完成端口工具来可以使用单个线程(或其中一些)来处理给定进程的所有未完成请求。

编辑:从评论移至此处以扩展有关Async存储库模式特定问题的答案:

我认为你应该公开你需要的那些Async方法,扩展通用存储库,避免耦合EF并避免任务包装,添加CountAsync,AddSync,FindAsync以及你需要同步的所有方法。

查看Asynchronous Command Execution in ADO.NET 2.0

存储库示例:

public interface IRepository<T> where T : class
{
    Task<int> AddAsync(T t);
    Task<int> RemoveAsync(T t);
    Task<List<T>> GetAllAsync();
    Task<int> UpdateAsync(T t);
    Task<int> CountAsync();
    Task<T> FindAsync(Expression<Func<T, bool>> match);
    Task<List<T>> FindAllAsync(Expression<Func<T, bool>> match);
}

CountAsync实施:

public async Task<int> CountAsync()
{
    return await _dbContext.Set<T>().CountAsync();
}

直接从帖子中取出所有内容。

然后您还可以扩展您的通用存储库。

编辑添加了一些有用的读物​​:

通用工作单元和存储库(轻量级流畅)框架与示例Northwind ASP.NET MVC 5应用程序:The Repository Pattern