question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Impossible to use stored procedures related to entities that inherits another one

See original GitHub issue

There is no way what so ever to get any dataset from a stored procedure that returns a type that inherits from another one:

var result = this.Context.Set<MyEntity>().FromSqlRaw($"EXECUTE MyStoredProcedure").AsEnumerable().ToList();

Whatever I do, it will always compose the call of my stored procedure: I suppose it tries to compose because it feels the need to ensure to get the right type. But it is obviously wrong:

SELECT 
  [p].blabla1, 
  [p].blabla2
FROM (
    EXECUTE MyStoredProcedure
) AS [p]
WHERE ([p].[Discriminator] = N'MyEntity')

Is there a way to have the code executed AS IS (no sort, no any where clause that would disturb the order of the dataset…), and blindly map to the columns that are setup in the entity setup?

Prior EF core 3.0, wrapping the sql statement within a sql_execute did the trick. But this doesn’t work anymore as it tries to compose anyway. This new behavior is more than understandable, as I was even initially surprised that preventing composition in such a way was working. I perfectly get the point of composition, and it is a fantastic feature to combine custom code with Linq operators. But it happens (in some specific cases) that we actually simply need EF mapping feature.

I understand that amending existing freshly neat and clear methods would jeopardize stability and clarity of its behavior, so I suppose it is very reasonable to assume that FromSqlRaw, FromSqlInterpolated or FromSql will always be composed as they are meant to be combined with Linq operations.

For everything else, you could simply expose another method that permits to build a collection of entities from a DataTable, a DataReader, a free sql statement (or anything that you believe is better) based on EF mapping specifications as this feature must already already exist somewhere within EF core. No confusion as the distinction would be crystal clear, and everybody (EF team and developers) would be satisfied.

Note

I created an interceptor to proceed with a simple “uncompose” for statements that have been composed whereas they shouldn’t.

using System.Data.Common;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.EntityFrameworkCore.Diagnostics;

namespace FundProcess.Pms.DataAccess
{
    public class InappropriateCompositionRemoverInterceptor : DbCommandInterceptor
    {
        private static readonly string[] _regexString = new[]{
            @".*\sfrom\s+\(\s*(?<query>execute\s+.+)\s*\)\s+as\s+.*",
            @".*\sfrom\s+\(\s*(?<query>.+\s+option\s+\(.+\))\s*\)\s+as\s+.*"
        };
        private static Regex[] _regexes;
        public InappropriateCompositionRemoverInterceptor()
        {
            _regexes = _regexString.Select(i => new Regex(i, RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.Singleline | RegexOptions.IgnoreCase)).ToArray();
        }
        public override InterceptionResult<DbDataReader> ReaderExecuting(
          DbCommand command,
          CommandEventData eventData,
          InterceptionResult<DbDataReader> result)
        {
            foreach (var regex in _regexes)
            {
                command.CommandText = ProcessRegex(command.CommandText, regex);
            }
            return result;
        }
        private string ProcessRegex(string input, Regex regex)
        {
            var match = regex.Match(input);
            if (match.Success)
                input = match.Groups["query"].Value;
            return input;
        }
    }
}

The problem is that EF core doesn’t map column using their name but by using their position in the column list… So I’m still stuck as I don’t have any idea where EF takes this specific order from. So I still have no way to get entities from a procedure, in a multitenant context, with an entity type that inherits another one.

Further technical details

EF Core version: 3.0 Database provider: Microsoft.EntityFrameworkCore.SqlServer Target framework: .NET Core 3.0 Operating system: ubuntu 19.04 IDE: Visual Studio Code

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Reactions:3
  • Comments:13 (6 by maintainers)

github_iconTop GitHub Comments

4reactions
smitpatelcommented, Dec 5, 2019

@stas-lucky - If your entity has a global query filter then you need to call IgnoreQueryFilters. Either your stored procedure returns data which is already filtered for your purposes (in which case you are good to go), or data from sproc requires additional filtering, since purpose of global query filters is to apply filters on database side, in latter case you need to ignore query filters and apply filters yourself on client.

This issue does not happen when using global query filter. I have updated title and OP to reflect that.

2reactions
jsgoupilcommented, Feb 3, 2020

I’m not sure what is the deal here, but personally, I am unable to run that command at all.

var result = this.Context.Set<MyEntity>().FromSqlRaw($"EXECUTE MyStoredProcedure").AsEnumerable().ToList();

There are no calls made on the database, and I always get the following error:

FromSqlRaw or FromSqlInterpolated was called with non-composable SQL and with a query composing over it. Consider calling `AsEnumerable` after the FromSqlRaw or FromSqlInterpolated method to perform the composition on the client side

I’m on EF Core 3.1.1. I spent about 3h trying everything with this .NET core 3.1.1 and nothing, I can’t make a store procedure work at all.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Possible to call a stored procedure on a Table-Per- ...
This is yet another issue introduced by EFC 3, tracked by #18232: Impossible to use stored procedures related to entities that inherits ...
Read more >
What are the pros and cons of using stored procedures vs ...
Pros: The company (developers) has lots of experience working with stored procedures. The deployment process is easier when we only have to ...
Read more >
Chapter 10. Working with stored procedures
Let's start with the first case, where the result of the stored procedure isn't an entity but is something else: a set of...
Read more >
8 Entity Framework Gotchas
If you have a stored procedure mapped to an entity that is part of an inheritance hierarchy, you must also map stored procedures...
Read more >
Who Needs Stored Procedures, Anyways?
Stored procedures can be individually secured within the database. A client can be granted permissions to execute a stored procedure without ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found