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
- Use a non-owned entity type as the IQueryable<T> element of the DbFunction.
- Define a dedicated read-model entity type (not owned) that mirrors the TVF columns and map the DbFunction to it.
- 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
- Never use an owned entity type as the IQueryable<T> element of a DbFunction.
- Define a dedicated keyless read-model entity for TVF results.
- Audit DbFunctions when converting entities to owned to catch invalid returns.
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
- The DbFunction ' ' returns ' ', but ' ' is not a mapped…
- The element type of the result of
- The entity type ' ' is mapped to the 'DbFunction' named ' '…
- The entity type ' ' is mapped to the DbFunction named ' '…
- Entity type ' ' has a split mapping and is an optional…
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)