Skip to content

EFCore: Set AllowEmptyStrings=true on client for non nullable string properties#575

Merged
Daniel-Svensson merged 5 commits into
OpenRIAServices:mainfrom
Daniel-Svensson:efcore_required
May 13, 2026
Merged

EFCore: Set AllowEmptyStrings=true on client for non nullable string properties#575
Daniel-Svensson merged 5 commits into
OpenRIAServices:mainfrom
Daniel-Svensson:efcore_required

Conversation

@Daniel-Svensson
Copy link
Copy Markdown
Member

@Daniel-Svensson Daniel-Svensson commented May 12, 2026

  • Generate [Required(AllowEmptyStrings=true)] instead of [Required] on client for non nullable string properties
  • It also bumps the package version to 4.1.0.

Summary by CodeRabbit

  • Bug Fixes

    • Validation for required non-nullable string properties now allows empty strings while still requiring a value, making required string validation more flexible.
  • Chores

    • Release version updated to 4.1.0.
  • Documentation

    • Added top-of-file release notes for the 4.1.0 release.

Review Change Stack

@Daniel-Svensson Daniel-Svensson changed the title Efcore required EFCore: Set AllowEmptyStrings=true on client for non nullable string properties May 12, 2026
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 12, 2026

📝 Walkthrough

Walkthrough

This PR makes EF Core codegen emit [Required(AllowEmptyStrings=true)] for required string CLR properties (version bumped to 4.1.0, baselines and changelog updated) and refactors client InvokeResult to expose a non-nullable Value with updated interface forwarding and conversion.

Changes

Required String Attribute Generation

