Summary#
s.Contains(x), s.StartsWith(x) and s.EndsWith(x) test a string against another string. They behave exactly like
C#'s String.Contains/StartsWith/EndsWith: an ordinal, literal match. They work on a local string and inside a
query predicate, and they mean the same thing in both.
Signature#
<string>.Contains(<string>) -> bool
<string>.StartsWith(<string>) -> bool
<string>.EndsWith(<string>) -> boolDescription#
The match is literal, not a pattern#
The argument is a plain string. A % or _ in it is an ordinary character — total.Contains("50%") is true only of a
string that actually contains "50%". This mirrors C# (and EF Core, which escapes these characters when it translates
the call to SQL) — there is no wildcard here.
For a WILDCARD search — % for any run of characters, _ for exactly one — use Text.Like, which is a
separate name precisely so the two cannot be confused. It pushes down into a query, and an anchored pattern
("RUSH-%") can use an index.
For full regular expressions on a string you already hold (a validator, a UI action), use Regex. Note it
runs in memory only: a regex inside a query .Where(...) predicate does not compile, because it has no SQL form.
Inside a query the searches that push down are these three literal tests, Text.Like, and — for a [Searchable]
field — full-text .Matches(...).
The match is case-sensitive#
"ACME Ltd".Contains("acme") is false. If you want a case-insensitive search, lower-case both sides:
c.Name.ToLower().Contains("acme")The argument may be computed#
It does not have to be a literal written in the source — a variable, a parameter, or any expression that yields a string works, in every context:
name.StartsWith(prefix) // prefix is a parameter, not a literalOne answer, wherever it runs#
The same expression gives the same result whether it is evaluated on a local string in a browser action, in a function body on the server, or compiled into SQL and run by the database. That is not a coincidence — it is the property the three implementations are tested against each other to hold.
Examples#
entity Order { string Code; }
List<Order> RushOrders() {
return Order.Where(o => o.Code.StartsWith("RUSH-")).ToList();
}
bool MatchesTerm(string note, string term) {
return note.ToLower().Contains(term.ToLower()); // computed argument; lower BOTH sides to ignore case
}See also#
- Text.Like — the WILDCARD search (
%,_), which does push down into a query - Regex — for full regular expressions on an in-hand string (in memory; not usable in a query predicate)
- Text.Split — the other string builtins
- execution side — why this runs in the browser too