我怎样才能 return 任务 <List<Model>> 来自 dapper for "Select * from table" 而不必再次查询第一个查询的结果 ID?

How can I return a Task<List<Model>> from dapper for "Select * from table" without having to query the resulting ids from the first query again?

我正在开发一个 Blazor 服务器端项目。 我为查询编写了一个存储库模式 class,但在使用函数 Task<List<Model>> GetAllModelsAsync() 时遇到了一些问题。我希望它成为 return 一项任务,这样我就可以在我的部分组件中等待它的结果 class 以允许更具响应性的渲染。

我使用以下代码让它工作:

public Task<List<Model>> GetAllModelsAsync()
        {
            List<Model> modelList = new();
            var sql = "SELECT * FROM model";
            var query = DbConnection.QueryAsync<Model>(sql).Result;
            
            var result = query.ToList();
            foreach (var model in result) modelList.Add(GetModelAsync(int.Parse($"{model.Id}")).Result);

            return Task.FromResult(modelList);
        }

尽管它正在运行,但感觉并不是最好的版本 因为我读过以下语法应该有效:

using (var connection = new SqlConnection(...)) 
{ 
  var authors = connection.Query<Author>(
    "Select * From Author").ToList(); 
}

我注意到以下语法也有效:

var query = (await DbConnection.QueryAsync<Model>(sql)).ToList();

虽然我现在必须将我的方法更改为异步。

我试图为它定义一个任务,但无法让它工作。

var sql = "SELECT * FROM model";
var task = new Task<List<Model>>(async () =>
{
  (await DbConnection.QueryAsync<Model>(sql)).ToList();
});

return task

现在我得到了return type of an 'async' anonymous function must be a 'void', 'Task', 'Task<T>', a task-like type, 'IAsyncEnumerable<T>', or 'lAsyncEnumerator<T>'

大多数错误状态的答案我必须return某种类型的任务<..>但我实际上return它。

我什至不确定这是否会破坏我的预期逻辑。 提前致谢!关于性能,我什至不确定我的第一个解决方案必须如此频繁地 运行 GetSkill 是否有任何好处。

这就是我使用 Dapper 的方式。效果很好:

  1. 制作你的 Dapper 方法 async
  2. 将调用您的方法的方法或事件也设为 async Task,这样您就可以 await 任务。
  3. 要return一个列表,执行return (await blah blah blah).ToList();
  4. 使用所有 SQL 调用的 Async 版本。

您的 foreach 循环似乎有点不对劲。你介意解释一下你想用它实现什么吗?您的第一个查询似乎应该 return 您需要的所有模型。

示例:

public async Task<List<ImageChoiceQuestion>> GetImageChoiceQuestionsByCreator(string AddedByUserId)
{
    string connectionString = _config.GetConnectionString("DefaultConnection");
    using (IDbConnection connection = new SqlConnection(connectionString));
    return (await connection.QueryAsync<ImageChoiceQuestion>(QImage.GetImageChoiceQuestionsByCreator, new { AddedByUserId })).ToList();
}

QImage.GetImageChoiceQuestionsByCreator 只是一个查询字符串。

我认为最直接的答案应该是:

public async Task<List<Model>> GetAllModelsAsync()
    {
        var sql = "SELECT * FROM model";
        var result = (await DbConnection.QueryAsync<Model>(sql))).ToList();
        
        return result;
    }

我不能说我有很多 Dapper 经验,但在您最初的实施中,您使用的是:

  1. .Result -> .Result 意思是你要阻塞等待任务完成才能得到查询的结果,以便立即使用。使用 await 关键字代替(这意味着还必须将 async 关键字添加到方法定义中)意味着当您等待的任何异步方法正在执行时,您都不会阻塞线程和当前正在执行的线程在此期间可以用于其他事情,直到结果准备就绪。我建议 Steven Cleary's blog posts 关于 async await 作为一个很好的参考。

  2. 我认为您不需要 foreach 循环。您将在第一次调用时获得所有模型,因此您不需要根据每个 ID 重新查询它们?

然后您可以像这样调用此方法

var allModels = await GetAllModelsAsync();