Search code examples
entity-frameworkapi.net-coreef-core-3.0db-first

To add navigation property without foreign key in EF Core, DB-first migration with .NET Core Web API


I am working with an existing system and updating it to .NET Core, Web API and EF Core.

The existing system has 2 tables:

  • Parent table: Id, name, etc..
  • Child table: Id, ParentId, name, etc..

Though ParentId exists in the child table, there is no foreign key reference, but I want to be able to use include when I query the parent. I have asked not to add FK as part of deleting they are putting -ve values to parentId column. This way they can bring it back and a legacy system was built that way.

Now, in db-first migration how can I specify a navigation property without fk so my EF Core to act relational; or at least return them together. Adding nullable foreign key is not an option as it will break the system when -ve values are added.

I do have suggested for full cleanup of DB and getting rid of -ve values but that involves lots of testing and no deliverable. So long story short how to add navigation property without foreign key in database first migration ?

I tried adding collection and virtual entry in the model, but after migration it got overwritten. I have added this by using HasMany on modelbuilder as per this document - https://learn.microsoft.com/en-us/ef/core/modeling/relationships?tabs=fluent-api%2Cfluent-api-simple-key%2Csimple-key

But scaffolding is overriding my navigation property


Solution

  • I found out the answer for this.

    In EF core 3.x the dbcontext created by DBFrist scaffolding is all partial classes. So I did the following: 1. new partial class for context class - here i added the relationship of navigation property using OnModelCreatingPartial() method. Example below

    public partial class dbContext : DbContext
    {
        partial void OnModelCreatingPartial(ModelBuilder builder)
        {
            builder.Entity<Packcomponent>()
            .HasOne(p => p.Pack)
            .WithMany(b => b.PackComponent)
            .HasForeignKey(p => p.PackId);
        }
    }
    
    1. extended the partial class in a new file and added navigation property there.

      
       public partial class Packcomponent
       {
         public Pack Pack { get; set; }
       }
       public partial class Pack
       {
         public List PackComponent { get; set; }
       }

    This way upon scaffolding it did not overwrite custom navigation properties and I also could use this properties to do EF operations like .Include() and to save related entities as well. It is pretty awesome!!