dotConnect for MongoDB Documentation
On this page
    Entity Framework Core Database-First Tutorial
    On this page

    Entity Framework Core supports the Database-First approach via the Scaffold-DbContext command of the Package Manager Console and the dotnet ef dbcontext scaffold command of the .NET CLI. These commands scaffold a DbContext and entity type classes for the collections of a MongoDB database.

    This tutorial shows how to create a simple console application powered by Entity Framework Core and dotConnect for MongoDB, using the Database-First approach. In less than 10 minutes, you will have a ready-to-use data access layer for your business objects.

    Requirements

    This tutorial requires the following:

    Creating Sample Data

    MongoDB collections have no fixed schema: dotConnect for MongoDB reads a sample of the documents of each collection (the Describe Amount connection string parameter, 100 by default) and builds the columns of the collection from the fields it finds. Therefore, the collections to scaffold must contain documents.

    Run the following script in mongosh. It creates the sample database with two collections: customers, whose documents hold an embedded document (address), an array of embedded documents (phones), and an array of values (tags), and orders, which refer to the customers by their _id.

    const d = db.getSiblingDB("sample");
    
    const eve = ObjectId();
    const tom = ObjectId();
    d.customers.insertMany([
      {
        _id: eve,
        name: "Eve Adams",
        email: "[email protected]",
        address: { city: "Rome", street: "Via Appia 12" },
        phones: [ { kind: "home", number: "+39 06 1234567" }, { kind: "mobile", number: "+39 333 7654321" } ],
        tags: [ "vip", "newsletter" ]
      },
      {
        _id: tom,
        name: "Tom Baker",
        email: "[email protected]",
        address: { city: "London", street: "Baker Street 221b" },
        phones: [ { kind: "mobile", number: "+44 7700 900123" } ],
        tags: [ "newsletter" ]
      }
    ]);
    
    d.orders.insertMany([
      { customerId: eve, orderDate: ISODate("2026-09-14T10:30:00Z"), total: NumberDecimal("129.90"), quantity: 3, paid: true },
      { customerId: eve, orderDate: ISODate("2026-10-02T16:05:00Z"), total: NumberDecimal("45.00"), quantity: 1, paid: false },
      { customerId: tom, orderDate: ISODate("2026-10-20T08:15:00Z"), total: NumberDecimal("310.50"), quantity: 5, paid: true }
    ]);
    

    Creating a New Project

    1. Open Visual Studio.
    2. On the menu bar, select File > New > Project. The Create a new project dialog opens.
    3. Select Console App (C#, .NET), then click Next.
    4. Enter the project name (ConsoleApplication1) and location, if necessary, then click Next.
    5. Select the framework (.NET 8.0, .NET 10.0, or .NET 11.0), then click Create. A new project is created.

    Installing NuGet Packages

    After creating a new project, add the necessary NuGet packages to it.

    1. On the menu bar, select Tools > NuGet Package Manager > Package Manager Console.
    2. Install the Entity Framework Core tools. For Entity Framework Core 11, run the following command in the Package Manager Console:
      Install-Package Microsoft.EntityFrameworkCore.Tools
      
      For Entity Framework Core 8, 9, or 10, specify the version of the package.
      Install-Package Microsoft.EntityFrameworkCore.Tools -Version 8.0.11
      
    3. Install dotConnect for MongoDB for Entity Framework Core.
      Install-Package Devart.Data.MongoDB.EFCore
      
      The latest version of the package is for Entity Framework Core 11. For Entity Framework Core 8, 9, or 10, specify the version ending with .8, .9, or .10, respectively (for Entity Framework Core 3.1, the version without the suffix).

    If you want to use the .NET CLI, install the Microsoft.EntityFrameworkCore.Design package instead of Microsoft.EntityFrameworkCore.Tools, and the dotnet-ef tool of the same version.

    dotnet add package Devart.Data.MongoDB.EFCore
    dotnet add package Microsoft.EntityFrameworkCore.Design
    dotnet tool install --global dotnet-ef
    

    Creating a Model from the Database

    To create a model from the database, run the Scaffold-DbContext command and pass a connection string and the Devart.Data.MongoDB.EFCore provider as parameters. For example, run the following command in the Package Manager Console:

    Scaffold-DbContext "Host=localhost;Database=sample;User Id=user;Password=pwd;License Key=***" Devart.Data.MongoDB.EFCore -OutputDir Models -Context SampleContext
    

    Alternatively, use the .NET CLI.

    dotnet ef dbcontext scaffold "Host=localhost;Database=sample;User Id=user;Password=pwd;License Key=***" Devart.Data.MongoDB.EFCore -o Models --context SampleContext
    

    If you have other collections in your database, you can use the -Tables parameter (--table for the .NET CLI) to filter the list of collections that are added to the model.

    Scaffold-DbContext "Host=localhost;Database=sample;User Id=user;Password=pwd;License Key=***" Devart.Data.MongoDB.EFCore -OutputDir Models -Context SampleContext -Tables customers,orders
    

    As a result, a context class and entity classes are generated based on the customers and orders collections. The embedded document address becomes the owned type Address, the array of embedded documents phones becomes a collection of the owned type Phone, and the array of values tags becomes List<string>.

    using System;
    using System.Collections.Generic;
    
    namespace ConsoleApplication1.Models;
    
    public partial class Customer
    {
        public string Id { get; set; }
    
        public string Name { get; set; }
    
        public string Email { get; set; }
    
        public List<string> Tags { get; set; } = new List<string>();
    
        public Address Address { get; set; }
    
        public List<Phone> Phones { get; set; } = new List<Phone>();
    }
    using System;
    using System.Collections.Generic;
    
    namespace ConsoleApplication1.Models;
    
    public partial class Address
    {
        public string City { get; set; }
    
        public string Street { get; set; }
    }
    using System;
    using System.Collections.Generic;
    
    namespace ConsoleApplication1.Models;
    
    public partial class Phone
    {
        public string Kind { get; set; }
    
        public string Number { get; set; }
    }
    using System;
    using System.Collections.Generic;
    
    namespace ConsoleApplication1.Models;
    
    public partial class Order
    {
        public string Id { get; set; }
    
        public string CustomerId { get; set; }
    
        public DateTime? OrderDate { get; set; }
    
        public string Total { get; set; }
    
        public int? Quantity { get; set; }
    
        public bool? Paid { get; set; }
    }

    Entity classes are simple classes that represent the data stored in the database. The ObjectId values (_id, customerId) are strings. The Decimal128 field total is a string by default; set the Decimal128 Mapping connection string parameter to get decimal or double instead. Value-type properties are nullable (DateTime?, int?, bool?), since a MongoDB document may lack any field. For the complete list of types, see Entity Framework Core Data Type Mapping.

    The context represents a session with the database and lets you query and save instances of the entity classes.

    using System;
    using System.Collections.Generic;
    using Microsoft.EntityFrameworkCore;
    
    namespace ConsoleApplication1.Models;
    
    public partial class SampleContext : DbContext
    {
        public SampleContext()
        {
        }
    
        public SampleContext(DbContextOptions<SampleContext> options)
            : base(options)
        {
        }
    
        public virtual DbSet<Customer> Customers { get; set; }
    
        public virtual DbSet<Order> Orders { get; set; }
    
        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
    #warning To protect potentially sensitive information in your connection string, you should move it out of source code. You can avoid scaffolding the connection string by using the Name= syntax to read it from configuration - see https://go.microsoft.com/fwlink/?linkid=2131148. For more guidance on storing connection strings, see https://go.microsoft.com/fwlink/?LinkId=723263.
            => optionsBuilder.UseMongoDB("Host=localhost;Database=sample;User Id=user;Password=pwd;License Key=***");
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<Customer>(entity =>
            {
                entity.ToTable("customers");
    
                entity.Property(e => e.Id)
                    .HasColumnType("oid")
                    .HasColumnName("_id");
                entity.Property(e => e.Email)
                    .HasColumnType("varchar")
                    .HasColumnName("email");
                entity.Property(e => e.Name)
                    .HasColumnType("varchar")
                    .HasColumnName("name");
    
                entity.Property(e => e.Tags).HasColumnName("tags");
    
                entity.OwnsOne(e => e.Address, b =>
                {
                    b.ToJson("address");
                    b.Property(p => p.City).HasJsonPropertyName("city");
                    b.Property(p => p.Street).HasJsonPropertyName("street");
                });
    
                entity.OwnsMany(e => e.Phones, b =>
                {
                    b.ToJson("phones");
                    b.Property(p => p.Kind).HasJsonPropertyName("kind");
                    b.Property(p => p.Number).HasJsonPropertyName("number");
                });
            });
    
            modelBuilder.Entity<Order>(entity =>
            {
                entity.ToTable("orders");
    
                entity.Property(e => e.Id)
                    .HasColumnType("oid")
                    .HasColumnName("_id");
                entity.Property(e => e.CustomerId)
                    .HasColumnType("oid")
                    .HasColumnName("customerId");
                entity.Property(e => e.OrderDate).HasColumnName("orderDate");
                entity.Property(e => e.Paid).HasColumnName("paid");
                entity.Property(e => e.Quantity).HasColumnName("quantity");
                entity.Property(e => e.Total)
                    .HasColumnType("decimal128")
                    .HasColumnName("total");
            });
    
            OnModelCreatingPartial(modelBuilder);
        }
    
        partial void OnModelCreatingPartial(ModelBuilder modelBuilder);
    }

    You can comment out or delete the warning about the connection string.

    Now you can use the model to retrieve and modify data.

    Using the Model

    Open your Program.cs file and replace its content with the following code:

    using ConsoleApplication1.Models;
    
    using (var db = new SampleContext())
    {
        // Creating a new customer and saving it to the database
        var customer = new Customer
        {
            Name = "Ann Lee",
            Email = "[email protected]",
            Address = new Address { City = "Rome", Street = "Via Veneto 5" },
            Phones = new List<Phone> { new Phone { Kind = "mobile", Number = "+39 347 1112233" } },
            Tags = new List<string> { "vip" }
        };
        db.Customers.Add(customer);
        var count = db.SaveChanges();
        Console.WriteLine("{0} records saved to database, new _id: {1}", count, customer.Id);
    
        // Retrieving and displaying data
        Console.WriteLine();
        Console.WriteLine("Customers from Rome:");
        foreach (var c in db.Customers.Where(c => c.Address.City == "Rome").OrderBy(c => c.Name))
            Console.WriteLine("{0} | {1} | {2}", c.Name, c.Address.Street, string.Join(", ", c.Tags));
    
        Console.WriteLine();
        Console.WriteLine("VIP customers with a mobile phone:");
        foreach (var c in db.Customers.Where(c => c.Tags.Contains("vip") && c.Phones.Any(p => p.Kind == "mobile")))
            Console.WriteLine("{0} | {1}", c.Name, c.Phones.First(p => p.Kind == "mobile").Number);
    
        Console.WriteLine();
        Console.WriteLine("Paid orders:");
        var paid = from o in db.Orders
                   join c in db.Customers on o.CustomerId equals c.Id
                   where o.Paid == true
                   orderby o.OrderDate
                   select new { c.Name, o.OrderDate, o.Total };
        foreach (var o in paid)
            Console.WriteLine("{0:yyyy-MM-dd} | {1} | {2}", o.OrderDate, o.Name, o.Total);
    }

    The queries filter by a field of the embedded document (c.Address.City), by an element of the array of values (c.Tags.Contains), and by the elements of the array of embedded documents (c.Phones.Any), and join the two collections by the customer ObjectId.

    After this, on the Debug menu, select Start Without Debugging. The application prints the following:

    1 records saved to database, new _id: 6ae3ab107cb0aece7a2bbc7f
    
    Customers from Rome:
    Ann Lee | Via Veneto 5 | vip
    Eve Adams | Via Appia 12 | vip, newsletter
    
    VIP customers with a mobile phone:
    Eve Adams | +39 333 7654321
    Ann Lee | +39 347 1112233
    
    Paid orders:
    2026-09-14 | Eve Adams | 129.90
    2026-10-20 | Tom Baker | 310.50
    

    The _id of the new customer is different on each run.

    See Also