Rob*_*oli 15 c# asynchronous entity-framework
我正在使用EF 6.1.3和.NET Framework 4.6.1实现模型.此模型由ASPNET应用程序和ASPNET CORE应用程序使用,因此它使用System.Data.Entity,它位于单独的程序集mymodel.dll中.
这是模型
using System.Data.Entity;
public partial class MyDbContext : DbContext
{
public virtual DbSet<Athlete> Athletes{ get; set; }
}
public partial class Athlete
{
public Athlete()
{
}
//...
public string Country { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我正在开发使用.NET Framework 4.6在aspnet核心中实现的MVC应用程序.它引用了EF 6.1.3,因此可以使用该模型.
public class MyViewModel
{
public IList<Athlete> ItalianAthletes{ get; set; }
}
using Microsoft.EntityFrameworkCore;
//solution: comment the previous line and use instead System.Data.Entity;
public class MyController : Controller
{
private readonly MyDbContext _context;
//...
public IActionResult Index()
{
MyViewModel myvm = new MyViewModel();
var result = _context.Athletes.Where(a=>a.Country=="Italy").ToList();
myvm.ItalianAthletes = result ;
return View(myvm);
}
}
Run Code Online (Sandbox Code Playgroud)
......它按预期工作.
现在将Index方法更改为async
public async Task<IActionResult> Index()
{
MyViewModel myvm = new MyViewModel();
var result = _context.Athletes.Where(a=>a.Country=="Italy").ToListAsync();
await result; //at this point an exception is thrown
//...
}
Run Code Online (Sandbox Code Playgroud)
InvalidOperationException:源IQueryable未实现IAsyncEnumerable.只有实现IAsyncEnumerable的源才能用于Entity Framework异步操作.
删除问题仍然存在的Where()子句,因此问题似乎与ToListAsync();
var result = _context.Users.ToListAsync();
Run Code Online (Sandbox Code Playgroud)
仔细阅读异常的文本我理解"由ToList()生成的IQueryable没有实现IAsyncEnumerable"但这对我没有意义,因为所有这些行为都是ToListAsync()的内部行为;
有人可以帮助我更好地了解引擎盖下发生的事情吗?我能做些什么让ToListAsync()按预期工作?
提前感谢您的任何评论
Igo*_*gor 10
你会想要做这两件事之一.
在两个程序集中引用EF nuget包.这是因为此ToListAsync()操作实际上是调用到您的EF DbContext,而这不能从没有引用EF NugetPackage的项目中完成.如果已经是这种情况,请确保System.Data.Entity在代码顶部的using语句中引用命名空间:
using System.Data.Entity;
Run Code Online (Sandbox Code Playgroud)
因为这是ToListAsync您要调用的扩展方法的位置.
在项目中使用EF的服务中包装从EF检索的代码,调用异步调用,并从您的asp.net mvc项目中调用它.这将是我的首选,因为它添加了一个很好的抽象层,使您的代码更容易测试/维护.
第二个选项的代码示例
public interface IAthleteService {
Task<List<Athlete>> GetAthletesByCountryAsync(string country, CancellationToken token);
}
public class AthleteService : IAthleteService {
private MyDbContext _context;
public async Task<List<Athlete>> GetAthletesByCountryAsync(string country, CancellationToken token)
{
return await _context.Athletes.Where(athlete => athlete.Country == country).ToListAsync(token).ConfigureAwait(false);
}
}
public class MyController : Controller
{
private readonly IAthleteService _service;
//...
public async Task<IActionResult> Index(CancellationToken token)
{
MyViewModel myvm = new MyViewModel();
myvm.ItalianAthletes = await _service.GetAthletesByCountryAsync("Italy", token).ConfigureAwait(true);
// rest of code
}
}
Run Code Online (Sandbox Code Playgroud)
笔记:
使用Entity Framework Core时,必须使用以下名称空间:
using Microsoft.EntityFrameworkCore;
Run Code Online (Sandbox Code Playgroud)
代替
using System.Data.Entity;
Run Code Online (Sandbox Code Playgroud)