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

Add null propagation/protection logic for InMemory provider. #17485

Merged

Conversation

maumar
Copy link
Contributor

@maumar maumar commented Aug 28, 2019

When we bind to a non-nullable property on entity that can be nullable (e.g. due to left join) we modify the result to be nullable, to avoid "nullable object must have a value" errors. This nullability is then propagated further. We have few blockers:

  • predicates (Where, Any, First, Count, etc): always need to be of type bool. When necessary we add "== true".
  • conditional expression Test: needs to be bool, same as above
  • method call arguments: we can't reliably rewrite methodcall when the arguments types change (generic methods specifically), we convert arguments back to their original types if they were changed to nullable versions.
  • method call caller: if the caller was changed from non-nullable to nullable we still need to call the method with the original type, but we add null check before - caller.Method(args) -> nullable_caller == null ? null : (resultType?)caller.Method(args)
  • selectors (Select, Max etc): we need to preserve the original result type, we use convert
  • anonymous type, array init: we need to preserve the original type, we use convert

Also enable GearsOfWar and ComplexNavigation tests for in memory.

When we bind to a non-nullable property on entity that can be nullable (e.g. due to left join) we modify the result to be nullable, to avoid "nullable object must have a value" errors. This nullability is then propagated further. We have few blockers:
- predicates (Where, Any, First, Count, etc): always need to be of type bool. When necessary we add "== true".
- conditional expression Test: needs to be bool, same as above
- method call arguments: we can't reliably rewrite methodcall when the arguments types change (generic methods specifically), we convert arguments back to their original types if they were changed to nullable versions.
- method call caller: if the caller was changed from non-nullable to nullable we still need to call the method with the original type, but we add null check before - caller.Method(args) -> nullable_caller == null ? null : (resultType?)caller.Method(args)
- selectors (Select, Max etc): we need to preserve the original result type, we use convert
- anonymous type, array init: we need to preserve the original type, we use convert

Also enable GearsOfWar and ComplexNavigation tests for in memory.
@maumar maumar requested a review from smitpatel August 28, 2019 23:59
@@ -52,6 +52,7 @@ protected override Expression VisitMember(MemberExpression memberExpression)
(target, nullable) =>
{
var memberAccessExpression = Expression.MakeMemberAccess(target, memberExpression.Member);

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:trollface:

@smitpatel smitpatel merged commit 25d30bf into smit/defaultIfEmpty Aug 29, 2019
@ghost ghost deleted the in_memory_null_protection_groupby_rebase branch August 29, 2019 05:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants