Inverse Property in EF Core

Prathamesh Shende 376 Reputation points
2021-10-23T21:27:16.837+00:00

How to apply Inverse Property in Ef Core I gone through so many examples but didnt helps me. So

my models like this
public class Customer
{

    public string Name { get; set; }
    public int AddedByID { get; set; }
    public int EditedByID { get; set; }
    public int DeletedByID { get; set; }
    [InverseProperty("Customers")]
    [ForeignKey("AddedByID")]
    public virtual UserLogin AddedBy { get; set; }
    [ForeignKey("EditedByID")]
    public virtual UserLogin EditedBy { get; set; }
    [ForeignKey("DeletedByID")]
    public virtual UserLogin DeletedBy { get; set; }

}
public class Vendor
{

    public string Name { get; set; }
    public int AddedByID { get; set; }
    public int EditedByID { get; set; }
    public int DeletedByID { get; set; }
    [InverseProperty("Vendors")]
    [ForeignKey("AddedByID")]
    public virtual UserLogin AddedBy { get; set; }
    [ForeignKey("EditedByID")]
    public virtual UserLogin EditedBy { get; set; }
    [ForeignKey("DeletedByID")]
    public virtual UserLogin DeletedBy { get; set; }

}
public class UserLogin
{
public UserLogin()
{
Customers = new HashSet<Customer>();
Vendors = new HashSet<Vendor>();

    }

public virtual ICollection<Customer> Customers { get; set; }
public virtual ICollection<Vendor> Vendors { get; set; }
}

this only works if I use only model (Customer) if Add this same properties into vendor then it throw error - Unable to determine the relationship represented by navigation 'Custom.Edited By' of type 'UserLogin'. Either manually configure the relationship, or ignore this property using the '[NotMapped]' attribute or by using 'EntityTypeBuilder.Ignore' in 'OnModelCreating'.'

this error is not show if I dont use vendor model

so How do I apply inverse property here

ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,157 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Zhi Lv - MSFT 32,011 Reputation points Microsoft Vendor
    2021-10-25T06:08:13.607+00:00

    Hi @Prathamesh Shende ,

    You can set the foreign key to nullable and use InverseProperty as below:

    public class Customer  
    {  
        [Key]  
        public int ID { get; set; }  
        public string Name { get; set; }  
        [ForeignKey("AddedBy")]  
        public int? AddedByID { get; set; }  
        [ForeignKey("EditedBy")]  
        public int? EditedByID { get; set; }  
        [ForeignKey("DeletedBy")]  
        public int? DeletedByID { get; set; }   
        public UserLogin AddedBy { get; set; }   
        public UserLogin EditedBy { get; set; }   
        public UserLogin DeletedBy { get; set; }  
    }  
    public class Vendor  
    {  
        [Key]  
        public int ID { get; set; }  
        public string Name { get; set; }  
        [ForeignKey("AddedBy")]  
        public int? AddedByID { get; set; }  
        [ForeignKey("EditedBy")]  
        public int? EditedByID { get; set; }  
        [ForeignKey("DeletedBy")]  
        public int? DeletedByID { get; set; }   
        public UserLogin AddedBy { get; set; }  
        public UserLogin EditedBy { get; set; }  
        public UserLogin DeletedBy { get; set; }  
    }  
    public class UserLogin  
    {   
        public UserLogin()  
        {  
            CustomersAdded = new List<Customer>();  
            VendorsAdded = new List<Vendor>();  
        }  
    
        [Key]  
        public int Id { get; set; }  
        public string Name { get; set; }  
    
        [InverseProperty("AddedBy")]  
        public List<Customer> CustomersAdded { get; set; }  
        [InverseProperty("EditedBy")]  
        public List<Customer> CustomersEdited { get; set; }  
        [InverseProperty("DeletedBy")]  
        public List<Customer> CustomersDeleted { get; set; }  
        [InverseProperty("AddedBy")]  
        public List<Vendor> VendorsAdded { get; set; }  
        [InverseProperty("EditedBy")]  
        public List<Vendor> VendorsEdited { get; set; }  
        [InverseProperty("DeletedBy")]  
        public List<Vendor> VendorsDeleted { get; set; }  
    }  
    

    And configure the cascading delete as NoAction:

    public class ApplicationDbContext : IdentityDbContext  
    {  
        public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)  
            : base(options)  
        {  
        }    
    
        public DbSet<UserLogin> UserLogin { get; set; }  
        public DbSet<Customer> Customers { get; set; }  
        public DbSet<Vendor> Vendors { get; set; }  
    
        protected override void OnModelCreating(ModelBuilder modelBuilder)  
        {  
            base.OnModelCreating(modelBuilder);  
            modelBuilder.Entity<Customer>()  
                .HasOne(c => c.AddedBy)  
                .WithMany(c=>c.CustomersAdded)  
                .OnDelete(DeleteBehavior.NoAction);  
            modelBuilder.Entity<Customer>()  
                .HasOne(c => c.EditedBy)  
               .WithMany(c => c.CustomersEdited)  
                .OnDelete(DeleteBehavior.NoAction);  
            modelBuilder.Entity<Customer>()  
                .HasOne(c => c.DeletedBy)  
               .WithMany(c => c.CustomersDeleted)  
                .OnDelete(DeleteBehavior.NoAction);  
            modelBuilder.Entity<Vendor>()  
                .HasOne(c => c.AddedBy)  
               .WithMany(c => c.VendorsAdded)  
                .OnDelete(DeleteBehavior.NoAction);  
            modelBuilder.Entity<Vendor>()  
                .HasOne(c => c.EditedBy)  
                .WithMany(c=>c.VendorsEdited)  
                .OnDelete(DeleteBehavior.NoAction);  
            modelBuilder.Entity<Vendor>()  
                .HasOne(c => c.DeletedBy)  
                .WithMany(c=>c.VendorsDeleted)  
                .OnDelete(DeleteBehavior.NoAction);   
        }  
    }  
    

    The generated table as below:

    143324-image.png

    Then, you can add/remove the entity via the ApplicationDbContext, like this:

            _context.UserLogin.Add(new UserLogin()  
            {  
               Name="AA",  
               CustomersAdded= new List<Customer>()  
               {  
                   new Customer(){ Name="Tom"}  
               },  
                CustomersEdited = new List<Customer>()  
               {  
                   new Customer(){ Name="John"}  
               },  
                VendorsAdded = new List<Vendor>()  
                {  
                    new Vendor(){ Name="Jack"}  
                }  
            });  
            _context.SaveChanges();  
    

    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,
    Dillion