Lets say there's a simple class, something like:
internal sealed class Foo
{
public Foo(DateTimeOffset start)
{
Start = start;
}
public DateTimeOffset Start { get; }
}
In the core domain, we want a single "definition" of what it means to having a "started" Foo
. Hence we do something like add a property like public bool IsStarted => Start < DateTimeOffset.UtcNow
to the Foo
class.
However, Foo
also happens to represent an "entity" in a database, meaning we expect to be able to retrieve lists of Foo
using Linq-to-Entities (i.e. Entity Framework).
(I know we may not necessarily be happy with the idea of sharing classes between the core domain and data access layer, but that's beside the point of this question.)
When fetching only those Foo
that "has started", we could go:
var entities = _someDatabaseContext.Foos.Where(foo => foo.Start < DateTimeOffset.UtcNow);
But that would obviously mean duplicating logic, and the "definition" of what it means to be "a started Foo" would be singular no more.
We would rather like to be able to do:
var entities = _someDatabaseContext.Foos.Where(foo => foo.IsStarted);
This, alas, would not translate with Linq-to-Entities, which as of yet has no notion of the "is started" concept.
The question: What would be a good way to encapsulate the definition of "started" for Foo
, in a manner the makes it readily available both in the application domain and at the level of querying the database?
Define an expression to represent the test. Use this expression with Linq-to-Entities, use the compiled delegate for execution.
Expression<Func<Foo, bool>> FooIsStartedPredicateExpression = foo => foo.Start < DateTimeOffset.UtcNow;
Func<Foo, bool> FooIsStartedPredicateDelegate = FooIsStartedPredicateExpression.Compile();
...
Foo someFooVar = ...;
var isStarted = FooIsStartedPredicateDelegate(someFooVar);
var foos = _someDatabaseContext.Foos.Where(FooIsStartedPredicateExpression);