EF Core 8 OPENJSON Gotcha

November 2023 ยท 2 minute read

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))