Skip to main content

Working with data in code

The JetVeo platform utilizes Entity Framework for data access and management.

Representation in code

Data you define in the Data section will be available in code.

  • Entities represented as classes with the same name
  • Aspects represented as interfaces with the same name
  • Codebooks represented as enum-like classes with the entries being the codebook codes

Working with the database

In the code, you have access to the Application Database. It is passed to you as an argument in Business Commands and in simple expressions. You can then pass it as an argument to your custom code.

The type of the database object is AppDatabase.

Get database data

For each entity defined in data, there is a corresponding entity table. Accessible at db.ExampleEntitySet

db.ExampleEntitySet is an IQueryable object. You can further specify what objects you want to get by doing queries. More about queries

Most common queries

  • Where(x => condition(x)) Contains elements, for which the passed lambda expression is true.
  • Count(x => condition(x)) Returns the number of elements, for which the lambda evaluates to true.
  • Any(x => condition(x)) Returns a boolean value: true if any object x specified by the lamda exists, false otherwise.
  • FirstOrDefault(x => condition(x)) Returns the first element, that satisfies the condition. Otherwise returns null or other specified default value.
  • SingleOrDefault(x => condition(x)) Returns the only single element, for which the condition is true. Otherwise returns null or other specified default value.

Modifying the database

Add

You can add an entity object to the database by calling db.ExampleEntitySet.Add(entity)

Documents

When creating an entity object, the document fields are implicitly set to null. When adding it to the database, the document are set to IDocument objects with 0 revisions. To assign an actual document, use the AddRevision method on the IDocument object.

Delete

You can delete an element, or a collection of elements:

  • Delete(x) Deletes the element x.
  • DeleteRange(xs) Deletes all elements from IEnumerable<T> x that are in the db table.

We generally advise against using these methods, because they are destructive. Instead, we recommend adding an attribute deleted, as you can ignore the objects with this attribute set, while still allowing for their restoration.

Modify

You can modify an entity object in the database by setting a value to some of it's field.

If this change violates any requirement defined in the App (Invalid state transition, Forbidden null reference...), this action will throw an exception.

For a state machine like this:

STATE_MACHINE_SCHEME

The following code will throw an exception. Unless the exception is handled, the command will fail.

var deletedEntity = db.ExampleEntitySet.FirstOrDefault(x => x.Status == ExampleCodebook.DELETED);
if (deletedEntity != null)
{
deletedEntity.Status = ExampleCodebook.ACTIVE;
}

STATE_MACHINE_EXCEPTION

Staged transactions

The changes to the database (Adding, modyfing, deleting) an element will be staged. The changes will apply only after the code has been sucessfully executed. (No uncaught exceptions, No negatve result returned).

If you add an element x to the database, you won't be able to find it until the staged changes are made.

public void ExampleDbAdd(AppDatabase db, long Id)
{
var exampleObject = db.ExampleEntitySet.Add(new ExampleEntity() { ExampleId = Id }); // Adds to the database
bool inDatabase = db.ExampleEntitySet.Any(x => x.ExampleId == Id); // false
...
}

After this method is executed, the exampleObject will be added to the database, but inDatabase will evaluate to false

Keeping track of the staged changes is often useful. These are stored in the entity table .Local. Reffering back to the previous case, the queries will evaluatr as shown below.

public void ExampleDbAdd2(AppDatabase db, long Id)
{
var exampleObject = db.ExampleEntitySet.Add(new ExampleEntity() { ExampleId = Id }); // Adds to the database
bool inDatabase = db.ExampleEntitySet.Any(x => x.ExampleId == Id); // false

bool inLocal = db.ExampleEntitySet.Local.Any(x => x.ExampleId == Id); // true
...
}

A commonly used pattern in a command is checking the local database for an object, and then looking into the application database. This might come useful when parsing data in a command, and collision control is needed.

var found = db.ExampleEntitySet.Local.FirstOrDefault(x => x.ExampleId == Id)   // Note the Local collection use
?? db.ExampleEntitySet.FirstOrDefault(x => x.ExampleId == Id); // Fallback to DB query