Skip to content

WhenToTheoriseAndWhenToGet

Craig Fowler edited this page Feb 22, 2020 · 2 revisions

The functions IQuery.Theorise<T> and IEntityData.Theorise<T> are essentially a performance optimisation.

They are designed for use when a developer wishes to express that an entity exists in the data-store but doesn't want to actually retrieve it from the store.

When in doubt, use Get

The theorise methods are a performance optimisation, and "premature optimisation is the root of all evil'. If in doubt about whether to use the Theorise or the Get methods, choose Get. Using Get will result in safer code, which behaves consistently in all scenarios.

Theorise, compared with Get

Return value if the object does not exist in the data-store

The Get method will go to the data-store in order to retrieve the specified object. In production environments this means a round-trip to the database. If the object does not exist, then the Get method will return null.

On the other hand, the Theorise method does not contact the data-store and in production it does not read the database. Instead it assumes that the specified object exists and returns a stand-in/proxy object which represents the object.

The Theorise method will never return null.

How the returned object is populated

When the Get method is used, it will fully retrieve the specified object and all of its property values/state will be populated using the data-store.

On the other hand, Theorise does not populate any properties/state of the object except for its identity/primary key value. An ORM backend might provide lazy-loading for this state upon access, but it is not certain.

Theorise should not be used if any state is required from the specified object.

When is Theorise appropriate?

Using Theorise is appropriate when we want a reference to an object which we believe to be in the data-store but all we want is the reference, not any of its state.

Example: Querying by related object

Here is an example where we create a query for parcels over 10kg in weight, which are in a specified warehouse.

public IList<Parcel> GetHeavyParcels(long warehouseId)
{
  // query is an instance of IQuery
  var warehouse = query.Theorise<Warehouse>(warehouseId);
  return query.Query<Parcel>()
    .Where(x => x.Warehouse == warehouse
                && x.WeightKg > 10)
    .ToList();
}

In this example, Theorise was appropriate to get the warehouse object. This was because the object was only used within a Linq query, and none of its properties/state was used in that query, only its existence.

Example: Setting a reference

In this example, we are updating a reference property on one object to point to another. We do not use any state of that newly-referenced object, we only wish to point to it by its identity.

public void TransferEmployee(Employee employee, long officeId)
{
  // query is an instance of IQuery
  // persister is an instance of IPersister
  var office = query.Theorise<Office>(officeId);
  employee.Office = office;
  persister.Update(employee);
}

As with the previous example, Theorise is appropriate because we do not use any of the state of the office object. All we want to do is to update the employee object to have a different office, identified by its identity/primary key value.

Note that this code is not entirely safe; if the office identified by officeId does not exist in the data-store then when the employee updated, it may cause an error (a foreign key constraint failure in a typical database). Use Theorise only when your are willing to accept that risk, or have ensured in some other way that the theoretical entity does in fact exist.

Clone this wiki locally