简体   繁体   中英

Entity Framework Core on MySql calling FromSqlInterpolated and return list of entities

I am using C# in an ASP Core project with Entity Framework Core 5.0.3, and using the Pomelo EntityFrameworkCore for MySql.

I am able to call standard SP's just fine with the below method:

int recordCount = await context.Database.ExecuteSqlInterpolatedAsync($"call `SP_ON_MYSQL` ({param1}, {param2}");

The SP in question outputs a result set of the Entity that I want to capture, and when I try this:

var qry = await context.ENITY.FromSqlInterpolated($"call `SP_ON_MYSQL` ({param1}, {param2})").SingleOrDefaultAsync();

I get the following error:

*'FromSqlRaw' or 'FromSqlInterpolated' was called with non-composable SQL and with a query composing over it.

Thank you in advance for any help that can be offered. Consider calling 'AsEnumerable' after the method to perform the composition on the client side.*

I have seen examples of this working with SQL Server, so please don't mark as already answered, unless you can show me an example that is not SQL Server specific.

Try this:

var qry = await context.ENITY
  .FromSqlInterpolated($"call `SP_ON_MYSQL` ({param1}, {param2})")
  .ToListAsync()
  .SingleOrDefault();

The answer of @Torvin is correct.

You need to add a AsEnumerable() , ToList() etc. call before the SingleOrDefault() call, if you are querying from a stored procedure. See Re-introduce detection for non-composable SQL in FromSql #17558 on the official EF Core repo for more information.

Here is a fully working console program, that demonstrates the approach:

using System.Diagnostics;
using System.Linq;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using Pomelo.EntityFrameworkCore.MySql.Infrastructure;

namespace IssueConsoleTemplate
{
    public sealed class IceCream
    {
        public int IceCreamId { get; set; }
        public string Name { get; set; }
    }
    
    public class Context : DbContext
    {
        public DbSet<IceCream> IceCreams { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder
                .UseMySql(
                    "server=127.0.0.1;port=3306;user=root;password=;database=So67040870",
                    b => b.ServerVersion("8.0.21-mysql")
                          .CharSetBehavior(CharSetBehavior.NeverAppend))
                .UseLoggerFactory(
                    LoggerFactory.Create(
                        b => b
                            .AddConsole()
                            .AddFilter(level => level >= LogLevel.Information)))
                .EnableSensitiveDataLogging()
                .EnableDetailedErrors();
        }
    }

    internal class Program
    {
        private static void Main()
        {
            using var context = new Context();

            SetupDatabase(context);

            var iceCreamId = 1;
            var searchContacts = context.IceCreams
                .FromSqlInterpolated($"CALL `GetIceCreams`({iceCreamId})")
                .AsEnumerable() // <-- Mandatory: Use AsEnumerable(), ToList() etc. or you will get an exception.
                .SingleOrDefault();

            Trace.Assert(searchContacts != null);
            Trace.Assert(searchContacts.Name == "Vanilla");
        }

        private static void SetupDatabase(Context context)
        {
            context.Database.EnsureDeleted();
            context.Database.EnsureCreated();

            var connection = context.Database.GetDbConnection();
            connection.Open();

            using var command = connection.CreateCommand();
            command.CommandText = @"CREATE PROCEDURE `GetIceCreams`(`someArg` int)
BEGIN
    SELECT someArg as `IceCreamId`, 'Vanilla' as `Name`;
END";
            command.ExecuteNonQuery();
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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