I want to create a direct relation between the Task entity and the child entities, to get with the task the corresponding child and when I get the child to get the corresponding task.

I have an entity named Task and I need to relate it with other entities types one2one. My solution was to create in the task entity one propriety for the child id and one for the child type:

public class Task
{
    public int Id { get; set; }
    public int ChildId { get; set; }
    public int TaskTypeId { get; set; }
    public Child1 Child1{ get; set; }
    public Child2 Child2{ get; set; }
} 

public class Child1
{
   public int Id { get; set; }
   public Task Task{get; set;}
}    

public class Child2
{
   public int Id { get; set; }
   public Task Task {get; set;}
}
3

There are 3 best solutions below

1
MrAlbino On

The properties of Child1 and Child2 classes are the same, why did you create 2 separate classes? Wouldn't it work to do it this way with a single class?

public class Task
{
    public int Id { get; set; }
    public int TaskTypeId { get; set; }
    public IEnumerable<Child1> Childs{ get; set; }
} 

public class Child1
{
   public int Id { get; set; }
   public int TaskId { get; set; }
   public Task Task { get; set; }
}    
2
HWS-SLS On

You configure your relationships by convention: https://www.entityframeworktutorial.net/efcore/conventions-in-ef-core.aspx

Therefore the naming is important Change the foreign Keys in the Task Model:

public class Task
{
    public int Id { get; set; }    
    public int TaskTypeId { get; set; }
    
    public int Child1Id { get; set; }
    public Child1 Child1{ get; set; }
    
    public int Child2Id { get; set; }
    public Child2 Child2{ get; set; }
} 

Alternative solution, relationship by Fluent API configuration: https://www.entityframeworktutorial.net/efcore/fluent-api-in-entity-framework-core.aspx With IEntityTypeConfiguration.

public class Task
{
    public int Id { get; set; }
    public int ChildId { get; set; }
    public int TaskTypeId { get; set; }
    public Child1 Child1{ get; set; }
    public Child2 Child2{ get; set; }
} 

public class Child1
{
   public int Id { get; set; }
   public Task Task{get; set;}
}    

public class Child2
{
   public int Id { get; set; }
   public Task Task {get; set;}
}

The implementtion of IEntityTypeConfiguration:

    internal class Child1DbConfig : IEntityTypeConfiguration<Child1>
    {

    public void Configure(EntityTypeBuilder<Child1> entity)
    {
                entity.ToTable("Child1");
                entity.HasKey(c => c.Id);
    
                entity.HasOne(d => d.Task)
                    .WithOne(p => p.Child1)
                    .HasForeignKey(d => d.TaskId);
    }
}

Dont forget to make a new migration after adding/editing the IEntityTypeConfiguration interface.

Also: Maybe choose another name for your Task class. Task is already a Class name in the 'System.Threading' namespace. So if you use anything async, you will run in to trouble sooner or later.

Thanks for CodeCaster for correcting my (wrong) Answer!

0
Fitri Halim On

I face same issue before, so since this is one to one table I suggest you used [Own] entity, which will map everything in the same table as the parent and remove headache.

public class Task
{
    public int Id { get; set; }
    public int ChildId { get; set; }
    public int TaskTypeId { get; set; }
    public Child1 Child1{ get; set; }
    public Child2 Child2{ get; set; }
} 

[Owned]
public class Child1
{
   public int Id { get; set; }
   public Task Task{get; set;}
}    

[Owned]
public class Child2
{
   public int Id { get; set; }
   public Task Task {get; set;}
}

Else, if you prefer them to be in separate table and you want to query them from the child, you can also make the Child.Id as the PK and FK at the same time, and referencing to Task table.

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    modelBuilder.Entity<Task>()
        .HasOne(e => e.Child1)
        .WithOne(e => e.Task)
        .HasForeignKey<Child1>(e => e.Id)
        .IsRequired();

    modelBuilder.Entity<Task>()
        .HasOne(e => e.Child2)
        .WithOne(e => e.Task)
        .HasForeignKey<Child2>(e => e.Id)
        .IsRequired();
}