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
{{ message }}
Repository navigation
Result of left joining a nullable nominal type should be null (i.e. no instance) and not an instance with all null property values #22517
when Blog does not have a Post, following query does not work in 5.0.0-preview.8.* or 6.0.0-* nightly. but works in 5.0.0-preview.7.*
publicclassBlog{publicintBlogId{get;set;}publicstringUrl{get;set;}[NotMapped]publicPostPost{get;set;}publicList<Post>Posts{get;set;}=newList<Post>();}publicclassPost{publicintPostId{get;set;}publicstringTitle{get;set;}publicstringContent{get;set;}publicintBlogId{get;set;}publicBlogBlog{get;set;}}// this IQueryable would come from other API.vardbPosts=frompindb.Posts// select p;selectnewPost{PostId=p.PostId,BlogId=p.BlogId,Content=p.Content};varquery=fromblogindb.Blogs
join postindbPosts on blog.BlogId equals post.BlogId into postsfromxpostinposts.DefaultIfEmpty()selectnewBlog{Url=blog.Url,Post=xpost};
Unhandled exception. System.InvalidOperationException: Nullable object must have a value.
at lambda_method17(Closure , QueryContext , DbDataReader , ResultContext , SingleQueryResultCoordinator )
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
Further technical details
EF Core version:
Database provider: (e.g. Microsoft.EntityFrameworkCore.Sqlite)
Target framework: (e.g. .NET Core 5.0)
Operating system:
IDE: (e.g. Visual Studio Code)
Reacted by Alexander Leontiev, Stanislav Mazanov, Konstantin Pankov, Vladimir Kuznetsov, Sergey Rumyantsev, Aleksei Kupriianov, Alexey Duzenko, Vadim Pakin, Ruslan Batkaev, Oleg Gladkevich and 50 more
dbug: Microsoft.EntityFrameworkCore.Query[10111]
Compiling query expression:
'DbSet<Blog>()
.GroupJoin(
inner: DbSet<Post>()
.Select(p => new Post{
PostId = p.PostId,
BlogId = p.BlogId,
Content = p.Content
}
),
outerKeySelector: blog => blog.BlogId,
innerKeySelector: post => post.BlogId,
resultSelector: (blog, posts) => new {
blog = blog,
posts = posts
})
.SelectMany(
collectionSelector: <>h__TransparentIdentifier0 => <>h__TransparentIdentifier0.posts
.DefaultIfEmpty(),
resultSelector: (<>h__TransparentIdentifier0, xpost) => new Blog{
Url = <>h__TransparentIdentifier0.blog.Url,
Post = xpost
}
)'
dbug: Microsoft.EntityFrameworkCore.Query[10107]
queryContext => new SingleQueryingEnumerable<Blog>(
(RelationalQueryContext)queryContext,
RelationalCommandCache.SelectExpression(
Projection Mapping:
Url -> 0
Post.PostId -> 1
Post.BlogId -> 2
Post.Content -> 3
SELECT b.Url, p.PostId, p.BlogId, p.Content
FROM Blogs AS b
LEFT JOIN Posts AS p ON b.BlogId == p.BlogId),
Func<QueryContext, DbDataReader, ResultContext, SingleQueryResultCoordinator, Blog>,
EFLeftJoinBug.BloggingContext,
False,
False
)
dbug: Microsoft.EntityFrameworkCore.Database.Command[20103]
Creating DbCommand for 'ExecuteReader'.
dbug: Microsoft.EntityFrameworkCore.Database.Command[20104]
Created DbCommand for 'ExecuteReader' (0ms).
dbug: Microsoft.EntityFrameworkCore.Database.Connection[20000]
Opening connection to database 'Test' on server '(local)'.
dbug: Microsoft.EntityFrameworkCore.Database.Connection[20001]
Opened connection to database 'Test' on server '(local)'.
dbug: Microsoft.EntityFrameworkCore.Database.Command[20100]
Executing DbCommand [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [b].[Url], [p].[PostId], [p].[BlogId], [p].[Content]
FROM [Blogs] AS [b]
LEFT JOIN [Posts] AS [p] ON [b].[BlogId] = [p].[BlogId]
info: Microsoft.EntityFrameworkCore.Database.Command[20101]
Executed DbCommand (7ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
SELECT [b].[Url], [p].[PostId], [p].[BlogId], [p].[Content]
FROM [Blogs] AS [b]
LEFT JOIN [Posts] AS [p] ON [b].[BlogId] = [p].[BlogId]
fail: Microsoft.EntityFrameworkCore.Query[10100]
An exception occurred while iterating over the results of a query for context type 'EFLeftJoinBug.BloggingContext'.
System.InvalidOperationException: Nullable object must have a value.
at lambda_method(Closure , QueryContext , DbDataReader , ResultContext , SingleQueryResultCoordinator )
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
System.InvalidOperationException: Nullable object must have a value.
at lambda_method(Closure , QueryContext , DbDataReader , ResultContext , SingleQueryResultCoordinator )
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
Unhandled exception. System.InvalidOperationException: Nullable object must have a value.
at lambda_method(Closure , QueryContext , DbDataReader , ResultContext , SingleQueryResultCoordinator )
at Microsoft.EntityFrameworkCore.Query.Internal.SingleQueryingEnumerable`1.Enumerator.MoveNext()
at EFLeftJoinBug.Program.Main(String[] args) in /home/ajcvickers/AllTogetherNow/Daily/Daily.cs:line 43
changed the title [-]Nullable object must have a value. SingleQueryResultCoordinator.[/-][+]Nullable object must have a value when left join-ing a nominal type[/+]on Sep 14, 2020
changed the title [-]Nullable object must have a value when left join-ing a nominal type[/-][+]Nullable object must have a value when left joining a nominal type[/+]on Sep 14, 2020
SingleQueryResultCoordinator is not the error. We are probably trying to materialize null into something which is non-nullable which should have been skipped from materialization.
Activity
ajcvickers commentedon Sep 12, 2020
Confirmed this works in 3.1, but fails in latest daily, on SQL Server and SQLite.
smitpatel commentedon Sep 13, 2020
@ajcvickers - What is the generated SQL? Can you post query plan?
ajcvickers commentedon Sep 13, 2020
@smitpatel Here's the logs:
[-]Nullable object must have a value. SingleQueryResultCoordinator.[/-][+]Nullable object must have a value when left join-ing a nominal type[/+][-]Nullable object must have a value when left join-ing a nominal type[/-][+]Nullable object must have a value when left joining a nominal type[/+]smitpatel commentedon Sep 14, 2020
SingleQueryResultCoordinator is not the error. We are probably trying to materialize null into something which is non-nullable which should have been skipped from materialization.
smitpatel commentedon Sep 14, 2020
Note: This gave incorrect result in 3.1.x by initialize post with default values rather than returning null (the result of DefaultIfEmpty).
With #20633 fixed, it now throws error.
Right fix would be not to create instance if no rows matched.
77 remaining items
ajcvickers commentedon Jun 27, 2026
Follow up work after #38479:
All are sub-cases of the umbrella #22517 unless noted.
GroupByapplied after the left join, then whole-object projection (shaper rebuilt viaApplyGrouping). Repro: closed dup DefaultIfEmpty() unsupported in subquery when main query has group by? #28119.Plain inner with no pushdown (no aggregate/filter) via the→ Tracked in Query: whole non-entity object from a plain (non-aggregated) LeftJoin/DefaultIfEmpty inner is not nulled on no-match #38608; not fixed as part of this work. The stated mechanism is a misdiagnosis: nav-expansion folds the plain innerLeftJoinoperator — marker is inlined into the combinedSELECTand never becomesNULL. (no dedicated issue)Selectinto the pending selector, so the marker is never injected (not "inlined"). It can't be fixed in the relational layer — deferred to the nav-expansion rework (Consider removing nav expansion as a way to tackle the pending selector problem #32957 / Rearchitect navigation expansion to happen in translation, not preprocessing #37859).struct/record structwhole-object projection (members not defaulted; materialization throws).record struct/ValueTuplewhole-object projection (fails at translation — a distinct path).Union/ set-operation of two left-join non-entity projections (set-operation translation failure). (no dedicated issue)obj == null/obj != nullon a left-joined non-entity, inWhere/OrderBy(translation failure). A complete Result of left joining a nullable nominal type should be null (i.e. no instance) and not an instance with all null property values #22517 (true null-tracking) would likely enable this. (no dedicated issue)RightJoinwhere the outer (non-entity) side is the nullable one — the marker is injected for the inner side only, so this still throws.Nullable<T>whole-object projection (latent and currently unreachable; the gate skips onIsValueType, butdefault(T?)isnull).Make the dotnet#30915 nullability marker survive a subsequent join
Make the dotnet#30915 nullability marker survive a subsequent join
Default a value-type non-entity left-join projection to default(T) on…
Address PR feedback: fix marker comments and add SqlServer SQL baselines
Default a value-type non-entity left-join projection to default(T) on…
Fold ValueTuple/Tuple member access through constructor-bound project…
Make the nullability marker survive GroupBy-element to-one subquery l…
Address review: guard non-grouping subquery clone, encapsulate marker…
Make the nullability marker survive GroupBy-element to-one subquery l…