Skip to content

Querying

IContactStore.Query() returns an IQueryable<Contact> that translates LINQ predicates to native queries where possible, with automatic in-memory fallback for unsupported filters.

On Android, predicates are translated to ContentProvider selection queries. On iOS, predicates are translated to CNContact fetch predicates.

var results = contactStore.Query()
.Where(c => c.GivenName.Contains("John"))
.ToList();
var results = contactStore.Query()
.Where(c => c.Phones.Any(p => p.Number.Contains("555")))
.ToList();
var results = contactStore.Query()
.Where(c => c.Emails.Any(e => e.Address.Contains("@example.com")))
.ToList();
var results = contactStore.Query()
.Where(c => c.GivenName.StartsWith("J") && c.FamilyName.Contains("Smith"))
.ToList();
var page = contactStore.Query()
.Where(c => c.FamilyName.StartsWith("A"))
.Skip(10)
.Take(20)
.ToList();
OperationExample
Containsc.GivenName.Contains("John")
StartsWithc.GivenName.StartsWith("J")
EndsWithc.GivenName.EndsWith("son")
Equalsc.GivenName.Equals("John")

These string properties support all four operations above:

  • GivenName
  • FamilyName
  • MiddleName
  • NamePrefix
  • NameSuffix
  • Nickname
  • DisplayName
  • Note

These collections support filtering with .Any():

CollectionFilterable Field
PhonesNumber
EmailsAddress

Returns a sorted, distinct list of uppercase first letters from all contacts’ family names:

var letters = await contactStore.GetFamilyNameFirstLetters();
// ['A', 'B', 'C', 'D', ...]

This is useful for building alphabetical index/jump lists in contact list UIs.

When you write a LINQ query, the library’s expression visitor extracts the predicate and translates it:

  1. Supported filters are converted to native queries (SQL-like selection on Android, NSPredicate on iOS)
  2. Unsupported filters cause a fallback to loading all contacts and filtering in memory
  3. Multiple supported filters are intersected — each filter narrows the result set