Overview
In this guide, you can learn how to use the MongoDB Entity Framework Core Provider to model relationships among documents in your MongoDB database. The EF Core Provider supports the following relationship types:
Embedded Relationships: Subdocuments embedded directly within a parent document. This is the recommended approach for one-to-one and one-to-many relationships in MongoDB.
Manual References: A document that references another document by storing its ID in a field, instead of embedding the document as a subdocument. This approach works well for modeling many-to-many relationships or when you need to access the documents independently.
Embedded Relationships
To embed a subdocument in a parent document, specify the model for the embedded document as an owned entity. Embedded relationships are the MongoDB-native way to model relationships and offer better performance for documents that you frequently access together.
You can designate an owned entity in the following ways:
[Owned] Attribute: Apply the
[Owned]data annotation attribute to the model class for the subdocument. This approach is declarative and concise, but also less flexible, because it applies globally to all usages of the owned type.Fluent API: Call the
OwnsOne()orOwnsMany()methods in yourDbContextconfiguration. This approach offers more control and flexibility, allowing you to configure the relationship differently for specific entities without modifying the model class.
The following sections provide examples of these approaches for modeling single and multiple owned entities.
One Owned Entity
To embed a single document within a parent document, call the OwnsOne()
method in your DbContext configuration or apply the [Owned] attribute
to the embedded class.
The following example shows a Customer entity that contains an embedded
Address document. Select the [Owned] Attribute or
Fluent API tab to see the corresponding syntax:
[] public class Address { public string Street { get; set; } = null!; public string City { get; set; } = null!; public string Country { get; set; } = null!; } public class Customer { public ObjectId Id { get; set; } public string Name { get; set; } = null!; public Address Address { get; set; } = null!; }
public class CustomerDbContext : DbContext { public DbSet<Customer> Customers { get; set; } = null!; public CustomerDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<Customer>(c => { c.OwnsOne(c => c.Address); c.ToCollection("customers"); }); } }
When you save a Customer entity, MongoDB stores the Address as an embedded
document within the Customer document. The following JSON shows how this relationship
appears in MongoDB:
{ "_id": ObjectId("..."), "Name": "John Doe", "Address": { "Street": "123 Main St", "City": "New York", "Country": "USA" } }
Multiple Owned Entities
To embed multiple documents in a parent document, call the OwnsMany()
method or apply the [Owned] attribute to the embedded class and define a
collection property.
The following example shows a Customer entity that contains multiple
embedded Order documents. Select the [Owned] Attribute or
Fluent API tab to see the corresponding syntax:
[] public class Order { public string Product { get; set; } = null!; public int Quantity { get; set; } } public class CustomerWithOrders { public ObjectId Id { get; set; } public string Name { get; set; } = null!; public List<Order> Orders { get; set; } = new(); }
public class OrderDbContext : DbContext { public DbSet<CustomerWithOrders> Customers { get; set; } = null!; public OrderDbContext(DbContextOptions options) : base(options) { } protected override void OnModelCreating(ModelBuilder modelBuilder) { base.OnModelCreating(modelBuilder); modelBuilder.Entity<CustomerWithOrders>(c => { c.OwnsMany(c => c.Orders); c.ToCollection("customers"); }); } }
When you save a CustomerWithOrders entity, MongoDB stores the Orders as an array of
embedded documents, as shown in the following JSON:
{ "_id": ObjectId("..."), "Name": "Jane Smith", "Orders": [ { "Product": "Laptop", "Quantity": 1 }, { "Product": "Mouse", "Quantity": 2 } ] }
Manual References
To model relationships among entities that aren't embedded, you can store references manually by saving the ID of one document in a field of another document. This approach requires you to manage the relationship in your application code.
The following example shows how to store a reference to a related entity:
public class Author { public ObjectId Id { get; set; } public string Name { get; set; } = null!; } public class Book { public ObjectId Id { get; set; } public string Title { get; set; } = null!; // Store reference to Author by storing the Author's Id public ObjectId AuthorId { get; set; } }
To retrieve the related entity, you must query the referenced collection separately, as shown in the following example:
// Query a book and its author var book = db.Books.FirstOrDefault(b => b.Title == "My Book"); var author = db.Authors.FirstOrDefault(a => a.Id == book!.AuthorId);
Additional Information
To learn more about modeling data in MongoDB, see Data Modeling in the MongoDB Server documentation.
To learn more about owned entity types in Entity Framework Core, see Owned Entity Types in the Microsoft Entity Framework Core documentation.
API Documentation
To learn more about the methods and types discussed in this guide, see the following Microsoft API documentation: