Skip to content

Support predicate lowering for conditional expressions in Where #243

Description

@j-d-ha

Summary

Where_conditional_bool_with_value_conversion_is_used currently fails because conditional/ternary expressions in Where predicates are not translated. The immediate failing shape is:

context.Set<Blog>()
    .Where(b => (b.IsVisible ? "Foo" : "Bar") == "Foo")
    .ToListAsync();

Blog.IsVisible uses a value converter (BoolToStringConverter("N", "Y")), so the expected predicate can be reduced to b.IsVisible and emitted as a provider-value comparison such as:

WHERE "IsVisible" = 'Y'

Current behavior

The test fails during query translation with:

The LINQ expression ... could not be translated. Additional information: The predicate could not be translated to DynamoDB PartiQL.

The failure comes from DynamoSqlTranslatingExpressionVisitor.VisitConditional, which currently returns NotTranslatedExpression for every ConditionalExpression.

Proposed approach

Do not generate SQL/PartiQL CASE expressions. DynamoDB PartiQL does not document general CASE WHEN support in its supported subset.

Instead, support conditional expressions in predicate contexts by lowering them into supported boolean logic. For example:

(test ? ifTrue : ifFalse) == value

can be lowered to:

(test && ifTrue == value) || (!test && ifFalse == value)

For the failing bool conversion case, this should simplify to the existing boolean predicate path and preserve value-converter handling:

WHERE "IsVisible" = 'Y'

Scope / guardrails

  • Support useful Where predicate cases via lowering to AND / OR / NOT / comparisons.
  • Preserve type mappings and value converters when comparing lowered branches.
  • Avoid adding broad server-side scalar conditional support unless DynamoDB PartiQL support is verified.
  • Projection conditionals such as Select(b => b.IsVisible ? "Foo" : "Bar") should remain client-side or otherwise be handled separately, not by emitting unsupported CASE.

Tests to consider

  • (b.IsVisible ? "Foo" : "Bar") == "Foo" translates to the visible row and emits a provider-value comparison ("IsVisible" = 'Y').
  • (b.IsVisible ? "Foo" : "Bar") == "Bar" translates to the non-visible row.
  • A non-constant branch case, if an existing model shape supports it, e.g. (test ? propA : propB) == value.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions