0

I effectively have the following entities defined:

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

    public string Name { get; set; }
}

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

    public string Description { get; set; }

    public int? OrderId { get; set; }

    public Order Order { get; set; }
}

They are configured so that the OrderId in Part is linked to the Order Id:

        // Order Model Builder
        var orderModelBuilder = modelBuilder.Entity<Order>()
            .ToTable("Orders");
        orderModelBuilder.HasKey(i => i.Id);
        orderModelBuilder.HasMany<Part>()
                .WithOne()
                .HasForeignKey(i => i.OrderId);

        // Part Model Builder
        var partModelBuilder = modelBuilder.Entity<Part>()
            .ToTable("Parts");
        partModelBuilder.HasKey(i => i.Id);
        partModelBuilder.HasOne(i => i.Order)
            .WithMany()
            .HasForeignKey(i => i.OrderId);

Now I would like to map these to a detailed order DTO which includes a collection of parts for an order:

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

    public string Description { get; set; }
}

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

    public string Name { get; set; }

    public List<PartDto> Parts { get; set; }
}

Currently, I use Automapper's ProjectTo() to handle queries so I can query what I want and get a list of orders back already mapped to my desired DTO. Now, I want to add Parts to that query so I can get all of the orders back with parts in one query without having to loop through orders and individually fetch the parts for each order returned. I could easily do that if List was part of the Order entity class but adding it at this stage isn't really an option.

CreateMap<Part, PartDto>()
                .ForMember(d => d.Id, a => a.MapFrom(s => s.Id))
                .ForMember(d => d.Description, a => a.MapFrom(s => s.Description))
                ;            
CreateMap<Order, OrderDetailsDto>()
                .ForMember(d => d.Id, a => a.MapFrom(s => s.Id))
                .ForMember(d => d.Name, a => a.MapFrom(s => s.Name))
                .ForMember(d => d.Parts, a => a.MapFrom(s => ?????))
                ;
.
..
...
await dbContext.Set<Order>().Where(...).ProjectTo<OrderDetailsDto>(configurationProvider).ToListAsync()

I know I can get shadow variables using EF.Property(object, name) but not sure how to load a restricted collection (dbContext.Set.Where(i => i.OrderId == orderId)). Any suggestions would be greatly appreciated!

--

I'm also open to adding another Entity class if there is a way to make it exist next to the existing entity. So far, I can't find a way to do that without EF Core complaining that it can only have one entity per class (without a discriminator column which would defeat the purpose!).

Jaron
  • 133
  • 6
  • 1
    It's simple, but requires model change. Add collection navigation property to `Order` entity - problem solved. – Ivan Stoev May 01 '20 at 00:53
  • Yes, I ended up doing that for now but I don't care for the change. The issue comes when you go to update the Order for a Part. Now you have to contend with Order having a list of Parts that includes the parent part you're updating/removing the order for! I would prefer to have that collection separate if at all possible as it's easier to work with then. – Jaron May 01 '20 at 16:23

0 Answers0