Where should “query” business logic be placed in Domain-driven design?

System description

This is a simple eCommerce application containing a Products inventory managed by an Admin. The Products in inventory/repository will show in the User App. Admin has the ability to mark ON/OFF a Product. ON = display in User App, OFF = do not display. Products are maintained in a single table (Products) in database.

This system is built (read: attempted) on DDD principles.
The Products data in db is accessed in code via .NET Entity Framework.
There are two different Applications (Admin App and User App) created.

  1. Admin App can see ALL Products.
    1. Domain name = Admin.
    2. Does the simple CRUD operations.
    3. Ignoring other setup here as it is pretty straightforward.
  2. User App should only see “ON” Products.
    1. Domain name = StoreView. (FYI – Entities from Admin domain are not mixed/reused here.)
    2. AggregateRoot = NONE. I realize that UserApp cannot modify a Product. So, decided to create Product as a DTO/POCO class.
    3. Repository = IProductRepository, has GetProducts().

My Problem

Where to place this (ON/OFF) “business logic”? (BTW, this is a business logic, right? OR is it an “application logic”?)
According to DDD, business logic should be maintained in the Domain layer. However, this is a “query” (product.Status == “ON”). Where should this logic be put – Domain Entity, Domain Service, Repository or Application?

I found these two questions closest to my problem, but I can’t find the answer, alas.
Handling Business Logic/Validation Race Conditions
How to completely avoid business logic in DAL?

Approach I – Query in Repository

Write the query business logic in IProductRepository, e.g.

public IEnumerable<Product> GetProducts()
    return db.Products.Where(p => p.Status == "ON").ToList();

Disadvantage: This does not look like how to do things in DDD.

Approach II – Query in Application Layer

Get ALL Products from repository, and then apply condition in Application Service/Controller/somewhere like that.

Disadvantage: ALL Products will be loaded in memory and then filtered. Also, I am not sure if this conforms to DDD.

Approach III – Query in an Aggregate Root

Have an AggregateRoot, say, Store. Store contains a property for Products. Get entire Store, including ALL Products from repository, and the “filtering” happens in Products’ getter.

ICollection<Product> _products;
ICollection<Product> Products
    get { return _products.Where(p => p.Status == "ON").ToList(); }
    private set { _products = value; }

Disadvantage: ALL Products will be loaded in memory. Also, keeping ALL Products throughout Store entity’s life-time seems really odd.

Approach IV – Maintain two separate Product tables for the two domains

Maintain two separate tables for Products, maybe in two different schemas: admin.Products and storeview.Products.
admin.Products will be populated by Admin users.
Raise a DomainEvent when Status is updated for a Product.
A Domain/Application EventHandler subscribed to the above event will create/update storeview.Products table.
NO query logic required in StoreView domain or “UserApp”.

Disadvantage: Additional complexity and infrastructure overhead of maintaining two separate tables in db.


What is the most-appropriate solution, in terms of DDD, strictly?