Skip to content

WhenToTheoriseAndWhenToGet

Craig Fowler edited this page Feb 23, 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.

How Theorise differs from Get

The return value for objects that don't 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 (no row of the specified identity in the corresponding table), 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 retrieves the specified object; 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 to do so.

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

When is Theorise appropriate?

Using Theorise is appropriate to get a reference to an object which is believed to exist in the data-store. It is useful when all the developer wants/needs is the reference to the object; 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 model is persisted to the database it could cause an error. In a typical relational database this would be a foreign key constraint violation error. Theorise is most appropriate when the developer has good reason to believe that the object does indeed exist in the data-store.