Upcoming Teaq version 2.0 Breaking Changes

There is a little refactor pain in the following changes, but this will be worth it, as it will clarify your code and reduce its size, and in some cases, work properly.

Async Defects Fixed and API corrected

The underlying handling of async was fundamentally incorrect. This has been fixed such that the asynchronous fetch of data is done using the underlying BCL async capabilities whenever possible. The API shape has been modified such that if you are iterating a batch reader directly, you are now responsible for invoking MoveNext or MoveNextAsync, which will (potentially) round trip to the backing store.

API Surface Reduced

The act of reading from the underlying data reader is no longer asynchronous. If you are using the IDataReader extensions, you will no longer see these async methods.

If you are using the reader extensions that hang off the IDbConnection, these are no longer available.

DataConfiguration is renamed to "Repository"

The name DataConfiguration is not correct; this name reflects only one aspect of the class responsibility. This class is a facade over underlying repository capabilities, and its purpose is to provide an entry point into your repository. Naming is hard.

IDataModel is visible

The IDataModel interface is now found in the Teaq namespace as it is often used in declarations. This is most likely non-breaking for the majority of code that is written with imported namespaces.

Simplification of IDataHandler

The IDataHandler interface is originally designed to be a dispatching mechanism to specific entity handlers. This means the implementer has to write "typeof" boilerplate code, and do type conversions that are a nuisance. The 1.5 IDataHandler will accept its generic type parameter as part of the interface definition, allowing you to implement handler-per-entity strategies. In addition, the "CanRead" method is removed. If you pass a data handler as an argument, it will be used unconditionally.

IDataHandler now only exposes the ReadEntity<T> method, expressing a single purpose: materialize a row into an object.

If you have invested in such type mapping code, you can re-purpose this code to be builder or factory to serve IDataHandler instances that target a single entity type.

Decoupling IDataContext and IDataModel

If you are creating IDataContext instances from your IDataModel instance, this has changed. Instead, create IDataContext instances using the Repository static class. The intent is to decouple data access from specific models. You can now pass IDataModel instances to the Query<T> methods for use when materializing objects.

For example:

var myConnection = "someConnectionString"; 
// "old" way, use an IDataModel instance:
// var context = DataConfiguration.DefaultModel.CreateContext(myConnection);
// "new" way, use Repository:
var context = Repository.BuildContext(myConnection);

Also, if you pass a QueryCommand instance built from a model, the underlying model reference is preserved for object materialization, so you don't have to do anything in this case, as follows:

// Assuming "myDataModel" is an existing IDataModel instance:
var queryCommand = myModel.ForEntity<Customer>()
    .BuildSelect()
    .Where(c => c.CustomerId == 123)
    .ToCommand();

var myConnection = "someConnectionString"; 
var context = Repository.BuildContext(myConnection);

// The following will use  "myDataModel" for object materialization by default:
var results = context.Query<Customer>(queryCommand);

Simplified Entry into Fast Reflection Types

You can now access the Fast Reflection types using myType.GetTypeDescription(...). The use of RuntimeTypeHandle is removed. This was a well intended optimization that didn't measure up after several rounds of profiling. Using Type is more direct and the handle was converted to Type internally anyway.

Last edited Aug 3, 2016 at 1:07 AM by bkjuice, version 21