dotnet / EntityFramework.Docs

Documentation for Entity Framework Core and Entity Framework 6
https://docs.microsoft.com/ef/
Creative Commons Attribution 4.0 International
1.63k stars 1.96k forks source link

FromSql method when used with stored procedure cannot be composed error #2492

Open robinwilson16 opened 4 years ago

robinwilson16 commented 4 years ago

It would be useful if this breaking changes document included how to handle the breaking change when amending EF code for stored procedures that return a single entity.

The suggested fix is to change

context.Products.FromSqlRaw("[dbo].[Ten Most Expensive Products]").FirstOrDefault();

To

context.Products.FromSqlRaw("[dbo].[Ten Most Expensive Products]").AsEnumerable().FirstOrDefault();

However whilst this works with tables it does not work for stored procedures where a single item is returned and no information on how to handle this is provided. After some trial and error I found this worked:

(await _context.Products.FromSqlInterpolated($"EXEC GetProducts").ToListAsync()).FirstOrDefault();

The issue does not apply for a list of items where this works:

await _context.Products.FromSqlInterpolated($"EXEC GetProducts").ToListAsync();

Could the docs be updated for next time I need to remind myself how I did this?


Document Details

Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.

ajcvickers commented 4 years ago

Notes from triage: we should document using IX-Async for this:

var result = await context.Set<Product>()
    .FromSqlRaw("[dbo].[Ten Most Expensive Products]")
    .AsAsyncEnumerable()
    .FirstOrDefaultAsync();

We might also consider showing how to write some of these extensions manually to avoid the dependency. For example:

public static class AsyncEnumerableExtensions
{
    public static async Task<TSource> FirstOrDefaultAsync<TSource>(this IAsyncEnumerable<TSource> source)
    {
        await using var e = source.GetAsyncEnumerator();
        return await e.MoveNextAsync() ? e.Current : default;
    }
}