![](/img/trans.png)
[英]How to write Repository method for .ThenInclude in EF Core 2
[英]How to create an asynchronous repository with EF Core?
我正在尝试使用存储库抽象 EF Core,但无法弄清楚如何使其异步。 这是同步版本:
public class UserRepository
{
private DbSet<User> users;
public UserRepository(ApplicationDbContext context)
{
users = context.Set<User>();
}
public IQueryable<User> GetAll()
{
return users;
}
...
}
问题是,为了使查询异步,我们需要使用 EF 的特殊扩展方法,如ToListAsync()
或CountAsync()
,如果使用存储库的项目引用 EF 命名空间,那么抽象的意义何在?
我研究的另一件事是返回IAsyncEnumerable<User>
,然后使用这个官方库异步使用 LINQ。 但是,我无法让它正常运行,因为在使用这些新的 LINQ 方法时,查询是在 .NET 中处理的,而不是将 LINQ 语法转换为 SQL。 我们以下面的查询为例:
var result = await Repository.GetAll()
.Limit(10)
.ToListAsync();
在使用 EF 的扩展方法时,我在 SSMS 中看到了这个查询:
exec sp_executesql N'SELECT [u].[Id], [u].[Deleted], [u].[EmailAddress], [u].[FirstName], [u].[LastName], [u].[PhoneNumber], [u].[Status], [u].[VerifiedEmailAddress], [u].[VerifiedPhoneNumber]
FROM [Users] AS [u]
ORDER BY (SELECT 1)
OFFSET @__p_0 ROWS FETCH NEXT @__p_1 ROWS ONLY',N'@__p_0 int,@__p_1 int',@__p_0=0,@__p_1=10
这意味着只会从数据库中选择 10 条记录,这正是我想要的。
但是当使用System.Linq.Async
的扩展方法时,我的 C# 代码仍然得到相同的结果,但是这个查询显示在 SSMS 中:
SELECT [u].[Id], [u].[Deleted], [u].[EmailAddress], [u].[FirstName], [u].[LastName], [u].[PhoneNumber], [u].[Status], [u].[VerifiedEmailAddress], [u].[VerifiedPhoneNumber]
FROM [Users] AS [u]
完全没有限制,这意味着如果我在 Users 表中有数百万行,那么每次运行查询时都会选择所有这些行,而我只需要前 10 行。
有没有办法使用 LINQ to SQL 和异步流? 或者也许是如何抽象 EF 但仍然允许异步查询的另一个想法?
我不建议抽象 EFCore,您可以使用IApplicationDbContext
抽象上下文。 主要是因为 EF 已经是一个抽象层,其次是因为让“用户”访问 IQueryable 可能会产生意外行为或异常。
如果你真的需要这样做,我在想的是:
public Task<List<User>> GetAsync(Action<IQueryable<User>> filter)
{
filter(_users);
return _users.ToListAsync();
}
并使用它:
var result = await Repository.GetAsync(x => x.Take(10));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.