Well technically, I think nopC is still doing Table-per-type (TPT) in the sense that there is table per entity, and certain properties are inherited. For example, look at
public partial class Product : BaseEntity, ILocalizedEntity, ISlugSupported, IAclSupported, IStoreMappingSupported, IDiscountSupported<DiscountProductMapping>, ISoftDeletedEntity
Product is a table in the DB. The BaseEntity, IAclSupported, and ISoftDeletedEntity provide additional properties (Table columns) not defined directly in Product class.
LINQ to DB is a different Object-Relational Mapping (ORM) framework than Entity Framework, and it has its own way of handling relationships between entities. It doesn't have the concept of navigational properties in the same way that Entity Framework does.
In Entity Framework, navigational properties are used to represent relationships between entities and provide a convenient way to navigate and work with related data.
In LINQ to DB, you typically work with relationships using JOIN operations in LINQ queries. You explicitly join tables and select the related data you need. LINQ to DB doesn't generate navigational properties for you automatically.
However, in nopCommerce plugins, you're more likely working within the context of the 'parameters' you receive in the methods of the interfaces you are supporting (either directly or overridden, etc.). Therefore, you would have one or more entities (e.g. an Order, ShippingOptionRequest, PaymentOptionRequest, etc.), so you're not likely going to "work with relationships using JOIN operations in LINQ queries". You would just call the service methods (e.g., GetCustomerByIdAsync) to get the child objects. So, it's now not considered a "work around"; rather it is "by design" ;) And to address your topic title, you can consider that the "eager loading" is somewhat addressed by the fact that nopC is caching the entities, so it's likely your service call won't need to be hitting the DB again.