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
Improve UseMemberBody and add new diagnostics (#174)
* Improve UseMemberBody and add new diagnostics
Fixes#134
* Fix diagnostic reports with Expression member bodies
* Handle explicit getters for UseMemberBody
* Split ProjectableInterpreter class file
* Fix extension methdods resolving and fix docs
-keeparegularC# implementationforin-memoryusewhilemaintainingaseparate, cleanerexpressionfor EF Core
324
+
- supply the body as a pre-built `Expression<Func<...>>` property for full control over the generated tree
325
+
326
+
##### Delegating to a method or property body
327
+
328
+
The simplest case — point `UseMemberBody` at another method or property that has the **same return type and parameter signature**. The generator uses the body of the target member instead:
329
+
330
+
```csharp
331
+
public class Entity
332
+
{
333
+
public int Id { get; set; }
334
+
335
+
// EF-side: generates an expression from ComputedImpl
336
+
[Projectable(UseMemberBody=nameof(ComputedImpl))]
337
+
publicintComputed=>Id; // original body is ignored
338
+
339
+
// In-memory implementation (or a different algorithm)
340
+
privateintComputedImpl=>Id*2;
341
+
}
342
+
```
343
+
344
+
The generated expression is `(@this) => @this.Id * 2`, so `Computed` projects as `Id * 2` in SQL even though the arrow body says `Id`.
345
+
346
+
##### Using an `Expression<Func<...>>` property as the body
347
+
348
+
For even more control you can supply the body as a typed `Expression<Func<...>>` property. This lets you write the expression once and reuse it from both the `[Projectable]` member and any runtime code that needs the expression tree directly:
349
+
350
+
```csharp
351
+
publicclassEntity
352
+
{
353
+
publicintId { get; set; }
354
+
355
+
[Projectable(UseMemberBody=nameof(Computed4))]
356
+
publicintComputed3=>Id; // body is replaced at compile time
357
+
358
+
// The expression tree is picked up by the generator and by the runtime resolver
> **Note:** When the projectable member is a *property*, the `Expression<Func<...>>` property body is handled entirely by the runtime resolver — no extra source is generated. This works transparently.
364
+
365
+
For **instance methods**, name the lambda parameter `@this` so that it matches the generator's own naming convention:
The generated expression is `(Foo a, Foo b) => a.Name == b.Name` — the same lambda that EF Core receives at query time. The two implementations are kept in sync in one place.
|**EFP0010**| Error | The name given to `UseMemberBody` does not match any member on the containing type |
401
+
|**EFP0011**| Error | A member with that name exists but its type or signature is incompatible with the projectable member |
402
+
317
403
#### Can I use pattern matching in projectable members?
318
404
319
405
Yes! As of version 6.x, the generator supports a rich set of C# pattern-matching constructs and rewrites them into expression-tree-compatible ternary/binary expressions that EF Core can translate to SQL CASE expressions.
0 commit comments