Overview
Entity Framework Core allows you to work with data in your application without explicitly running database commands. To query your data, use the Language-Integrated Query (LINQ) syntax. LINQ allows you to write strongly typed queries using C#-specific keywords and operators. When you run the application, the EF Core Provider automatically translates the LINQ queries and runs them on the database using the MongoDB Query API.
In this guide you can see examples of common query operations on an application configured to use the EF Core Provider.
Tip
To learn how to configure an application to use the EF Core Provider, see Configure the EF Core Provider.
Sample Data
The examples in this guide use the planets collection from the
sample_guides database. The documents in this collection use the
following Planet class as a model:
public class Planet { public ObjectId _id { get; set; } public string name { get; set; } = null!; public int orderFromSun { get; set; } public bool hasRings { get; set; } }
This collection is from the sample datasets provided by Atlas. See the Quick Start guide to learn how to create a free MongoDB cluster and load this sample data.
Find Entities
Find a single entity by using the FirstOrDefault() method, or find
multiple entities by using the Where() method.
Find a Single Entity
The FirstOrDefault() method returns the first entity it finds in your collection that
matches the search criteria, and returns null if no matching entities
are found.
The following code uses the FirstOrDefault() method to find a planet with
the name field of "Mercury" from a DBSet called Planets and prints
the planet name to the console:
var planet = db.Planets.FirstOrDefault(p => p.name == "Mercury"); Console.WriteLine(planet?.name);
Find Multiple Entities
You can use the Where() method to retrieve multiple entities from your
collections. Where() returns all entities that match the search
criteria.
The following code uses the Where() method to find all planets that have the
hasRings field set to true and prints the planet names to the console.
var planets = db.Planets.Where(p => p.hasRings); foreach (var p in planets) { Console.WriteLine(p.name); }
Query a Shadow Property
A shadow property is a property that isn't defined on your .NET entity class but is included in the Entity Framework model and mapped to fields in the database. You can use shadow properties to query or track data in your documents without exposing it as a property on your entity.
To reference a shadow property in a LINQ query, call the EF.Property<T>() method and
pass the configured property name as an argument. The generic type argument must match the
data type of the shadow property.
For example, the Planet class does not define a property for the mainAtmosphere
field. To configure this field as a shadow property, call the
Property<T>() method in the OnModelCreating() method of
PlanetDbContext, as shown in the following example:
public class PlanetDbContext : DbContext { public DbSet<Planet> Planets { get; init; } = null!; public static PlanetDbContext Create(IMongoDatabase database) => new(new DbContextOptionsBuilder<PlanetDbContext>() .UseMongoDB(database.Client, database.DatabaseNamespace.DatabaseName) .Options); public PlanetDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Planet>().ToCollection("planets"); modelBuilder.Entity<Planet>().Property<string[]>("mainAtmosphere"); } }
The call to modelBuilder.Entity<Planet>().Property<string[]>("mainAtmosphere")
instructs the framework to include mainAtmosphere in the model
and map it to a string[] field in MongoDB.
The following code uses the EF.Property<string[]>() method to find all planets that
have a non-empty mainAtmosphere shadow property and prints the planet
names to the console:
var planets = db.Planets.Where( p => EF.Property<string[]>(p, "mainAtmosphere").Length > 0); foreach (var p in planets) { Console.WriteLine(p.name); }
Sort Entities
Use the OrderBy() method to specify an order in which to return entities
from a query. OrderBy() sorts the elements in ascending order based on a
specified sort criteria.
The following code uses the OrderBy() method to find all planets and sort
them by the value of the orderFromSun field in ascending order. It then
prints the results to the console.
var planetList = db.Planets.OrderBy(p => p.orderFromSun); foreach (var p in planetList) { Console.WriteLine(p.name); }
{"_id":"...","name":"Mercury","orderFromSun":1,"hasRings":false} {"_id":"...","name":"Venus","orderFromSun":2,"hasRings":false} {"_id":"...","name":"Earth","orderFromSun":3,"hasRings":false} {"_id":"...","name":"Mars","orderFromSun":4,"hasRings":false} {"_id":"...","name":"Jupiter","orderFromSun":5,"hasRings":true} {"_id":"...","name":"Saturn","orderFromSun":6,"hasRings":true} {"_id":"...","name":"Uranus","orderFromSun":7,"hasRings":true} {"_id":"...","name":"Neptune","orderFromSun":8,"hasRings":true}
Tip
Sort in Descending Order
You can sort the results of a query in descending order by using the
OrderByDescending() method.
You can perform a secondary sort on your query by using the ThenBy() method. The
ThenBy() method sorts the results of the OrderBy() method in ascending
order based on a specified sort criteria. The ThenBy() method should be
chained to the OrderBy() method.
Tip
Secondary Sort in Descending Order
You can perform a secondary sort in descending order by using the
ThenByDescending() method.
The following code uses the OrderBy() and ThenBy() methods to find all
planets and sort them by the hasRings() field, with a secondary sort
on the name field.
var planetList = db.Planets.OrderBy(o => o.hasRings).ThenBy(o => o.name); foreach (var p in planetList) { Console.WriteLine("Has rings: " + p.hasRings + ", Name: " + p.name); }
{"_id":"...","name":"Earth","orderFromSun":3,"hasRings":false} {"_id":"...","name":"Mars","orderFromSun":4,"hasRings":false} {"_id":"...","name":"Mercury","orderFromSun":1,"hasRings":false} {"_id":"...","name":"Venus","orderFromSun":2,"hasRings":false} {"_id":"...","name":"Jupiter","orderFromSun":5,"hasRings":true} {"_id":"...","name":"Neptune","orderFromSun":8,"hasRings":true} {"_id":"...","name":"Saturn","orderFromSun":6,"hasRings":true} {"_id":"...","name":"Uranus","orderFromSun":7,"hasRings":true}
Tip
When sorting on fields with a boolean value, entities with a field value of
false show before those with a value of true.
Limit the Number of Results
Use the Take() method to specify a maximum number of entities to return from a query.
The following code uses the Take() method to return the first 3 planets from the Planets collection:
var planetList = db.Planets.Take(3); foreach (var p in planetList) { Console.WriteLine(p.name); }
Skip Results
Use the Skip() method to specify a number of entities to skip before returning results from a query.
The following code uses the OrderBy() and Skip() methods to skip the first 5 planets (ordered by orderFromSun) and return the remaining planets:
var planetList = db.Planets.OrderBy(p => p.orderFromSun).Skip(5); foreach (var p in planetList) { Console.WriteLine(p.name); }
Scalar Aggregations
The EF Core Provider supports the following scalar aggregation methods:
Count(): Returns the number of elements in a collection or the number of documents that match a predicateLongCount(): Returns the number of elements in a collection as alongor the number of documents that match a predicateAny(): Returnstrueif any elements in a collection match the predicateMax(): Returns the maximum value of a specified field in a collectionMin(): Returns the minimum value of a specified field in a collectionSum(): Returns the sum of values of a specified field in a collectionAverage(): Returns the average of values of a specified field in a collection
The following sections show examples of each of the preceding methods.
Count
The following example uses the Count() method to count the number of elements in the
Planets collection:
var planetCount = db.Planets.Count(); Console.WriteLine("Planet Count: " + planetCount);
The following example uses the Count() method to count the number of elements in the
Planets collection that have a hasRings field set to true:
var planetCountWithRings = db.Planets.Count(p => p.hasRings); Console.WriteLine("Planet Count with Rings: " + planetCountWithRings);
LongCount
The following example uses the LongCount() method to count the number of
elements in the Planets collection and returns the result as a long:
var planetCountLong = db.Planets.LongCount(); Console.WriteLine("Long Planet Count: " + planetCountLong);
The following example uses the LongCount() method to count the number of
elements in the Planets collection that have a hasRings field set to
true and returns the result as a long:
var planetCountLongWithRings = db.Planets.LongCount(p => p.hasRings); Console.WriteLine("Long Planet Count with Rings: " + planetCountLongWithRings);
Any
The following example uses the Any() method to check if any elements in the
Planets collection have a hasRings field set to true:
var results = db.Planets.Any(p => p.hasRings); Console.WriteLine("Planet with Rings: " + results);
Max
The following example uses the Max() method to find the maximum value of the
orderFromSun field in the Planets collection:
var furthestPlanet = db.Planets.Max(p => p.orderFromSun); Console.WriteLine("Furthest Planet: " + furthestPlanet);
Min
The following example uses the Min() method to find the minimum value of the
orderFromSun field in the Planets collection:
var closestPlanet = db.Planets.Min(p => p.orderFromSun); Console.WriteLine("Closest Planet: " + closestPlanet);
Sum
The following example uses the Sum() method to find the sum of the
orderFromSun field in the Planets collection:
var totalOrderFromSun = db.Planets.Sum(p => p.orderFromSun); Console.WriteLine("Total Order From Sun: " + totalOrderFromSun);
Average
The following example uses the Average() method to find the average value of
the orderFromSun field in the Planets collection:
var averageOrderFromSun = db.Planets.Average(p => p.orderFromSun); Console.WriteLine("Average Order From Sun: " + averageOrderFromSun);
Inspect the Queries Sent to MongoDB
After you write a LINQ query, inspect the generated query to confirm that the provider
is sending the expected shape to MongoDB Server. To inspect
queries during development, enable EF Core logging on your DbContext by using
the LogTo()
method.
The following example shows how to enable logging to the console when creating a
DbContext object:
var mongoClient = new MongoClient("<connection string URI>"); var dbContextOptions = new DbContextOptionsBuilder<MyDbContext>() .UseMongoDB(mongoClient, "<database name>") .LogTo(Console.WriteLine) .Options; var db = new MyDbContext(dbContextOptions);
Enable Sensitive Data Logging
The provider logs full MQL query text only when sensitive data logging is
enabled. If you don't enable sensitive data logging, query logs might omit
values. To enable sensitive data logging, call the
EnableSensitiveDataLogging()
method from your DbContextOptionsBuilder object, as shown in the following
example:
var mongoClient = new MongoClient("<connection string URI>"); var dbContextOptions = new DbContextOptionsBuilder<MyDbContext>() .UseMongoDB(mongoClient, "<database name>") .LogTo(Console.WriteLine) .EnableSensitiveDataLogging() .Options; var db = new MyDbContext(dbContextOptions);
Important
Avoid in Production
Enable sensitive data logging only in development environments.
Custom Serialization Conventions
If you register custom BSON serialization conventions on the MongoClient,
such as camel-case field naming, those conventions can change the field names
stored in MongoDB so that they differ from the property names in your entity
model. The EF Core Provider uses entity property names to generate MQL, so
a mismatch can cause queries to target the wrong fields and bypass any indexes
on those fields. When your stored field names differ from your entity property
names, you can explicitly map a property to its stored field name in
OnModelCreating() by using HasElementName(), as shown in the following
example:
protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Planet>() .Property(p => p.name) .HasElementName("name"); }
Tip
.NET/C# Driver Monitoring APIs
If you need lower-level visibility into MongoDB commands, you can use the
.NET/C# Driver monitoring APIs on your MongoClient object.
To learn more about these APIs, see
Monitoring
in the .NET/C# Driver documentation.
Additional Information
To learn more about aggregations in MongoDB, see the Aggregation Operations guide in the MongoDB Server manual.
To learn more about the EF Core methods discussed in this guide, see the following .NET API documentation links:
To learn more about the .NET/C# Driver methods used on this page, see the following API documentation links:
To learn more about the HasElementName() method, see the following EF Core Provider
API documentation link: