繁体   English   中英

如何使用 EF Core 创建异步存储库?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM