簡體   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