To be clear you can get a long way by abusing EF's willingness to try and interpret arbitrarily complex expressions - it just provides zero tooling or guidance on how to build those expressions.
Or projections. It's possible to write a reusable projection for EF like so:
class MyTableProjection {
public static Expression<Func<MyTable, MyTableProjection>> Expression =>
t => new MyTableProjection {
Id = t.Id,
Str = t.Str,
Flag = t.Flag
};
public int Id { get; init; }
public string Str { get; init; }
public bool Flag { get; init; }
}
dbContext.MyTable
.Where(...)
.Select(MyProjection.Expression)
.ToListAsync()
But I have never seen anyone do this because it breaks the promise that you magically won't have to write any code or abstractions.[1] https://github.com/scottksmith95/LINQKit [2] http://www.albahari.com/nutshell/predicatebuilder.aspx
Re: Composability
You can generate something like the WHERE clause of a query in a function and return it alone (rather than as a SELECT query) or even combine it with another WHERE.
e.g. In SA the "select" and "where" portions aren't tightly coupled.
Re: Expressivity
Right now you can easily build up ef.core queries by chaining IQueryable.Where, which is nice but you can only do that for selects and something like OR conditions are difficult to implement.
e.g. in SA you can just pass a list of predicates to the or_() function.
e.g. in SA you can build a WHERE clause and then pass the same clause to a select or a bulk operation.