title: EF Core relationship without foreign key
body: <p>How to setup a navigation property without declaring a foreign key?  </p>
  
  <p>I have two tables (<code>segment</code> and <code>category</code>), they can join using 2 columns (origin/destination) but they don't meet the foreign key constraint because they can have value that doesn't exist in the other table (so its not about null or not null)</p>
  
  <p><strong>Segment</strong>         </p>
  
  <pre><code>Id   Date       OriginId  DestinationId
  ---------------------------------------
  1    2020-01-10    1        2
  2    2020-01-18    2        1
  2    2020-02-05    1        3
  4    2020-04-11    3        3
  </code></pre>
  
  <p><strong>Category</strong>            </p>
  
  <pre><code>Id  OriginId   DestinationId  Category
  -----------------------------------------
  1      1            2         Primary
  2      2            1         Secondary
  2      2            3         Primary
  </code></pre>
  
  <p>I want to know every <code>Segment</code> category. But not every segment exists in <code>Category</code> so some segments won't have a category.</p>
  
  <p>This SQL works :</p>
  
  <pre><code>SELECT 
      s.*, c.name
  FROM 
      Segment s
  LEFT OUTER JOIN 
      Category c ON c.originId = s.originId AND c.destinationId = s.destinationId
  </code></pre>
  
  <p>This LINQ also works:</p>
  
  <pre><code>from s in Segment
  join c in Category on new { s.OriginId, s.DestinationId } equals new { c.OriginId, c.DestinationId } into grouping
  from c in grouping.DefaultIfEmpty()
  select new { s, c };
  </code></pre>
  
  <p>But to use navigation, closest I got is this: I added a property on each class respectively and setup the relationship in context using fluent api</p>
  
  <pre><code>protected override void OnModelCreating(ModelBuilder modelBuilder)
  {
      modelBuilder.Entity&lt;Segment&gt;()
          .HasOne(segment =&gt; segment.Category)
          .WithMany(category =&gt; category.Segments)
          .HasForeignKey(segment =&gt; new { segment.OriginId, segment.DestinationId })
          .HasPrincipalKey(category =&gt; new { category.OriginId, category.DestinationId })
          .IsRequired(false);
  }
  
  // then I can do
  var query = Segments.Include(o =&gt; o.Category).ToList();
  </code></pre>
  
  <p>This works to retrieve records that already exists in the database.</p>
  
  <p>But to insert a new record to Segment where originId and destinationId do not exists in Category it complains about originId and destinationId not meeting the foreign key constraint. And it's ok because they don't exist in the other table.</p>
  
  <p>They actually aren't foreign keys, just a column to use for joining them, but I don't khow to set this using a navigation property + Fluent Api.</p>