Skip to content
This repository has been archived by the owner on Feb 13, 2018. It is now read-only.

BASE.data.DataContext

Jared Barnes edited this page Nov 26, 2015 · 24 revisions

The DataContext helps developers with handling changes to models. Think of the DataContext as a transaction handler. If you have the need to query for data and modify some of the data and the relationships among that model, then the DataContext is your answer. It handles relationships for you, so you don't have to think about updating foreign keys, or primary keys from a service. The DataContext wants you to think about data as it should be, just data, not so much about the storage structure for persisting the data.

The DataContext uses many of the other technologies to handle complexity. It uses Queryables for querying your Service, Futures for asynchrony while interacting with the Service, and Observables for knowing whether or not properties have changed on a instance of a model.

Here is a list of the other technologies that you need to understand when using the DataContext.

The DataContext is perfect to use behind a form. Forms usually consist of related data on one or more models. The changes that happen on the form should be handled with the DataContext on a save button click. Here is how it might look.

//...
var edm = new Edm();
var service = new Service(edm);
//...

saveButton.addEventListener("click", function(){
    var firstName = firstNameInput.value;
    var lastName = lastNameInput.value;
    var id = idInput.value;

    var dataContext = new BASE.data.DataContext(service);

    dataContext.people.firstOrDefault(function(expBuilder){
        return expBuilder.property("id").isEqualTo(id);
    }).then(function(person){
        person.firstName = firstName;
        person.lastName = lastName;

        dataContext.saveChangesAsync().then(function(response){
            console.log("Saved Data!");
        });
    });

});

//...

You'll notice that the life of the DataContext is with in the click function. A Service on the other hand is a long lived object that keeps no memory of the objects that are being queried for. It's simple the portal to the persistent data layer. The DataContext uses the service to maintain the data in a transaction.

When using a DataContext we need a service, and a service needs an edm (Entity Data Model) . The edm describes the model as it appears in storage, and how the data is associated.

#DataSet

DataSets are added automatically from the definitions of the model in the edm. The edm relies on the "collectionName" property found on the model description.

//...
var edm = new BASE.data.Edm();

var personModel = {
    type: Person,
    collectionName: "people",
    properties: {
        id: {
            type: Integer,
            primaryKey: true,
            autoIncrement: true
        },
        firstName: {
            type: String
        },
        lastName: {
            type: String
        }
    } 
};

edm.addModel(personModel);

var service = new BASE.data.services.InMemoryService(edm);

//...

var dataContext = new BASE.data.DataContext(service);

console.log(dataContext.people); // ==> DataSet

//...

DataSet's are queryables. This means that you can start a query like so.

//...
dataContext.people.where(function(expBuilder){
    return expBuilder.property("firstName").isEqualTo("John");
}).toArray();

#DataSet Instance Methods

dataSet.add(entity)

This adds an entity to the dataContext. This is like INSERT.

../

var person = new Person();
dataContext.people.add(person);

dataContext.saveChangesAsync().try();

../

dataSet.remove(entity)

This removes an entity to the dataContext. This is like DELETE.

../

dataContext.people.remove(person);

dataContext.saveChangesAsync().try();

../

dataSet.attach(entity)

This attaches an entity to the dataContext without causing any change tracker changes. There may be an error thrown if the entity or any of the associated entities connected to this entity are already loaded into the dataContext. Use dataSet.load if you need to just load it.

../

var person = new Person();
person.id = 3;

dataContext.people.attach(person);

../

dataSet.load(entity)

This is used to load dto's, unlike attach, it will clone the object passed and return the newly loaded entity.

../

var person = new Person();
person.id = 3;

var loadedPerson = dataContext.people.load(person);

../

dataSet.createInstance(entity)

This creates an instance of the dataSet Type and loads that into the DataContext.

../

var person = dataContext.people.createInstance();
person.firstName = "John";
person.lastName = "Doe";

dataContext.saveChangesAsync().try();

../

DataContext instance methods

dataContext.addEntity

This adds entities to the dataContext. This method will place the entity into the added bucket, and upon saving will put the entity into the loaded bucket.

dataContext.addEntity(entity) ==> undefined

var person = new Person();

dataContext.addEntity(person:any);

dataContext.loadEntity

This loads entities to the dataContext. This method will clone the entity that was supplied and return the entity that was loaded. This is useful if you need to load an entity, but don't know it is already loaded.

dataContext.loadEntity(Type: Function, entity:any) ==> loadedEntity

var dto = {
    id: 1,
    firstName: "John",
    lastName: "Doe"
};

var loadedEntity = dataContext.loadEntity(Person, dto);

dataContext.attachEntity

This attaches entities to the dataContext. This method will not clone any entities but throw errors if any of the entities attached are already loaded into the DataContext instance.

dataContext.attachEntity(entity:any) ==> undefined

var person = new Person();
person.id = 1;
person.firstName = "John";
person.lastName = "Doe";

dataContext.attachEntity(person);

dataContext.removeEntity

This removes entities from the dataContext. This method will place the entity into the remove bucket, and upon saving will be put into the loaded bucket.

dataContext.removeEntity(entity:any) ==> undefined

dataContext.people.firstOrDefault(function(expBuilder){
    return expBuilder.property("firstName").isEqualTo("John");
}).then(function(person){
    dataContext.removeEntity(person);
    dataContext.saveChangesAsync().try();
});

dataContext.detachEntity

This will forget the entity was ever loaded into the data context.

dataContext.detachEntity(entity:any) ==> undefined

dataContext.people.firstOrDefault(function(expBuilder){
    return expBuilder.property("firstName").isEqualTo("John");
}).then(function(person){
    dataContext.detachEntity(person);
    // The entity is now not part of this data context.

    var dataContext2 = new BASE.data.DataContext(service);
    dataContext.attachEntity(person);
});

dataContext.syncEntity

Allows you to update an entity with a newer version without causing change tracker changes. This would be useful in a web socket environment.

dataContext.syncEntity(entity:any, dto: any) ==> undefined

dataContext.people.firstOrDefault(function(expBuilder){
    return expBuilder.property("firstName").isEqualTo("John");
}).then(function(person){
    var dto = {firstName:"Jane"};
    dataContext.syncEntity(person, dto);
    console.log(dataContext.getPendingEntities().updated.length);
});

dataContext.saveEntity

Saves the entity and the entities that it depends. This returns a future.

dataContext.saveEntity(entity:any) ==> Future<any>


dataContext.saveChangesAsync

Saves all changes in the change tracker buckets.

dataContext.saveChangesSequentially

Saves all the entities in linear form. There are times when the order in which you save them matters. The data context remembers which order things where added, updated and deleted. This save guarantees order.

dataContext.asQueryableLocal(Type);

Allows you to query all the loaded entities of that type.

dataContext.asQueryable(Type);

Allows you to query all the entities in the persistent layer.

dataContext.getQueryProvider(Type);

Gets the query provider for the specified Type.

dataContext.getOrm()

Returns the orm used to maintain relationships.

dataContext.getLoadedEntities

Return a BASE.collections.Hashmap<Type, array> of loaded entities.

dataContext.getPendingEntities

Gives you the meta data concerning which entities needed to be added, updated and removed.

dataContext.dispose

This terminates the data context and allows you to hold on to entities that were part of the data context and hand them off to other data context instances.

dataContext.purgeChangeTracker

This restores all entities to their initial state. Updated, and Removed go to loaded, and Added go to detached. This doesn't however change the entities back to their initial property values.

Clone this wiki locally