Force products collection to use EAV instead of flat table

The object which is responsible to determine if flat index is available (class Magento\Catalog\Model\Indexer\Product\Flat\State) is an immutable shared instance. But it is possible to use our own instance, using virtual types.

This is my di.xml:

  <virtualType name="disabledFlatStateProductCollectionFactory" type="Magento\Catalog\Model\ResourceModel\Product\CollectionFactory">
    <arguments>
      <argument name="instanceName" xsi:type="string">disabledFlatStateProductCollection</argument>
    </arguments>
  </virtualType>
  <virtualType name="disabledFlatStateProductCollection" type="Magento\Catalog\Model\ResourceModel\Product\Collection">
    <arguments>
      <argument name="catalogProductFlatState" xsi:type="object">disabledFlatState</argument>
    </arguments>
  </virtualType>
  <virtualType name="disabledFlatState" type="Magento\Catalog\Model\Indexer\Product\Flat\State">
    <arguments>
      <argument name="isAvailable" xsi:type="boolean">false</argument>
    </arguments>
  </virtualType>

Now, I have a virtual product collection factory type, where my own "State" instance with $isAvailable = false is used eventually:

disabledFlatStateProductCollectionFactory
 |
 + disabledFlatStateProductCollection
    |
    + disabledFlatState

And for the classes where I need a collection factory with disabled flat index, I specify the virtual type disabledFlatStateProductCollectionFactory for the corresponding constructor parameter:

<arguments>
  <argument name="collectionFactory" xsi:type="object">disabledFlatStateProductCollectionFactory</argument>
</arguments>

When a product collection is loaded, the fact that it uses EAV or flat tables is determined by this result \Magento\Catalog\Model\ResourceModel\Product\Collection::isEnabledFlat().
You can write an around or after plugin, that returns false if you are in the context of a certain store view.

Or even better, the values for flat flag are stored (cached) in the member _flatEnabled from the same class.

public function isEnabledFlat()
{
    if (!isset($this->_flatEnabled[$this->getStoreId()])) {
        $this->_flatEnabled[$this->getStoreId()] = $this->getFlatState()->isAvailable();
    }
    return $this->_flatEnabled[$this->getStoreId()];
}

You can write the same around or after plugin for the method \Magento\Catalog\Model\Indexer\Product\Flat\State::isAvailable().
This way your plugin is executed only once. It could be helpful if you have heavy logic behind it or if it is used in other places.

This looks more elegant that changing a config value on the fly.