Skip to content

Incompatibility with Dbcontext, DbFunction and Interface #33025

@chrisdreams13

Description

@chrisdreams13

DbFunction don't get the mapping function when an interface is used

There's a strange behavior when an interface is used instead of the direct object of dbcontext when a DbFunciton is called. In the code bellow, I create a function in sql (Test) and added it to my context using DbFunctionAttribute.

If MyDbContext is used to call the Test function works ok. The problem is when the IMyDbContext interface is required to the dependency injection, the Test function throws the NotSupportedException like the mapping doesn't exist.

I tried to cast the interface reference to the base class and works ok, but I believe it's not the desired behavior using interfaces. Also, I tried to add virtual to Test function in MyDbContext, but didn't works with the interface.

Code

CREATE FUNCTION dbo.Test(@i int) RETURNS int AS
begin
  return @i;
end
public interface IMyDbContext {
    int Test(int i);
}
public class MyDbContext(DbContextOptions<MyDbContext> dbContextOptions) : DbContext(dbContextOptions), IMyDbContext {
    ...
    [DbFunction("Test", "dbo", IsBuiltIn = false)]
    public int Test(int i) => throw new NotSupportedException();
}
// Added both to my dependency injection
var builder = WebApplication.CreateBuilder(args);
builder
    .AddDbContext<IMyDbContext, MyDbContext>(ServiceLifetime.Transient)
    .AddDbContext<MyDbContext>(ServiceLifetime.Transient);
public class MyController(IMyDbContext iContext, MyDbContext context): ControllerBase
{
    public IActionResult TestOk() => Ok(
        context.Users.Select(it => context.Test(it.Id))); // using concrete class

    public IActionResult TestWrong() => Ok(
        iContext .Users.Select(it => iContext .Test(it.Id))); // using interface

    public virtual IActionResult TestCastOk()
    {
        var ctx = iContext as MyDbContext;                    // using interface, casted to concrete class
        return Ok(ctx!.Users.Select(it => ctx.Tomorrow(it.Id)));
    }
}

Stack traces

[12:43:18 DBG] Compiling query expression: 
'DbSet<User>()
    .Select(it => __P_0.Test(it.Id))'
[12:43:18 DBG] Generated query execution expression: 
'queryContext => new SingleQueryingEnumerable<int>(
    (RelationalQueryContext)queryContext, 
    RelationalCommandCache.QueryExpression(
        Client Projections:
            0 -> 0
        SELECT u.Id
        FROM Users.Users AS u), 
    null, 
    Func<QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator, int>, 
    MyDbContext, 
    False, 
    True, 
    True
)'
[12:43:18 DBG] Creating DbConnection.
[12:43:18 DBG] Created DbConnection. (2ms).
[12:43:18 DBG] Opening connection to database '' on server ''.
[12:43:18 DBG] Opened connection to database '' on server ''.
[12:43:18 DBG] Creating DbCommand for 'ExecuteReader'.
[12:43:18 DBG] Created DbCommand for 'ExecuteReader' (1ms).
[12:43:18 DBG] Initialized DbCommand for 'ExecuteReader' (3ms).
[12:43:18 DBG] Executing DbCommand [Parameters=[], CommandType='"Text"', CommandTimeout='30']
SELECT [u].[Id]
FROM [Users].[Users] AS [u]
[12:43:18 INF] Executed DbCommand (3ms) [Parameters=[], CommandType='"Text"', CommandTimeout='30']
SELECT [u].[Id]
FROM [Users].[Users] AS [u]
[12:43:18 ERR] 
An exception occurred while iterating over the results of a query for context type 'MyDbContext'.
System.NotSupportedException.
   at MyDbContext.Test(Int32 i) in MyDbContext.Accounting
   at lambda_method39(Closure, QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator)
   at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
[12:43:18 DBG] Closing data reader to '' on server ''.
[12:43:18 DBG] A data reader for '' on server '' is being disposed after spending 113ms reading results.

Include provider and version information

EF Core version: Microsoft.EntityFrameworkCore, 8.0.0
Database provider: Microsoft.EntityFrameworkCore.SqlServer, 8.0.0
Target framework: net8.0
Operating system: Windows 10
IDE: Microsoft Visual Studio Professional 2022 (64-bit) 17.8.3

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions