Dazfl
Dazfl

Reputation: 775

Entity Framework Core and defining a one-to-many and one-to-one relationship

I've tried looking for a solution for this, but I haven't been successful thus far (if anyone could point me to an answer, or example, I would be very greatful).

I have a hypothetical entity structure as follows:

public class ClassA
{
    public int Id { get; set; }

    public string ClassName { get; set; }

    public ICollection<ClassB> ClassBs { get; set; }
}

public class ClassB 
{
    public int Id { get; set; }

    public int ParentId { get; set; }
    public ClassA Parent { get; set; }

    public int SingleRelatedClassId { get; set; }
    public ClassA SingleRelatedClass { get; set; }
}

As you can see ClassA has a one-to-many relationship to ClassB. This works well and correctly. However, I now need to introduce a one-to-one relationship between ClassB and ClassA (SingleRelatedClass) without a navigation property in ClassA.

How can I achieve these relationships with either data annotations or Fluent API?

Upvotes: 0

Views: 43

Answers (1)

Dazfl
Dazfl

Reputation: 775

So it turns out that I had my entities (mostly) set up correctly, but my configuration and actual query were incorrect. Below is what worked for me.

Entities:

public class ClassA
{
    public int Id { get; set; }
    public string ClassName { get; set; }

    public virtual ICollection<ClassB> ClassBs { get; set; }
}

public class ClassB 
{
    public int Id { get; set; }

    public int ParentId { get; set; }
    public virtual ClassA Parent { get; set; }

    public int SingleRelatedClassId { get; set; }
    public virtual ClassA SingleRelatedClass { get; set; }
}

Configuration (only relevant info included):

public void Configurate(EntityTypeBuilder<ClassB> builder)
{
    // One-to-many
    builder
        .HasOne(b => b.Parent)
        .WithMany(a => a.ClassBs)
        .HasForeignKey(b => b.ParentId);

    // One-to-one (without navigation property)
    builder
        .HasOne(b => b.SingleRelatedClass)
        .WithOne()
        .HasForeignKey<ClassB>(b => b.SingleRelatedClassId);
}

Query (single item select example, using eager loading):

var result = await _context.ClassA
    .AsNoTracking()
    .Include(a => a.ClassBs)
    .ThenInclude(b => b.SingleRelatedClass)
    .Where(a => a.Id.Equals(idFilter))
    .FirstOrDefaultAsync();

If there is a more efficient, or more correct, way to do this, by all means let me know, but this worked correctly for me.

Upvotes: 1

Related Questions