Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Query throws NullReferenceException when global query filter uses null collection on the context #9791

Closed
tplooker opened this issue Sep 13, 2017 · 10 comments

Comments

@tplooker
Copy link

I was using the global query filters for a multi-tennanted system and I noticed if the lambda expression involved in the query fails due to say the TennatId's list being null, then it fails to load the Entity entirely. It was easily solved by initializing the tennantid list before OnModelCreating() but I wondered if there was a way to improve this behavior?

protected override void OnModelCreating(ModelBuilder modelBuilder) { modelBuilder.Entity<Project>().HasQueryFilter(e => !e.IsDeleted && TennantIds.Contains(e.TennantId) && e.IsActive); }

@ajcvickers ajcvickers added this to the 2.1.0 milestone Sep 13, 2017
@smitpatel smitpatel self-assigned this Sep 15, 2017
@smitpatel
Copy link
Contributor

Trying to write a test for this too if it is fixed by #9825

@smitpatel
Copy link
Contributor

Included a test in #9837

The issue here is in client code. The query filter is appending additional where clause. But in a fresh context instance the value of TennantIds is null hence TennantIds.Contains is obvious NullRefException. Either the query filter needs to be safe to evaluate with default value (by putting appropriate null checks) or when running query, make sure to initialize property properly instead of leaving them to default values. Therefore it works when initializing list because default value does not remain null. (hence no NRE).

@ajcvickers
Copy link
Member

@tplooker Were you seeing a null reference exception?

@tplooker
Copy link
Author

@ajcvickers I was getting a NRE on the actual DBSet defined in the dbcontext when I tried to access it after onmodelcreating() so I'm assuming the bad global query filter caused the entity to not load entirely?

@ajcvickers
Copy link
Member

@tplooker Can you post the stack trace? (Essentially, if TennantIds is null when the query is executed, the a null ref exception seems reasonable. However, if it is failing silently, then that seems like something we need to dig into further.)

@tplooker
Copy link
Author

So this is the stack trace I get when running a seed method over the database for entity tennantcategory on startup after onModelCreating() with the tennantID list uninitialized.

at lambda_method(Closure , TennantCategory )
at System.Linq.Enumerable.WhereEnumerableIterator1.MoveNext() at System.Linq.Enumerable.Any[TSource](IEnumerable1 source)
at lambda_method(Closure , QueryContext )
at Microsoft.EntityFrameworkCore.Query.Internal.QueryCompiler.<>c__DisplayClass17_01.<CompileQueryCore>b__0(QueryContext qc) at System.Linq.Queryable.Any[TSource](IQueryable1 source)
at MyTime.Platform.WebAPI.Models.ApplicationDbContextInitializer.d__9.MoveNext() in C:\Users\tlook\Documents\Repositories\MyTime\Platform\WebAPI\Models\ApplicationDbContextInitializer.cs:line 71
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at MyTime.Platform.WebAPI.Startup.Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, IDefaultDbContextInitializer databaseInitializer) in C:\Users\tlook\Documents\Repositories\MyTime\Platform\WebAPI\Startup.cs:line 140

I would have just expected the NRE to originate from onModelCreating() when it was first applying the global query filter featuring an un-initialized list?

@ajcvickers
Copy link
Member

@tplooker Closing this as by-design. Specifically:

  • It's good that OnModelCreating doesn't throw--this is just where the query filter is being defined, not executed.
  • The exception when the query is executed is expected because the property being de-referenced in this case is null and it is not a case where EF would compensate for difference in database/client nulls.

@ajcvickers ajcvickers removed this from the 2.1.0 milestone Sep 18, 2017
@ajcvickers ajcvickers changed the title Global query filter fails silently Query throws NullReferenceException when global query filter uses null collection on the context Sep 18, 2017
@tplooker
Copy link
Author

@ajcvickers Ok thanks, does this mean that if the tennantId list is set after onmodelcreating, the global query filter shouldnt fail and hence the entity would still load?

@ajcvickers
Copy link
Member

@tplooker Yes, that is my understanding.

@tplooker
Copy link
Author

I've just tested it and seen that it does, thanks for clarifying!

@smitpatel smitpatel removed their assignment Jan 12, 2022
@ajcvickers ajcvickers reopened this Oct 16, 2022
@ajcvickers ajcvickers closed this as not planned Won't fix, can't repro, duplicate, stale Oct 16, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants