1

I am using entity framework core in my .net core 3.1 application. I have an object like

public class AppEntity
 {
        [Key]
        public int entity_id { get; set; }
        [Required]
        public string entityname { get; set; }
        [Required]
        public string short_code { get; set; }
        [Required]
        public int entitytype_id { get; set; }
        public int? parent_id { get; set; }        
        public AppEntity Parent { get; set; }
 }

How can i make my object loaded with parent object on model creating. current code at model creating is

protected override void OnModelCreating(ModelBuilder builder)
{
    builder.Entity<AppEntity>(o => { o.HasIndex(e => e.short_code).IsUnique(true); });   
builder.Entity<AppEntity>().HasOne(j => j.Parent).WithOne().HasForeignKey<AppEntity>(f => f.parent_id);

     
}

I am getting exception on modelcreating as

The property or navigation 'Parent' cannot be added to the entity type 'AppEntity' because a property or navigation with the same name already exists on entity type 'AppEntity'.

mj1313
  • 7,930
  • 2
  • 12
  • 32
Kamran Shahid
  • 3,954
  • 5
  • 48
  • 93
  • 1
    **OnModelCreating** This method is called by the framework when your context is first created to build the model and its mappings in memory **not loading your data**, to load Parent Entity with your object when fetch data just use **Include** like _context.AppEntity.Include(a=>a.Parent) – Mohamed Adel Jan 12 '21 at 12:55
  • This will help you https://stackoverflow.com/questions/7348663/c-sharp-entity-framework-how-can-i-combine-a-find-and-include-on-a-model-obje/7348694 – Mohamed Adel Jan 12 '21 at 13:13
  • Does this answer your question? [C# Entity-Framework: How can I combine a .Find and .Include on a Model Object?](https://stackoverflow.com/questions/7348663/c-sharp-entity-framework-how-can-i-combine-a-find-and-include-on-a-model-obje) – Flater Jan 12 '21 at 13:55

1 Answers1

1

As the comments said, the OnModelCreating is used to build the relationship between tables.

Before loading the object with parent object, you need to change the code in OnModelCreating. The WithOne need to specific an object.

    public DbSet<Entity>   entities { get; set; }
    public DbSet<AppEntity> appEntities { get; set; }
    protected override void OnModelCreating(ModelBuilder builder)
    {
        base.OnModelCreating(builder);
        builder.Entity<AppEntity>(o => { 
            o.HasIndex(e => e.short_code)
            .IsUnique(true); 
        });
        builder.Entity<AppEntity>()
            .HasOne(j => j.Parent)
            .WithOne(i=>i.appEntity)
            .HasForeignKey<AppEntity>(f => f.parent_id);
    }

Because you have create the foreign key in dbcontext, so you can remove [ForeignKey("parent_id")].

In addition, in model Entity, you should add the property AppEntity to reference the child object.

 public class Entity
{
    public int id { get; set; }

    public AppEntity appEntity { get; set; }
}

Then, you can use Include to include the two objects.

    public virtual Entity GetById(int id) 
    { 
        
        var entity = _context.entities
             .Include(y => y.appEntity)
             .FirstOrDefault(x => x.id == id);
        return entity; 
    }

Edit:

In one table, this will lead to circular references, because you have added the parent_id to reference the parent.

A better solution is to remove public AppEntity Parent { get; set; }, and remove builder.Entity<AppEntity>().HasOne(j => j.Parent).WithOne().HasForeignKey<AppEntity>(f => f.parent_id);.

Before inserting data into the table, query whether entity_id exists, if it exists, add it, if it does not exist, set it null. Because the primary key has its own index, the query speed is very fast.

When querying, based on these two columns, the corresponding data can be clearly processed using sub-query or associated query.

Karney.
  • 4,803
  • 2
  • 7
  • 11