{"id":48644,"date":"2023-11-02T08:00:00","date_gmt":"2023-11-02T15:00:00","guid":{"rendered":"https:\/\/devblogs.microsoft.com\/dotnet\/?p=48644"},"modified":"2023-11-03T15:02:05","modified_gmt":"2023-11-03T22:02:05","slug":"efcore-mongodb","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/dotnet\/efcore-mongodb\/","title":{"rendered":"Trying out MongoDB with EF Core using Testcontainers"},"content":{"rendered":"<p>Helping developers use both relational <em>and non-relational<\/em> databases effectively was one of the original tenets of EF Core. To this end, there has been an <a href=\"https:\/\/learn.microsoft.com\/ef\/core\/providers\/cosmos\/\">EF Core database provider for Azure Cosmos DB document databases<\/a> for many years now. Recently, the EF Core team has been collaborating with engineers from <a href=\"https:\/\/www.mongodb.com\/\">MongoDB<\/a> to bring support for MongoDB to EF Core. The initial result of this collaboration is the first <a href=\"https:\/\/www.mongodb.com\/blog\/post\/mongodb-provider-entity-framework-core-now-available-public-preview\">preview release of the MongoDB provider for EF Core<\/a>.<\/p>\n<p>In this post, we will try out <a href=\"https:\/\/github.com\/mongodb\/mongo-efcore-provider\">the MongoDB provider<\/a> for EF Core by using it to:<\/p>\n<ul>\n<li>Map a C# object model to documents in a MongoDB database<\/li>\n<li>Use EF to save some documents to the database<\/li>\n<li>Write LINQ queries to retrieve documents from the database<\/li>\n<li>Make changes to a document and use EF\u2019s change tracking to update the document<\/li>\n<\/ul>\n<p>The code shown in this post <a href=\"https:\/\/github.com\/ajcvickers\/MongoTestApp\">can be found on GitHub<\/a>.<\/p>\n<h2>Testcontainers<\/h2>\n<p>It\u2019s very easy to <a href=\"https:\/\/www.mongodb.com\/atlas\/database\">get a MongoDB database in the cloud<\/a> that you can use to try things out. However, <a href=\"https:\/\/testcontainers.com\/\">Testcontainers<\/a> is another way to test code with different database systems which is particularly suited to:<\/p>\n<ul>\n<li>Running automated tests against the database<\/li>\n<li>Creating standalone reproductions when reporting issues<\/li>\n<li>Trying out new things with minimal setup<\/li>\n<\/ul>\n<p>Testcontainers are distributed as NuGet packages that take care of running a container containing a configured ready-to-use database system. The containers use Docker or a Docker-alternative to run, so this may need to be installed on your machine if you don\u2019t already have it. See <a href=\"https:\/\/dotnet.testcontainers.org\/\"><em>Welcome to Testcontainers for .NET!<\/em><\/a> for more details. Other than starting Docker, you don&#8217;t need to do anything else except import the NuGet package.<\/p>\n<h2>The C# project<\/h2>\n<p>We&#8217;ll use a simple console application to try out MongoDB with EF Core. This project needs two package references:<\/p>\n<ul>\n<li><a href=\"https:\/\/www.nuget.org\/packages\/MongoDB.EntityFrameworkCore\">MongoDB.EntityFrameworkCore<\/a> to install the EF Core provider. This package also transitives installs the common EF Core packages and the <a href=\"https:\/\/www.nuget.org\/packages\/MongoDB.Driver\/\">MongoDB.Driver<\/a> package which is used by the EF Provider to access the MongoDB database.<\/li>\n<li><a href=\"https:\/\/www.nuget.org\/packages\/Testcontainers.MongoDb\">Testcontainers.MongoDb<\/a> to install the pre-defined Testcontainer for MongoDB.<\/li>\n<\/ul>\n<p>The full <code>csproj<\/code> file looks like this:<\/p>\n<pre><code class=\"language-xml\">&lt;Project Sdk=\"Microsoft.NET.Sdk\"&gt;\r\n\r\n    &lt;PropertyGroup&gt;\r\n        &lt;OutputType&gt;Exe&lt;\/OutputType&gt;\r\n        &lt;TargetFramework&gt;net7.0&lt;\/TargetFramework&gt;\r\n        &lt;ImplicitUsings&gt;enable&lt;\/ImplicitUsings&gt;\r\n        &lt;Nullable&gt;enable&lt;\/Nullable&gt;\r\n        &lt;RootNamespace \/&gt;\r\n    &lt;\/PropertyGroup&gt;\r\n\r\n    &lt;ItemGroup&gt;\r\n        &lt;PackageReference Include=\"Testcontainers.MongoDB\" Version=\"3.5.0\" \/&gt;\r\n        &lt;PackageReference Include=\"MongoDB.EntityFrameworkCore\" Version=\"7.0.0-preview.1\" \/&gt;\r\n    &lt;\/ItemGroup&gt;\r\n\r\n&lt;\/Project&gt;<\/code><\/pre>\n<p>Remember, the full project is available to <a href=\"https:\/\/github.com\/ajcvickers\/MongoTestApp\">download from GitHUb<\/a>.<\/p>\n<h2>The object model<\/h2>\n<p>We&#8217;ll map a simple object model of customers and their addresses:<\/p>\n<pre><code class=\"language-csharp\">public class Customer\r\n{\r\n    public Guid Id { get; set; }\r\n    public required string Name { get; set; }\r\n    public required Species Species { get; set; }\r\n    public required ContactInfo ContactInfo { get; set; }\r\n}\r\n\r\npublic class ContactInfo\r\n{\r\n    public required Address ShippingAddress { get; set; }\r\n    public Address? BillingAddress { get; set; }\r\n    public required PhoneNumbers Phones { get; set; }\r\n}\r\n\r\npublic class PhoneNumbers\r\n{\r\n    public PhoneNumber? HomePhone { get; set; }\r\n    public PhoneNumber? WorkPhone { get; set; }\r\n    public PhoneNumber? MobilePhone { get; set; }\r\n}\r\n\r\npublic class PhoneNumber\r\n{\r\n    public required int CountryCode { get; set; }\r\n    public required string Number { get; set; }\r\n}\r\n\r\npublic class Address\r\n{\r\n    public required string Line1 { get; set; }\r\n    public string? Line2 { get; set; }\r\n    public string? Line3 { get; set; }\r\n    public required string City { get; set; }\r\n    public required string Country { get; set; }\r\n    public required string PostalCode { get; set; }\r\n}\r\n\r\npublic enum Species\r\n{\r\n    Human,\r\n    Dog,\r\n    Cat\r\n}<\/code><\/pre>\n<p>Since MongoDB works with documents, we&#8217;re going to map this model to a top level Customer document, with the addresses and phone numbers embedded in this document. We&#8217;ll see how to do this in the next section.<\/p>\n<h2>Creating the EF model<\/h2>\n<p>EF works by <a href=\"https:\/\/learn.microsoft.com\/ef\/core\/modeling\/\">building a model of the mapped CLR types<\/a>, such as those for <code>Customer<\/code>, etc. in the previous section. This model defines the relationships between types in the model, as well as how each type maps to the database.<\/p>\n<p>Luckily there is not much to do here, since EF uses a set of model building conventions that generate a model based on input from both the model types and the database provider. This means that for relational databases, each type gets mapped to a different table by convention. For document databases like Azure CosmosDB and now MongoDB, only the top-level type (<code>Customer<\/code> in our example) is mapped to its own document. Other types referenced from the top-level types are, by-convention, included in the main document.<\/p>\n<p>This means that the only thing EF needs to know to build a model is the top-level type, and that the MongoDB provider should be used. We do this by defining a type that extends from <code>DbContext<\/code>. For example:<\/p>\n<pre><code class=\"language-csharp\">public class CustomersContext : DbContext\r\n{\r\n    private readonly MongoClient _client;\r\n\r\n    public CustomersContext(MongoClient client)\r\n    {\r\n        _client = client;\r\n    }\r\n\r\n    protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)\r\n        =&gt; optionsBuilder.UseMongoDB(_client, \"efsample\");\r\n\r\n    public DbSet&lt;Customer&gt; Customers =&gt; Set&lt;Customer&gt;();\r\n}<\/code><\/pre>\n<p>In this <code>DbContext<\/code> class:<\/p>\n<ul>\n<li><code>UseMongoDB<\/code> is called, passing in the client driver and the database name. This tells EF Core to use the MongoDB provider when building the model and accessing the database.<\/li>\n<li>A <code>DbSet&lt;Customer&gt;<\/code> property that defines the top-level type for which documents should be modeled.<\/li>\n<\/ul>\n<p>We&#8217;ll see later how to create the <code>MongoClient<\/code> instance and use the <code>DbContext<\/code>. When we do, examining the <a href=\"https:\/\/learn.microsoft.com\/ef\/core\/modeling\/#debug-view\">model DebugView<\/a> shows this:<\/p>\n<pre><code class=\"language-text\">Model: \r\n  EntityType: ContactInfo Owned\r\n    Properties:\r\n      CustomerId (no field, Guid) Shadow Required PK FK AfterSave:Throw\r\n    Navigations:\r\n      BillingAddress (Address) ToDependent ContactInfo.BillingAddress#Address (Address)\r\n      Phones (PhoneNumbers) ToDependent PhoneNumbers\r\n      ShippingAddress (Address) ToDependent ContactInfo.ShippingAddress#Address (Address)\r\n    Keys:\r\n      CustomerId PK\r\n    Foreign keys:\r\n      ContactInfo {'CustomerId'} -&gt; Customer {'Id'} Unique Ownership ToDependent: ContactInfo Cascade\r\n  EntityType: ContactInfo.BillingAddress#Address (Address) CLR Type: Address Owned\r\n    Properties:\r\n      ContactInfoCustomerId (no field, Guid) Shadow Required PK FK AfterSave:Throw\r\n      City (string) Required\r\n      Country (string) Required\r\n      Line1 (string) Required\r\n      Line2 (string)\r\n      Line3 (string)\r\n      PostalCode (string) Required\r\n    Keys:\r\n      ContactInfoCustomerId PK\r\n    Foreign keys:\r\n      ContactInfo.BillingAddress#Address (Address) {'ContactInfoCustomerId'} -&gt; ContactInfo {'CustomerId'} Unique Ownership ToDependent: BillingAddress Cascade\r\n  EntityType: ContactInfo.ShippingAddress#Address (Address) CLR Type: Address Owned\r\n    Properties:\r\n      ContactInfoCustomerId (no field, Guid) Shadow Required PK FK AfterSave:Throw\r\n      City (string) Required\r\n      Country (string) Required\r\n      Line1 (string) Required\r\n      Line2 (string)\r\n      Line3 (string)\r\n      PostalCode (string) Required\r\n    Keys:\r\n      ContactInfoCustomerId PK\r\n    Foreign keys:\r\n      ContactInfo.ShippingAddress#Address (Address) {'ContactInfoCustomerId'} -&gt; ContactInfo {'CustomerId'} Unique Ownership ToDependent: ShippingAddress Cascade\r\n  EntityType: Customer\r\n    Properties:\r\n      Id (Guid) Required PK AfterSave:Throw ValueGenerated.OnAdd\r\n      Name (string) Required\r\n      Species (Species) Required\r\n    Navigations:\r\n      ContactInfo (ContactInfo) ToDependent ContactInfo\r\n    Keys:\r\n      Id PK\r\n  EntityType: PhoneNumbers Owned\r\n    Properties:\r\n      ContactInfoCustomerId (no field, Guid) Shadow Required PK FK AfterSave:Throw\r\n    Navigations:\r\n      HomePhone (PhoneNumber) ToDependent PhoneNumbers.HomePhone#PhoneNumber (PhoneNumber)\r\n      MobilePhone (PhoneNumber) ToDependent PhoneNumbers.MobilePhone#PhoneNumber (PhoneNumber)\r\n      WorkPhone (PhoneNumber) ToDependent PhoneNumbers.WorkPhone#PhoneNumber (PhoneNumber)\r\n    Keys:\r\n      ContactInfoCustomerId PK\r\n    Foreign keys:\r\n      PhoneNumbers {'ContactInfoCustomerId'} -&gt; ContactInfo {'CustomerId'} Unique Ownership ToDependent: Phones Cascade\r\n  EntityType: PhoneNumbers.HomePhone#PhoneNumber (PhoneNumber) CLR Type: PhoneNumber Owned\r\n    Properties:\r\n      PhoneNumbersContactInfoCustomerId (no field, Guid) Shadow Required PK FK AfterSave:Throw\r\n      CountryCode (int) Required\r\n      Number (string) Required\r\n    Keys:\r\n      PhoneNumbersContactInfoCustomerId PK\r\n    Foreign keys:\r\n      PhoneNumbers.HomePhone#PhoneNumber (PhoneNumber) {'PhoneNumbersContactInfoCustomerId'} -&gt; PhoneNumbers {'ContactInfoCustomerId'} Unique Ownership ToDependent: HomePhone Cascade\r\n  EntityType: PhoneNumbers.MobilePhone#PhoneNumber (PhoneNumber) CLR Type: PhoneNumber Owned\r\n    Properties:\r\n      PhoneNumbersContactInfoCustomerId (no field, Guid) Shadow Required PK FK AfterSave:Throw\r\n      CountryCode (int) Required\r\n      Number (string) Required\r\n    Keys:\r\n      PhoneNumbersContactInfoCustomerId PK\r\n    Foreign keys:\r\n      PhoneNumbers.MobilePhone#PhoneNumber (PhoneNumber) {'PhoneNumbersContactInfoCustomerId'} -&gt; PhoneNumbers {'ContactInfoCustomerId'} Unique Ownership ToDependent: MobilePhone Cascade\r\n  EntityType: PhoneNumbers.WorkPhone#PhoneNumber (PhoneNumber) CLR Type: PhoneNumber Owned\r\n    Properties:\r\n      PhoneNumbersContactInfoCustomerId (no field, Guid) Shadow Required PK FK AfterSave:Throw\r\n      CountryCode (int) Required\r\n      Number (string) Required\r\n    Keys:\r\n      PhoneNumbersContactInfoCustomerId PK\r\n    Foreign keys:\r\n      PhoneNumbers.WorkPhone#PhoneNumber (PhoneNumber) {'PhoneNumbersContactInfoCustomerId'} -&gt; PhoneNumbers {'ContactInfoCustomerId'} Unique Ownership ToDependent: WorkPhone Cascade<\/code><\/pre>\n<p>Looking at this model, it can be seen that EF created <a href=\"https:\/\/learn.microsoft.com\/ef\/core\/modeling\/owned-entities\">owned entity types<\/a> for the <code>ContactInfo<\/code>, <code>Address<\/code>, <code>PhoneNumber<\/code> and <code>PhoneNumbers<\/code> types, even though only the <code>Customer<\/code> type was referenced directly from the <code>DbContext<\/code>. These other types were discovered and configured by the model-building conventions.<\/p>\n<h2>Create the MongoDB test container<\/h2>\n<p>We now have a model and a <code>DbContext<\/code>. Next we need an actual MongoDB database, and this is where Testcontainers come in. There are Testcontainers available for many different types of database, and they all work in a very similar way. That is, a container is created using the appropriate <code>DbBuilder<\/code>, and then that container is started. For example:<\/p>\n<pre><code class=\"language-csharp\">await using var mongoContainer = new MongoDbBuilder()\r\n    .WithImage(\"mongo:6.0\")\r\n    .Build();\r\n\r\nawait mongoContainer.StartAsync();<\/code><\/pre>\n<p>And that&#8217;s it! We now have a configured, clean MongoDB instance running locally with which we can do what we wish, before just throwing it away.<\/p>\n<h2>Save data to MongoDB<\/h2>\n<p>Let&#8217;s use EF Core to write some data to the MongoDB database. To do this, we&#8217;ll need to create a <code>DbContext<\/code> instance, and for this we need a <code>MongoClient<\/code> instance from the underlying MongoDB driver. Often, in a real app, the <code>MongoClient<\/code> instance and the <code>DbContext<\/code> instance will be obtained using dependency injection. For the sake of simplicity, we&#8217;ll just <code>new<\/code> them up here:<\/p>\n<pre><code class=\"language-csharp\">var mongoClient = new MongoClient(mongoContainer.GetConnectionString());\r\n\r\nawait using (var context = new CustomersContext(mongoClient))\r\n{\r\n    \/\/ ...\r\n}<\/code><\/pre>\n<p>Notice that the Testcontainer instance provides the connection string we need to connect to our MongoDB test database.<\/p>\n<p>To save a new <code>Customer<\/code> document, we&#8217;ll use <code>Add<\/code> to start tracking the document, and then call <code>SaveChangesAsync<\/code> to insert it into the database.<\/p>\n<pre><code class=\"language-csharp\">await using (var context = new CustomersContext(mongoClient))\r\n{\r\n    var customer = new Customer\r\n    {\r\n        Name = \"Willow\",\r\n        Species = Species.Dog,\r\n        ContactInfo = new()\r\n        {\r\n            ShippingAddress = new()\r\n            {\r\n                Line1 = \"Barking Gate\",\r\n                Line2 = \"Chalk Road\",\r\n                City = \"Walpole St Peter\",\r\n                Country = \"UK\",\r\n                PostalCode = \"PE14 7QQ\"\r\n            },\r\n            BillingAddress = new()\r\n            {\r\n                Line1 = \"15a Main St\",\r\n                City = \"Ailsworth\",\r\n                Country = \"UK\",\r\n                PostalCode = \"PE5 7AF\"\r\n            },\r\n            Phones = new()\r\n            {\r\n                HomePhone = new() { CountryCode = 44, Number = \"7877 555 555\" },\r\n                MobilePhone = new() { CountryCode = 1, Number = \"(555) 2345-678\" },\r\n                WorkPhone = new() { CountryCode = 1, Number = \"(555) 2345-678\" }\r\n            }\r\n        }\r\n    };\r\n\r\n    context.Add(customer);\r\n    await context.SaveChangesAsync();\r\n}<\/code><\/pre>\n<p>If we look at the JSON (actually, <a href=\"https:\/\/bsonspec.org\/spec.html\">BSON<\/a>, which is a more efficient binary representation for JSON documents) document created in the database, we can see it contains nested documents for all the contact information. This is different from what EF Core would do for a relational database, where each type would have been mapped to its own top-level table.<\/p>\n<pre><code class=\"language-json\">{\r\n  \"_id\": \"CSUUID(\\\"9a97fd67-515f-4586-a024-cf82336fc64f\\\")\",\r\n  \"Name\": \"Willow\",\r\n  \"Species\": 1,\r\n  \"ContactInfo\": {\r\n    \"BillingAddress\": {\r\n      \"City\": \"Ailsworth\",\r\n      \"Country\": \"UK\",\r\n      \"Line1\": \"15a Main St\",\r\n      \"Line2\": null,\r\n      \"Line3\": null,\r\n      \"PostalCode\": \"PE5 7AF\"\r\n    },\r\n    \"Phones\": {\r\n      \"HomePhone\": {\r\n        \"CountryCode\": 44,\r\n        \"Number\": \"7877 555 555\"\r\n      },\r\n      \"MobilePhone\": {\r\n        \"CountryCode\": 1,\r\n        \"Number\": \"(555) 2345-678\"\r\n      },\r\n      \"WorkPhone\": {\r\n        \"CountryCode\": 1,\r\n        \"Number\": \"(555) 2345-678\"\r\n      }\r\n    },\r\n    \"ShippingAddress\": {\r\n      \"City\": \"Walpole St Peter\",\r\n      \"Country\": \"UK\",\r\n      \"Line1\": \"Barking Gate\",\r\n      \"Line2\": \"Chalk Road\",\r\n      \"Line3\": null,\r\n      \"PostalCode\": \"PE14 7QQ\"\r\n    }\r\n  }\r\n}<\/code><\/pre>\n<h2>Using LINQ queries<\/h2>\n<p>EF Core supports <a href=\"https:\/\/learn.microsoft.com\/ef\/core\/querying\/\">LINQ for querying data<\/a>. For example, to query a single customer:<\/p>\n<pre><code class=\"language-csharp\">using (var context = new CustomersContext(mongoClient))\r\n{\r\n    var customer = await context.Customers.SingleAsync(c =&gt; c.Name == \"Willow\");\r\n\r\n    var address = customer.ContactInfo.ShippingAddress;\r\n    var mobile = customer.ContactInfo.Phones.MobilePhone;\r\n    Console.WriteLine($\"{customer.Id}: {customer.Name}\");\r\n    Console.WriteLine($\"    Shipping to: {address.City}, {address.Country} (+{mobile.CountryCode} {mobile.Number})\");\r\n}<\/code><\/pre>\n<p>Running this code results in the following output:<\/p>\n<pre><code class=\"language-text\">336d4936-d048-469e-84c8-d5ebc17754ff: Willow\r\n    Shipping to: Walpole St Peter, UK (+1 (555) 2345-678)<\/code><\/pre>\n<p>Notice that the query pulled back the entire document, not just the <code>Customer<\/code> object, so we are able to access and print out the customer&#8217;s contact info without going back to the database.<\/p>\n<p>Other LINQ operators can be used to perform filtering, etc. For example, to bring back all customers where the <code>Species<\/code> is <code>Dog<\/code>:<\/p>\n<pre><code class=\"language-csharp\">var customers = await context.Customers\r\n    .Where(e =&gt; e.Species == Species.Dog)\r\n    .ToListAsync();<\/code><\/pre>\n<h2>Updating a document<\/h2>\n<p>By default, <a href=\"https:\/\/learn.microsoft.com\/ef\/core\/querying\/tracking\">EF tracks the object graphs returned from queries<\/a>. Then, when <code>SaveChanges<\/code> or <code>SaveChangesAsync<\/code> is called, EF detects any changes that have been made to the document and sends an update to MongoDB to update that document. For example:<\/p>\n<pre><code class=\"language-csharp\">using (var context = new CustomersContext(mongoClient))\r\n{\r\n    var baxter = (await context.Customers.FindAsync(baxterId))!;\r\n    baxter.ContactInfo.ShippingAddress = new()\r\n    {\r\n        Line1 = \"Via Giovanni Miani\",\r\n        City = \"Rome\",\r\n        Country = \"IT\",\r\n        PostalCode = \"00154\"\r\n    };\r\n\r\n    await context.SaveChangesAsync();\r\n}<\/code><\/pre>\n<p>In this case, we&#8217;re using <code>FindAsync<\/code> to query a customer by primary key&#8211;a LINQ query would work just as well. After that, we change the shipping address to Rome, and call <code>SaveChangesAsync<\/code>. EF detects that only the shipping address for a single document has been changed, and so sends a partial update to patch the updated address into the document stored in the MongoDB database.<\/p>\n<h2>Going forward<\/h2>\n<p>So far, the MongoDB provider for EF Core is only in its first preview. Full CRUD (creating, reading, updating, and deleting documents) is supported by this preview, but there are some limitations. See the <a href=\"https:\/\/github.com\/mongodb\/mongo-efcore-provider#readme\">readme<\/a> on GitHub for more information, and for places to ask questions and file bugs.<\/p>\n<h2>Learn more<\/h2>\n<p>To learn more about EF Core and MongoDB:<\/p>\n<ul>\n<li>See the <a href=\"https:\/\/learn.microsoft.com\/ef\/core\/\">EF Core documentation<\/a> to learn more about using EF Core to access all kinds of databases.<\/li>\n<li>See the <a href=\"https:\/\/www.mongodb.com\/docs\/\">MongoDB documentation<\/a> to learn more about using MongoDB from any platform.<\/li>\n<li>Watch <a href=\"https:\/\/www.youtube.com\/live\/Zat-ferrjro?si=WD2mjd2_dd3dquko\">Introducing the MongoDB provider for EF Core<\/a> on the .NET Data Community Standup.<\/li>\n<li>Watch the upcoming <a href=\"https:\/\/www.youtube.com\/live\/EQvRGG9Ine8?si=TkN5q_4ZiHPoxkJy\">Announcing MongoDB Provider for Entity Framework Core<\/a> on the MongoDB livestream.<\/li>\n<\/ul>\n<h2>Summary<\/h2>\n<p>We used <a href=\"https:\/\/testcontainers.com\/\">Testcontainers<\/a> to try out the <a href=\"https:\/\/github.com\/mongodb\/mongo-efcore-provider\">first preview release of the MongoDB provider for EF Core<\/a>. Testcontainers allowed us to test MongoDB with very minimal setup, and we were able to create, query, and update documents in the MongoDB database using EF Core.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>An introduction to the MongoDB database provider for EF Core, including use of Testcontainers<\/p>\n","protected":false},"author":13047,"featured_media":48645,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[685,859],"tags":[7250,7694,70,7760],"class_list":["post-48644","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-dotnet","category-entity-framework","tag-ef-core","tag-efcore","tag-entity-framework","tag-mongodb"],"acf":[],"blog_post_summary":"<p>An introduction to the MongoDB database provider for EF Core, including use of Testcontainers<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/48644","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/users\/13047"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/comments?post=48644"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/posts\/48644\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media\/48645"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/media?parent=48644"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/categories?post=48644"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/dotnet\/wp-json\/wp\/v2\/tags?post=48644"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}