Reputation: 775
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
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