C# 只有实现IAsyncEnumerable的源才能用于实体框架异步操作
我正在使用EF6.1.3和.NETFramework 4.6.1实现一个模型。 此模型由ASPNET应用程序和ASPNET核心应用程序使用,因此它使用System.Data.Entity,并位于单独的程序集mymodel.dll中 这就是模型C# 只有实现IAsyncEnumerable的源才能用于实体框架异步操作,c#,entity-framework,asynchronous,C#,Entity Framework,Asynchronous,我正在使用EF6.1.3和.NETFramework 4.6.1实现一个模型。 此模型由ASPNET应用程序和ASPNET核心应用程序使用,因此它使用System.Data.Entity,并位于单独的程序集mymodel.dll中 这就是模型 using System.Data.Entity; public partial class MyDbContext : DbContext { public virtual DbSet<Athlete> Athlete
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; }
}
仔细阅读异常文本,我理解“ToList()生成的IQueryable没有实现IAsyncEnumerable”,但这对我来说没有意义,因为所有这些行为都是ToListSync()的内部行为
有人能帮我更好地了解引擎盖下发生了什么?我该怎么做才能使ToListSync()按预期工作
提前感谢您的任何评论您将想做以下两件事之一 在两个程序集中引用EF nuget包。这是因为此
ToListAsync()
操作实际上是通过EF DbContext调用的,而这不能从没有EF NugetPackage引用的项目中完成。如果已经出现这种情况,请确保在代码顶部的using语句中引用命名空间System.Data.Entity
:
using System.Data.Entity;
因为这是要调用的扩展方法toListSync
的位置
将从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
}
}
公共接口IAthleteService{
任务GetAthletesByCountryAsync(字符串国家/地区,取消令牌);
}
公共类体育服务:IAthleteService{
私有MyDbContext\u context;
公共异步任务GetAthletesByCountryAsync(字符串国家/地区,取消令牌)
{
return await _context.atternates.Where(atternate=>atternate.Country==Country).ToListAsync(令牌).ConfigureAwait(false);
}
}
公共类MyController:Controller
{
专用只读IAthleteService\u服务;
//...
公共异步任务索引(CancellationToken令牌)
{
MyViewModel myvm=新的MyViewModel();
myvm.意大利语运动员=等待_服务.GetAthletesByCountryAsync(“意大利”,令牌).ConfigureAwait(true);
//代码的其余部分
}
}
注:
- 我使用了CancellationToken,它允许取消异步操作。这是完全可选的
- 我使用了ConfigureAwait,这允许您指定在操作恢复时是否应重新捕获相同的线程上下文。不这样做可以节省资源(pass false),但您只能在可能的情况下这样做。在上面的例子中,它是在库中完成的。同样在上面的示例中,它不是从控制器完成的,因为您需要与线程关联的Http上下文(pass true)
- 我没有考虑清理资源(比如使AthleteService可用于清理DbContext)或注入依赖项
using Microsoft.EntityFrameworkCore;
而不是
using System.Data.Entity;
两个程序集都已引用EF。6.1.3(编辑我的问题)@RobertoVanoli-您是否确保使用System.Data.Entity
代码>包含在顶部的控制器代码文件中?此命名空间包含要调用的扩展方法。您猜对了,我引用了错误的EF。实际上,我在控制器中使用的是Microsoft.EntityFrameworkCore,而不是System.Data.Entity。现在调用的是正确的ToListSync()方法(不清楚ToList()版本以前工作的原因)。附言:我想为你的额外建议加上+1,但我的声誉不允许我现在投票:-(.无论如何,谢谢你,还有regards@RobertoVanoli-很好,很高兴你成功了!你现在应该可以投票了,因为你有超过15名代表(我在20或30分钟前投票了你的问题)。我代表您这样做了@RobertoVanoli Good solution:)可能会对您有所帮助:使用solutionFor Entity Framework Core访问编辑代码这是最准确的答案和最新的答案,必须作为解决方案进行投票。
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
}
}
using Microsoft.EntityFrameworkCore;
using System.Data.Entity;