## Impacted versions:
 8.0 / 9.0 / 10.0
## Steps to reproduce:
* see https://github.com/odoo/odoo/issues/11841
* in a shell
  1. create an in memory record `order = self.env['purcahse.order'].new({....})`
  2. create an in memory record with a reference to the first one `order_line = self.env['purchase.order.line'].new({'order_id': order, ....})`
  3. order_line.order_id is an in memory recordset
  4. create a record for a model that inherits from mail.thread `self.env['product.product'].create({....})`
  5. At this stage order_line.order_id is an empty recordset

## Current behavior:
 In memory records are dropped when a call is done to self.invalidate_cache
## Expected behavior:
In memory records are preserved when a call is done to self.invalidate_cache


There are lot of places where the method `invalidate_cache` is called and the silent removal of the in memory records from all environments has unpredictable effects on fields modified by a computed method or an onchange or even related fields .... Moreover since all caches are invalidated each time you create / write / unlink  (https://github.com/odoo/odoo/blob/10.0/addons/mail/models/mail_followers.py#L111) an instance of a model that inherits from 'mail.thread', the performances of the server are severely penalized.

OPW703903

addons/purchase/purchase.py
return qty, price
    def update_origin_po(self, cr, uid, po, proc, context=None):
        pass
    def make_po(self, cr, uid, ids, context=None):
        """ Resolve the purchase from procurement, which may result in a new PO creation, a new PO line creation or a quantity change on existing PO line.
        Note that some operations (as the PO creation) are made as SUPERUSER because the current user may not have rights to do it (mto product launched by a sale for example)
        @return: dictionary giving for each procurement its related resolving PO line.
        """
        res = {}
        company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id
        po_obj = self.pool.get('purchase.order')
        po_line_obj = self.pool.get('purchase.order.line')
        seq_obj = self.pool.get('ir.sequence')
        pass_ids = []
        linked_po_ids = []
        sum_po_line_ids = []
        for procurement in self.browse(cr, uid, ids, context=context):
            ctx_company = dict(context or {}, force_company=procurement.company_id.id)
            partner = self._get_product_supplier(cr, uid, procurement, context=ctx_company)
            if not partner:
                self.message_post(cr, uid, [procurement.id], _('There is no supplier associated to product %s') % (procurement.product_id.name))
                res[procurement.id] = False
            else:
                schedule_date = self._get_purchase_schedule_date(cr, uid, procurement, company, context=context)
                purchase_date = self._get_purchase_order_date(cr, uid, procurement, company, schedule_date, context=context) 
                line_vals = self._get_po_line_values_from_proc(cr, uid, procurement, partner, company, schedule_date, context=ctx_company)
                
                available_draft_po_ids = po_obj.search(cr, uid, [
                    ('partner_id', '=', partner.id), ('state', '=', 'draft'), ('picking_type_id', '=', procurement.rule_id.picking_type_id.id),
                    ('location_id', '=', procurement.location_id.id), ('company_id', '=', procurement.company_id.id), ('dest_address_id', '=', procurement.partner_dest_id.id)], context=context)