dotnet / dotnet/efcore

Cannot pass a field with an interface type into an EF extension

Open
#35,699 2 comments 0 reactions 0 assignees View on GitHub
area-query customer-reported
Dominant language
C#
Stars
14.8k
Forks
3.4k
PR merge metrics
PR metrics pending

Description

### Bug description

I have created a DBFunctions / IMethodCallTranslator extension called FreeTextSearch (The idea being that it provides a wrapper round the SQLite free text search Match method).

The prototype for the extension is in DbFunctionsExtensions.cs:

``public static bool FreeTextSearch(this DbFunctions _, object propertyReference, string freeText, [NotParameterized]IFreeTextConfig config) =>
throw new NotImplementedException("This method is for use with Entity Framework Core only and has no in-memory implementation.");``

When the extension is called like this (in Tests.cs):

``IFreeTextConfig config = new SqliteFreeTextConfig();
IQueryable query = context.TestTable.Where(e => EF.Functions.FreeTextSearch(e.TextContent!, "MIKE", config));``

The translator fails to get called and the an InvalidOperationException with the text shown below is raised:

System.InvalidOperationException: 'The LINQ expression 'DbSet()
.Where(t => __Functions_0
.FreeTextSearch(
propertyReference: t.TextContent,
freeText: "MIKE",
config: (IFreeTextConfig)SqliteFreeTextConfig))' could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.'

However, when I change IFreeTextConfig to SqliteFreeTextConfig (see below) then it works fine and the translator code gets called.

``SqliteFreeTextConfig config = new SqliteFreeTextConfig();
IQueryable query = context.TestTable.Where(e => EF.Functions.FreeTextSearch(e.TextContent!, "MIKE", config));``

The argument ``config`` in the method ``FreeTextSearch`` is type ``IFreeTextConfig`` so why does it not work if I pass an interface but does when I pass a concrete class?

Attached is a project that can be used to demonstrate the issue.

Thanks,

Mike

[EntityFrameworkTest.zip](https://github.com/user-attachments/files/19012821/EntityFrameworkTest.zip)

### Your code

```csharp
.
```

### Stack traces

```text

```

### Verbose output

```text

```

### EF Core version

9.0.2

### Database provider

Microsoft.EntityFrameworkCore.Sqlite

### Target framework

.Net 9.0

### Operating system

Windows 11

### IDE

Visual Studio 2022 17.13.2

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.