异步方法不可用于ObjectResult<;T>;

本文关键字:lt gt ObjectResult 用于 异步方法 | 更新日期: 2023-09-27 18:26:23

根据EF6的文档,ObjectResult实现了IDbAsyncEnumerable <T>、IDbAsync Enumerable,这意味着它实现了ObjectResult <T>等异步方法ToListAsync(),对吗?

然而,在VisualStudio中,当调用这样的存储过程时,我并不认为这是一种可能的方法:

public async Task<List<MyObject>> GetResultFromMyStoredProcedure(string foo, string bar)
{
    return await context.My_Stored_Procedure(foo, bar).ToListAsync();
}

但将存储过程作为查询调用似乎确实有效:

public async Task<List<MyObject>> GetResultFromMyStoredProcedure(string foo, string bar)
{
    var fooParam = new SqlParameter("@foo", foo);
    var barParam = new SqlParameter("@bar", bar);
    return await context.Database.SqlQuery<T>("My_Stored_Procedure @foo, @bar", fooParam, barParam).ToListAsync();
}

我已经确保我的项目引用了正确的EF dll(6.1.3)-使用NuGet。我错过了什么?

异步方法不可用于ObjectResult<;T>;

更新

由于你不能直接转换为Queryable,我已经反编译了EF用于IDbAsyncEnumerable的内部方法,并制作了这个扩展方法(来自微软反编译的源代码,所以它应该尽可能好):

public static Task<List<T>> ToListAsync<T>(this IDbAsyncEnumerable<T> source, CancellationToken cancellationToken)
{
    TaskCompletionSource<List<T>> tcs = new TaskCompletionSource<List<T>>();
    List<T> list = new List<T>();
    ForEachAsync<T>(source.GetAsyncEnumerator(), new Action<T>(list.Add), cancellationToken).ContinueWith((Action<Task>)(t =>
    {
        if (t.IsFaulted)
            tcs.TrySetException((IEnumerable<Exception>)t.Exception.InnerExceptions);
        else if (t.IsCanceled)
            tcs.TrySetCanceled();
        else
            tcs.TrySetResult(list);
    }), TaskContinuationOptions.ExecuteSynchronously);
    return tcs.Task;
}
private static async Task ForEachAsync<T>(IDbAsyncEnumerator<T> enumerator, Action<T> action, CancellationToken cancellationToken)
{
    using (enumerator)
    {
        cancellationToken.ThrowIfCancellationRequested();
        if (await System.Data.Entity.Utilities.TaskExtensions.WithCurrentCulture<bool>(enumerator.MoveNextAsync(cancellationToken)))
        {
            Task<bool> moveNextTask;
            do
            {
                cancellationToken.ThrowIfCancellationRequested();
                T current = enumerator.Current;
                moveNextTask = enumerator.MoveNextAsync(cancellationToken);
                action(current);
            }
            while (await System.Data.Entity.Utilities.TaskExtensions.WithCurrentCulture<bool>(moveNextTask));
        }
    }
}

如果没有CancellationToken,你可能会有过载,比如:

public static Task<List<T>> ToListAsync<T>(this IDbAsyncEnumerable<T> source)
{
   return ToListAsync<T>(source, CancellationToken.None);
}

旧答案(无效

不确定我是否能正确理解这个问题,但你就不能简单地这样做吗?

return await context.My_Stored_Procedure(foo, bar).AsQueryable().ToListAsync();