dotnet/efcore · error · InvalidOperationException

The DbFunction ' ' has an invalid return type ' '. Owned…

Error message

The DbFunction '{function}' has an invalid return type '{type}'. Owned entity types cannot be used as the return type of a DbFunction.

What it means

ValidateDbFunction throws DbFunctionInvalidIQueryableOwnedReturnType when a non-scalar DbFunction (returns IQueryable<T>) has T as an owned entity type, or a type marked IsOwned, or a type shared as owned across entity types. DbFunctions returning queryables cannot return owned entities because ownership ties the entity to a specific owner, not to a free-standing function result.

Solutions

  1. Use a non-owned entity type as the IQueryable<T> element of the DbFunction.
  2. Define a dedicated read-model entity type (not owned) that mirrors the TVF columns and map the DbFunction to it.
  3. If the data must stay owned elsewhere, project the DbFunction into a DTO via FromSqlRaw and a SqlQueryRaw<T> instead.

Example fix

// before — Owner is an owned entity
[Owned] public class AddressRow { public string City { get; set; } }
public IQueryable<AddressRow> ActiveAddresses(this DbContext db)
    => throw new NotImplementedException();
modelBuilder.HasDbFunction(...); // throws

// after — dedicated non-owned read model
public class AddressView { public string City { get; set; } }
modelBuilder.Entity<AddressView>().HasNoKey();
public IQueryable<AddressView> ActiveAddresses(this DbContext db)
    => throw new NotImplementedException();
Defensive patterns

Strategy: validation

Validate before calling

var elementType = dbFunction.ReturnType.GetGenericArguments()[0];
var et = dbFunction.Model.FindEntityType(elementType);
if (et?.IsOwned() == true || ((IConventionModel)dbFunction.Model).IsOwned(elementType))
    throw new InvalidOperationException($"DbFunction cannot return owned entity {elementType}.");

Type guard

static bool ReturnsOwnedEntity(IDbFunction f)
{
    var t = f.ReturnType.GetGenericArguments()[0];
    var e = f.Model.FindEntityType(t);
    return e?.IsOwned() == true || ((IConventionModel)f.Model).IsOwned(t);
}

Prevention

When it happens

Trigger: Defining HasDbFunction on a method returning IQueryable<OwnedEntity> where OwnedEntity is configured via OwnsOne/OwnsMany or marked [Owned]. The validator checks `entityType?.IsOwned() == true || model.IsOwned(elementType) || (entityType == null && some entity shares the CLR type)`.

Common situations: Reusing an owned entity type as the element of a TVF/queryable DbFunction; migrating from regular entity to owned and forgetting to update the DbFunction; scaffolding table-valued functions whose row type was later marked owned.

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/e68ec90584022bd9. Report an issue: GitHub.

Appendix: source

Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:382

        {
            if (dbFunction.TypeMapping == null)
            {
                throw new InvalidOperationException(
                    RelationalStrings.DbFunctionInvalidReturnType(
                        dbFunction.ModelName,
                        dbFunction.ReturnType.ShortDisplayName()));
            }
        }
        else
        {
            var elementType = dbFunction.ReturnType.GetGenericArguments()[0];
            var entityType = model.FindEntityType(elementType);

            if (entityType?.IsOwned() == true
                || ((IConventionModel)model).IsOwned(elementType)
                || (entityType == null && model.GetEntityTypes().Any(e => e.ClrType == elementType)))
            {
                throw new InvalidOperationException(
                    RelationalStrings.DbFunctionInvalidIQueryableOwnedReturnType(
                        dbFunction.ModelName, elementType.ShortDisplayName()));
            }

            if (entityType == null)
            {
                throw new InvalidOperationException(
                    RelationalStrings.DbFunctionInvalidReturnEntityType(
                        dbFunction.ModelName, dbFunction.ReturnType.ShortDisplayName(), elementType.ShortDisplayName()));
            }

            if ((entityType.BaseType != null || entityType.GetDerivedTypes().Any())
                && entityType.FindDiscriminatorProperty() == null)
            {
                throw new InvalidOperationException(
                    RelationalStrings.TableValuedFunctionNonTph(dbFunction.ModelName, entityType.DisplayName()));
            }
        }

View on GitHub (pinned to 3a2006ef56)