You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I'm using projection in EF Core with Linqkit to reuse expressions with Invoke(). I want to apply filters to projected models:
public class TransportModel
{
public Guid Id { get; set; }
public InmateModel Inmate { get; set; }
}
public class InmateModel
{
public Guid Id { get; set; }
public List<Guid> InmateIds { get; set; }
}
public static Expression<Func<Transport, Inmate>> GetInmateProjection()
{
return transport => transport.Inmate;
}
public static Expression<Func<Inmate, InmateModel>> InmateModelProjection()
{
return inmate => new InmateModel()
{
Id = inmate.Id,
InmateIds = inmate.Collusions.Select(x => x.InmateId).ToList()
};
}
public static Expression<Func<Transport, TransportModel>> GetTransportModelProjection()
{
return transport => new TransportModel()
{
Inmate = InmateModelProjection().Invoke(GetInmateProjection().Invoke(transport)),
};
}
// Actual query
IQueryable<TransportModel> query = dbContext.Transports
.Select(GetTransportModelProjection());
This code works unless there is an Inmate which is null. Then I get the following exception:
System.InvalidOperationException: Nullable object must have a value.
at lambda_method1483(Closure , QueryContext , DbDataReader ,
ResultContext , SingleQueryResultCoordinator ) at
Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable1.Enumerator.MoveNext() at System.Collections.Generic.List1..ctor(IEnumerable1 collection) at System.Linq.Enumerable.ToList[TSource](IEnumerable1 source)
So I add a null check to prevent this error:
public static Expression<Func<Transport, TransportModel>> GetTransportModelProjection()
{
return transport => transport != null ? new TransportModel()
{
Inmate = InmateModelProjection().Invoke(GetInmateProjection().Invoke(transport)),
} : null;
}
The exception does not appear anymore, however I cannot filter all data anymore:
// This works
query = query.Where(transport => transport.Inmate.Id == someId);
// This does not work anymore due to null check
query = query.Where(transport => transport.Inmate.InmateIds.Contains(someId));
This is the exception I get for the second filter:
The LINQ expression 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'.
Is there a bug in the translator?
The only workaround I can use so far is to flatten the models:
public static Expression<Func<Transport, TransportModel>> GetTransportModelProjection()
{
return transport => new TransportModel()
{
Inmate = InmateModelProjection().Invoke(GetInmateProjection().Invoke(transport)),
InmateIds = GetInmateProjection().Invoke(transport).Collusions.Select(x => x.Id).ToList()
};
}
But it would be nice to do this with nested projections.
Include provider and version information
EF Core version: 6.0.7
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 6.0
Operating system: Windows 11
IDE: Microsoft Visual Studio Enterprise 2022 (64-bit), Version 17.3.2
The text was updated successfully, but these errors were encountered:
SELECT [t].[Id], [i].[Id], [c].[InmateId]
FROM [Transport] AS [t]
LEFT JOIN [Inmate] AS [i] ON [t].[InmateId] = [i].[Id]
LEFT JOIN [Collusion] AS [c] ON [i].[Id] = [c].[InmateId]
ORDER BY [t].[Id], [i].[Id], [c].[InmateId]
This is the generated SQL query. Also the "Nullable object must have a value" exception only appears when a projected property of InmateModel is not nullable (Id). Otherwise it will just create a new model where Inmate / InmateId is null and set null for each property. But this is not what should happen, the whole Inmate property should be null instead.
@Ben555555 This exception is expected if the type isn't nullable. Creating an instance with null values instead of not creating an instance is tracked by #22517 (comment)
@Ben555555 This exception is expected if the type isn't nullable. Creating an instance with null values instead of not creating an instance is tracked by #22517 (comment)
But will this fix the null check from not being translated correctly?
I'm using projection in EF Core with Linqkit to reuse expressions with Invoke(). I want to apply filters to projected models:
This code works unless there is an Inmate which is null. Then I get the following exception:
So I add a null check to prevent this error:
The exception does not appear anymore, however I cannot filter all data anymore:
This is the exception I get for the second filter:
Is there a bug in the translator?
The only workaround I can use so far is to flatten the models:
and query like this
or build the filter directly on the unprojected query:
But it would be nice to do this with nested projections.
Include provider and version information
EF Core version: 6.0.7
Database provider: Microsoft.EntityFrameworkCore.SqlServer
Target framework: .NET 6.0
Operating system: Windows 11
IDE: Microsoft Visual Studio Enterprise 2022 (64-bit), Version 17.3.2
The text was updated successfully, but these errors were encountered: