使用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());
}
答案 0 :(得分:7)
是的,因为如果ADO驱动程序使用IOCP线程池实现异步方法(并且确实如此),则不会使用工作线程等待操作,而是使用{{3}的特殊等待机制以这种方式,服务器应该能够最好地扩展,当有很多争用对数据库查询执行长期运行的IO操作时。
检查一些文章,你可以找到谷歌搜索:
从最后一个链接开始:
在以前版本的.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