Layer / File(s) Summary
Core generation logic, version bump, and release notes
src/OpenRiaServices.Server.EntityFrameworkCore/Framework/EFCoreTypeDescriptor.cs, src/OpenRiaServices.Server.EntityFrameworkCore/Framework/OpenRiaServices.Server.EntityFrameworkCore.csproj, Changelog.md
EFCoreTypeDescriptor.GetMemberAttributes sets AllowEmptyStrings=true for string properties; project version updated to 4.1.0; changelog documents the client-side change.
Generated baselines: C# EF (Northwind)
src/Test/Desktop/OpenRiaServices.Common.DomainServices.Test/Baselines/Default/EF/Northwind_EFCore.g.cs
Northwind C# generated models update [Required()][Required(AllowEmptyStrings=true)] for Category, Customer, Product, Region, and Territory string/key properties.
Generated baselines: VB EF (Northwind)
src/Test/Desktop/OpenRiaServices.Common.DomainServices.Test/Baselines/Default/EF/Northwind_EFCore.g.vb
Northwind VB generated models update Required()Required(AllowEmptyStrings:=true) for the same properties.
Generated baselines: C# Scenarios (Default)
src/Test/Desktop/OpenRiaServices.Common.DomainServices.Test/Baselines/Default/Scenarios/EFCoreContextScenarios.g.cs
Scenario C# baselines updated to include AllowEmptyStrings=true in Required attributes for several properties.
Generated baselines: VB Scenarios (Default)
src/Test/Desktop/OpenRiaServices.Common.DomainServices.Test/Baselines/Default/Scenarios/EFCoreContextScenarios.g.vb
Scenario VB baselines updated to include AllowEmptyStrings:=true in Required attributes for matching properties.
Generated baselines: C# FullTypeNames
src/Test/Desktop/OpenRiaServices.Common.DomainServices.Test/Baselines/FullTypeNames/Scenarios/EFCoreDbContextScenarios.g.cs
FullTypeNames C# baselines updated RequiredAttribute parameters to allow empty strings for affected properties.
Generated baselines: VB FullTypeNames
src/Test/Desktop/OpenRiaServices.Common.DomainServices.Test/Baselines/FullTypeNames/Scenarios/EFCoreDbContextScenarios.g.vb
FullTypeNames VB baselines updated RequiredAttribute to use AllowEmptyStrings:=true.
Generated baselines: Complex object scenarios (C# & VB)
src/Test/Desktop/OpenRiaServices.Common.DomainServices.Test/Baselines/Default/Scenarios/EFCore_ComplexObject.g.cs, EFCore_ComplexObject.g.vb
Owned/complex-type scenario baselines updated their Required attributes to allow empty strings.

InvokeResult refactor

Layer / File(s) Summary
InvokeResult non-nullable Value and conversions
src/OpenRiaServices.Client/Framework/InvokeResult.cs
IInvokeResult.Value XML docs added; InvokeResult<T> now exposes public T Value { get; } (was nullable/backing field), constructor assigns it, explicit IInvokeResult.Value forwards Value, and implicit conversion operator returns T instead of T?.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 I hopped through code where strings used to sigh,

Now empty and present may sweetly lie.
Versions bumped, baselines tidy and neat,
InvokeResult stands firmer on its feet. 🥕

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title directly and clearly describes the main change: generating [Required(AllowEmptyStrings=true)] instead of [Required] for non-nullable string properties in EFCore client code.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Tip

💬 Introducing Slack Agent: The best way for teams to turn conversations into code.

Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.

  • Generate code and open pull requests
  • Plan features and break down work
  • Investigate incidents and troubleshoot customer tickets together
  • Automate recurring tasks and respond to alerts with triggers
  • Summarize progress and report instantly

Built for teams:

  • Shared memory across your entire org—no repeating context
  • Per-thread sandboxes to safely plan and execute work
  • Governance built-in—scoped access, auditability, and budget controls

One agent for your entire SDLC. Right inside Slack.

👉 Get started


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@Daniel-Svensson Daniel-Svensson marked this pull request as ready for review May 12, 2026 16:53
@Daniel-Svensson Daniel-Svensson requested a review from Copilot May 12, 2026 16:53
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Updates EF Core metadata inference so client proxies generate [Required(AllowEmptyStrings=true)] for non-nullable string properties (aligning “required” with non-null rather than non-empty), and bumps the EF Core integration package version to 4.1.0.

Changes:

  • Infer RequiredAttribute with AllowEmptyStrings=true for non-nullable string properties in the EF Core type descriptor.
  • Update generated baseline files (C# / VB) to reflect the new [Required(AllowEmptyStrings=true)] output.
  • Bump OpenRiaServices.Server.EntityFrameworkCore package/assembly version to 4.1.0 and add a changelog entry.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
src/OpenRiaServices.Server.EntityFrameworkCore/Framework/EFCoreTypeDescriptor.cs Changes inferred RequiredAttribute to allow empty strings for string properties.
src/OpenRiaServices.Server.EntityFrameworkCore/Framework/OpenRiaServices.Server.EntityFrameworkCore.csproj Bumps VersionPrefix/AssemblyVersion to 4.1.0.
Changelog.md Adds release note entry for the change/version.
src/Test/Desktop/OpenRiaServices.Common.DomainServices.Test/Baselines/FullTypeNames/Scenarios/EFCoreDbContextScenarios.g.cs Baseline update for generated [Required(AllowEmptyStrings=true)].
src/Test/Desktop/OpenRiaServices.Common.DomainServices.Test/Baselines/FullTypeNames/Scenarios/EFCoreDbContextScenarios.g.vb Baseline update for generated RequiredAttribute(AllowEmptyStrings:=true).
src/Test/Desktop/OpenRiaServices.Common.DomainServices.Test/Baselines/Default/Scenarios/EFCoreContextScenarios.g.cs Baseline update for generated [Required(AllowEmptyStrings=true)].
src/Test/Desktop/OpenRiaServices.Common.DomainServices.Test/Baselines/Default/Scenarios/EFCoreContextScenarios.g.vb Baseline update for generated Required(AllowEmptyStrings:=true).
src/Test/Desktop/OpenRiaServices.Common.DomainServices.Test/Baselines/Default/EF/Northwind_EFCore.g.cs Baseline update for generated [Required(AllowEmptyStrings=true)].
src/Test/Desktop/OpenRiaServices.Common.DomainServices.Test/Baselines/Default/EF/Northwind_EFCore.g.vb Baseline update for generated Required(AllowEmptyStrings:=true).

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Changelog.md
@Daniel-Svensson
Copy link
Copy Markdown
Member Author

@copilot can you fix the failing test (DomainServices.TestClientCodegen_EFCore_ComplexObject) ?

You will need to
1.. build the solution
2. Run the codegen tests in OpenRiaServices.Tools.Test.CodeGen
and follow the instructions in the tests output (it will tell you to run a .bat file to update test baselines).
4. Commit and push the updated baseline

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/OpenRiaServices.Client/Framework/InvokeResult.cs (1)

37-60: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Add InvokeResult nullability change to the 4.1.0 changelog.

The changelog for EF Core 4.1.0 documents the AllowEmptyStrings=true codegen change but does not mention the InvokeResult<T> public API nullability tightening introduced in this PR:

  • Value property: T?T
  • Implicit operator: returns T?T

This is a source-level breaking change for nullable-reference-type-aware consumers, who will receive "always true" / nullable-mismatch diagnostics on existing null checks. Add an entry to Changelog.md under the 4.1.0 section documenting this change (the runtime behavior is unchanged, but the typed contract is now stricter).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/OpenRiaServices.Client/Framework/InvokeResult.cs` around lines 37 - 60,
Update Changelog.md under the 4.1.0 section to document the source-level
nullability tightening for InvokeResult<T>: note that the public Value property
changed from T? to T and the implicit operator on InvokeResult<T> now returns T
(was T?), explain this is a nullable-reference-type breaking change for
source-level consumers (nullable-mismatch diagnostics) while runtime behavior is
unchanged; reference the symbols InvokeResult<T>.Value and the implicit operator
on InvokeResult<T> so reviewers can locate the API change.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@src/OpenRiaServices.Client/Framework/InvokeResult.cs`:
- Around line 37-60: Update Changelog.md under the 4.1.0 section to document the
source-level nullability tightening for InvokeResult<T>: note that the public
Value property changed from T? to T and the implicit operator on InvokeResult<T>
now returns T (was T?), explain this is a nullable-reference-type breaking
change for source-level consumers (nullable-mismatch diagnostics) while runtime
behavior is unchanged; reference the symbols InvokeResult<T>.Value and the
implicit operator on InvokeResult<T> so reviewers can locate the API change.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 943c24eb-33f5-4d0e-842f-d1378e06d172

📥 Commits

Reviewing files that changed from the base of the PR and between b4c0ab2 and bcb2aa2.

📒 Files selected for processing (3)
  • src/OpenRiaServices.Client/Framework/InvokeResult.cs
  • src/Test/Desktop/OpenRiaServices.Common.DomainServices.Test/Baselines/Default/Scenarios/EFCore_ComplexObject.g.cs
  • src/Test/Desktop/OpenRiaServices.Common.DomainServices.Test/Baselines/Default/Scenarios/EFCore_ComplexObject.g.vb

@sonarqubecloud
Copy link
Copy Markdown

@Daniel-Svensson Daniel-Svensson enabled auto-merge (squash) May 13, 2026 06:28
@Daniel-Svensson Daniel-Svensson merged commit 46ad68a into OpenRIAServices:main May 13, 2026
7 checks passed
@Daniel-Svensson Daniel-Svensson deleted the efcore_required branch May 13, 2026 06:29
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.

3 participants