LitwareHR on SSDS - Part II - The data access layer

The heart of LitwareHR implementation on SSDS is in it's data access layer of course. In fact, we created two different, but functionally equivalent implementations: one runs against SQL (LitwareHR's original implementation) and a second stack that runs against SSDS. Of course they are mutually exclusive and all layers above the DataModel cannot tell the difference.




As illustrated in the diagram above, the key class is Repository<T> , which among other things encapsulates all access to SSDS, translates T's into SSDS's Flexible Entities and in general provides a higher level of abstraction on top of SSDS artifacts. For example, Repository deals with tenants, which are then mapped into Authorities & Containers by a provider. The default implementation of this simply does a 1:1 mapping between Tenants and Containers, being Authorities fixed (as specified in configuration), but because it is using a provider model, you can supply a more sophisticated implementation.

T allows us to use typed objects that represent LitwareHR entities: Resumes, Positions, etc. so a hypothetical LitwareHR developer can write things similar to this:

 public class Position : ExtensibleEntity
    public string Code {set;get;}
    public string Location {set; get;}
 Position p = new Position { Id = Guid.NewGuid(), Code = "Code_1", Location = "Location_1", };

p.Fields.Add( "YearsOfExperience", 15 );

In LitwareHR all entities derive from ExtensibleEntity which is just a simple helper base class that provides some useful fields such as: Id, a collection of fields, etc.

In the example above, Id comes from ExtensibleEntity, Code and Location are defined at design time by the developer and "YearsOfExperience" might be a field that a particular tenant is adding to this position. Because it is a tenant specific field, it is defined at runtime.

Behind the scenes the Position entity will be translated into a SSDS flexible entity. Id, and Kind are intrinsic properties in SSDS and are automatically mapped into the Position.Id and typeof(Position).ToString(). The rest is mapped to flexible properties.

All those details are of course handled by Repository<T>. Its interface is straight forward and looks like the one below, which is self-explanatory.

 Insert( T );

T GetById( id );

IEnumerable<T> ListAll();

IEnumerable<T> Search( string query );

Delete( id );

Update( T );

So a complete snippet (taken from one of our tests) looks like this: