I don’t spend as much time in Entity Framework as I probably should and was recently caught out by a bit of a gotcha with a new feature in EF Core 8 that I thought would be useful to note down.
Background
EF Core 8 is now out alongside .Net 8 with some shiny new features under the hood. One of those being the usage of the OPENJSON
type when using a .Contains
inside a .Select
. From what I understand this is a performance boost rather than using the previous method of IN
in the underlying SQL query. More information on that here: EF Core 8 What’s New
Usually the joy of Entity Framework means that you don’t have to worry too much about this stuff (but you should have some idea what is happening under the hood!).
The Gotcha
So what’s the problem?
I’ll be honest here. In this instance I’m writing against an existing database and relying on minimal configuration for my entities. This resulted in me not setting a MaxLength on an entity, which in turn results in the following query being produced:
SELECT [s].[Id], [s.Code]
FROM [Item] AS [s]
WHERE EXISTS (
SELECT 1
FROM OPENJSON(@__Codes_0) WITH ([value] nvarchar '$') AS [s0]
WHERE [s0].[value] = [s].[Code] OR ([s0].[value] IS NULL AND [s].[Code] IS NULL))
Notice the [value] nvarchar
. That should have a length to it, but instead is truncated to 1 character without it.
The fix is simple, in the entity configuration I needed to assign a HasMaxLength(30)
to the property e.g.
builder.Property(x => x.Code).HasColumnName("Code").HasColumnType("nvarchar").HasMaxLength(30);
This results in the query being updated and working now as expected:
SELECT [s].[Id], [s.Code]
FROM [Item] AS [s]
WHERE EXISTS (
SELECT 1
FROM OPENJSON(@__Codes_0) WITH ([value] nvarchar(30) '$') AS [s0]
WHERE [s0].[value] = [s].[Code] OR ([s0].[value] IS NULL AND [s].[Code] IS NULL))