title: EF Core: use a dictionary property
body: <p>Is there a way to fill a dictionary property with Entity Framework Core?</p>
  
  <p>For performance reasons, we like to search in the application instead of the database. As a list won’t scale well, we like to use a dictionary.</p>
  
  <p>For example (simplified example)</p>
  
  <pre><code>class Course
  {
      public Dictionary&lt;string, Person&gt; Persons { get; set; }
  
      public int Id { get; set; }
  }
  
  class Person
  {
      public string Firstname { get; set; }
      public string Lastname { get; set; }
  }
  </code></pre>
  
  <p>Things I tried</p>
  
  <ul>
  <li>Naively just add a dictionary property. This will result the in following error:
  
  <blockquote>
    <p>System.InvalidOperationException: The property 'Persons' could not be mapped, because it is of type 'Dictionary' which is not a supported primitive type or a valid entity type. Either explicitly map this property, or ignore it using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.</p>
  </blockquote></li>
  <li><p>Try adding a <a href="https://docs.microsoft.com/en-us/ef/core/modeling/value-conversions" rel="noreferrer">value conversion</a> (with <code>HasConversion</code>), but conversion one only works on a single item and not on collections. The <code>HasMany</code> already gives a compile error:</p>
  
  <pre><code>builder
    .HasMany&lt;Person&gt;(c =&gt; c.Persons) //won't compile, Persons isn't a IEnumerable&lt;Person&gt;
    .WithOne().HasForeignKey("PersonId");
  </code></pre></li>
  <li><p>Creating a custom collection class (inherited from <a href="https://docs.microsoft.com/en-us/dotnet/api/system.collections.objectmodel.collection-1" rel="noreferrer"><code>Collection&lt;T&gt;</code></a> and implement <code>InsertItem</code>, <code>SetItem</code> etc.) – unfortunately this also won’t work because EF Core will add the item to the collection and first after that will fill the properties (at least with our OwnsOne properties, that is not in the demo case) - <code>SetItem</code> won't be called afterwards.</p></li>
  <li><p>Adding a "computed" property that will build the dictionary, the setter won't be called (the list is updated every time with partly values, a bit the same as above). See try:</p>
  
  <pre><code>class Course
  {
      private Dictionary&lt;string, Person&gt; _personsDict;
  
      public List&lt;Person&gt; Persons
      {
          get =&gt; _personsDict.Values.ToList();
          set =&gt; _personsDict = value.ToDictionary(p =&gt; p.Firstname, p =&gt; p); //never called
      }
  
      public int Id { get; set; }
  }
  </code></pre></li>
  </ul>
  
  <p>Of course I could build a dictionary in the Repository (using the <a href="https://docs.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/implementing-the-repository-and-unit-of-work-patterns-in-an-asp-net-mvc-application" rel="noreferrer">Repository pattern</a>), but that’s tricky as I could forget some parts – and I really prefer compile time errors over run-time errors and declarative style over imperative style code. </p>
  
  <p>Update, to be clear </p>
  
  <ul>
  <li>this isn't a code first approach</li>
  <li>the idea to change the mapping in EF Core, so no database changes. - I haven't tagged the database on purpose ;) </li>
  <li>If I use a <code>List</code> instead of Dictionary, the mapping works </li>
  <li>It's a 1:n or n:m relationship in the database (see HasMany - WithOne)</li>
  </ul>