Session - STARIONGROUP/COMET-SDK-Community-Edition GitHub Wiki
The Session class is the core class of the COMET-SDK for API developers that wish to develop C# applications that need to interface with ECSS-E-TM-10-25A Annex C. It provides a layer of abstraction for the IDal
interface that exposes the methods that can be used to Create, Read, Update and Delete objects from an Annex C data-source.
The
ISession
interface works with POCO instances, theIDal
interface works with DTO instances.
The Credentials class is used to capture information required to connect to a data-source. It carries the username, password and URI of the data-source. The Credentials
are used to instantiate a Sesssion
object and cannot be changed while the Session
is active.
The Session
class implements the ISession interface that exposes the following core methods:
method | description | async |
---|---|---|
Open | Open a connection to a data-source | y |
Read | Read Things from a data-source |
y |
Update | Update changed Things from a data-source |
y |
Write | Write updates to Things to a data-source |
y |
Refresh | Update the Cache with updated Things from a data-source |
y |
Reload | Reload all Things from a data-source for all open TopContainers
|
y |
Close | Close the connection to a data-source and clear the Cache | n |
The ISession
interface exposes more convenience methods that are explained in the following sections.
The Session
class constructor expects 2 arguments, an instance of IDal
and an instance of Credential
. The IDal
interface represents a Data Access Layer implementation used to perform operations on a ECSS-E-TM-10-25 Annex C data-source.
var uri = new Uri("https://cdp4services-public.cdp4.org");
var credentials = new Credentials("some-user-name", "some-password", uri);
var dal = new CdpServicesDal();
var session = new Session(dal, credentials);
The Open
method connects to the data-source and requests data from the SiteDirectory
route provided by the Annex C data-source. The data-source returns an array of DTO instances that are processed by the Assembler, converted into POCO instances that are add to the Cache. Messages are produced for the objects that are added to the Cache by means of the CDP Message Bus.
try
{
await session.Open();
}
catch(Exception ex)
{
// handle the exception here and don't forget to do some logging
}
The Open
method should be used in combination with await
operator, await
can only be used in an asynchronous method modified by the async
keyword.
The data that is returned contains enough information for the current user to select an
Iteration
or aReference Data Library
to work with.
Five distinct Read
methods are provided by the ISession
interface:
-
public async Task Read(Iteration iteration, DomainOfExpertise domain)
: reads data from the data-source related to a specificIteration
, including all the objects that are contained by the specifiedIteration
. -
public async Task Read(ReferenceDataLibrary rdl)
: reads data from the data-source related to a specificReferenceDataLibrary
, including all the objects that are contained by the specifiedIteration
. -
public async Task Read(Thing thing)
: reads anyThing
from the data-source. -
public async Task Read(Thing thing, IQueryAttributes queryAttributes)
: reads anyThing
from the data-source and takes an extra parameterIQueryAttributes
to construct extra read constraints. -
public async Task Read(IEnumerable<Thing> things, IQueryAttributes queryAttributes)
: reads an enumerable list of anyThing
from the data-source and takes an extra parameterIQueryAttributes
to construct extra read constraints.
The IQueryAttributes
interface is used to specify constraints on the Read
method. It is typically used to readd all revisions of a specifc Thing
.
RevisionNumber: Returns the set of all objects contained by the Thing that have a revisionNumber that is greater than the given value. This enables getting the net change of objects since a previous revision
FromRevisionNumber: Specifies, using an integer, that all revisions of an object are requested starting at the specified lower revision. If no revisionTo is specified the range that is requested includes all revisions until the most recent revision.
ToRevisionNumber: Specifies, using an integer, that all revisions of an object are requested until the specified upper revision. If no revisionFrom is specified the range that is requested starts a revision 0.
FromRevisionTimestamp: Specifies, using a TimeStamp, that all revisions of an object are requested starting at the specified lower revision. If no revisionTo is specified the range that is requested includes all revisions until the most recent revision.
ToRevisionTimestamp: Specifies, using an TimeStamp, that all revisions of an object are requested until the specified upper revision. If no revisionFrom is specified the range that is requested starts a revision 0.
Most concepts contained by an Iteration
are owned by a DomainOfExpertise
. The Session
class maintains a list of opened Iterations
and the DomainOfExpertise
used to open that Iteration
in the OpenIterations
property.
In order to read an Iteration
from a data-source a temporary container EngineeringModel
and Iteration
object need to be created. The session.Open()
method retrieves data from the SiteDirectory
which does not contain the EngineeringModel
and Iteration
objects. It does however contain the EngineeringModelSetup
and IterationSetup
objects. These setup objects represent meta-data regarding the EngineeringModel
and Iteration
that we can use to create the Iteration
object used in the Read
method.
try
{
// assume that you know the unique identifier of the EngineeringModel, the Iteration, and DomainOfExpertise object that you want to open.
// These can be retrieved from the cache based on the EngineeringModelSetup and IterationSetup objects that were returned with the Open method
var engineeringModel = new EngineeringModel(Guid.Parse("694508eb-2730-488c-9405-6ca561df68dd"), session.Assembler.Cache, session.Credentials.Uri);
var iteration = new Iteration(Guid.Parse("44647ff6-ffe3-44ff-9ed9-3256e2a97f9d"), session.Assembler.Cache, session.Credentials.Uri);
// construct a containment chain -> this is used to compute the route of the Iteration that is to be retrieved from the data-source
engineeringModel.Iteration.Add(iteration);
// get the DomainOfExpertise from the Cache (loaded when the session.Open method was called)
Lazy<Thing> lazyDomainOfExpertise;
session.Assembler.Cache.TryGetValue(new CacheKey(Guid.Parse("8790fe92-d1fa-42ea-9520-e0ddac52f1ad"), null), out lazyDomainOfExpertise);
// read the Iteration
await session.Read(iteration, (DomainOfExpertise)lazyDomainOfExpertise.Value);
}
catch(Exception ex)
{
// handle the exception here and don't forget to do some logging
}
Messages are produced for the objects that are added and/or updated to the Cache by means of the CDP Message Bus.
Since march 2020 the COMET SDK is capable of receiving extra constraints for Read actions in the form of the IQueryAttributes
class.
This class is used to construct ECSS TM 10 25 Annex C
request query attributes.
Annex C provides the capability to query only those objects that have changed, meaning: changed since the last time the Thing
was updated. This is a means to limit the trafic between the client and data-source. The ISession
interface exposes the Update
method for this purpose. The revision numnber, which is maintained by the data-source for each Thing
is used to determine the delta's that need to be returned by the server.
try
{
// Update the Iteration that was previously read using the Read method.
await session.Update(iteration);
}
catch(Exception ex)
{
// handle the exception here and don't forget to do some logging
}
Messages are produced for the objects that are added and/or updated to the Cache by means of the CDP Message Bus.
The Write
method is used to write updates to Things
. Multiple Things
can be updated in one transaction. Annex C specifies that 2 routes can be used to update any data in a data-source. The SiteDirectory
and Iteration
routes support updates, any other routes do not support updates. Any data that is contained in the SiteDirectory
containment that needs to be added, updated or deleted is sent to the SiteDirectory
route; Any data that is contained in the EngineeringModel\{iid}\Iteration{iid}
containment that needs to be added, updated or deleted is sent to the EngineeringModel\{iid}\Iteration{iid}
route. In COMET-SDK terms this is handled by the ThingTransaction
, OperationContainer
and Operation
classes. Annex C does not allow Things
contained by the SiteDirectory
and an Iteration
to be updated in the same transaction.
Note: concepts that are contained by an
EngineeringModel
, but are not in the containment tree of anIteration
are also sent to anIteration
route, e.g.ModelLogEntry
.
The following example shows how to add an ElementDefinition
to an Iteration
:
// get the Iteration that the new ElementDefinition needs to be added to from the cache
Lazy<Thing> lazyIteration;
session.Assembler.Cache.TryGetValue(new CacheKey(Guid.Parse("44647ff6-ffe3-44ff-9ed9-3256e2a97f9d"), null), out lazyIteration);
var iteration = (Iteration)lazyIteration.Value;
// set the context of the transaction to the iteration the new ElementDefinition needs to be added to.
// Only a SiteDirectory or Iteration object can be set as context.
var context = TransactionContextResolver.ResolveContext(iteration);
var transaction = new ThingTransaction(context);
// Create a shallow clone of the iteration, the new ElementDefintion will be added to this object. The cached
// Iteration object should not be changed, so we record the change on a clone.
var iterationClone = iteration.Clone(false);
// Create a new instance of ElementDefinition
var elementDefinition = new ElementDefinition();
elementDefinition.ShortName = "BAT";
elementDefinition.Name = "Battery";
elementDefinition.Owner = domainOfExpertise;
// register the new ElementDefinition and the container Iteration (clone) with the transaction.
transaction.Create(elementDefinition, iterationClone);
// finalize the transaction, the result is an OperationContainer that the session class uses to write the changes
// to the Iteration object (the list of contained elements is updated) and and the new ElementDefinition.
var operationContainer = this.transaction.FinalizeTransaction();
try
{
await session.Write(operationContainer);
}
catch(Exception ex)
{
// handle the exception here and don't forget to do some logging
}
The Refresh
method is used to query a data-source for all Things
that have changed. The Refresh
method uses the Update
method performs an Update
on the SiteDirectory
and all Iterations
that have been Read
by the session.
try
{
await session.Refresh();
}
catch(Exception ex)
{
// handle the exception here and don't forget to do some logging
}
Messages are produced for the objects that are added and/or updated to the Cache by means of the CDP Message Bus.
The Reload
method is used to query a data-source for all Things
in the context of the SiteDirectory
and the open Iterations
of the session. Where the Refresh method is used to get the delta's, the Reload
method is used to get all data, regardless of whether it has been changed or not.
try
{
await session.Refresh();
}
catch(Exception ex)
{
// handle the exception here and don't forget to do some logging
}
Messages are produced for the objects that are added and/or updated to the Cache by means of the CDP Message Bus.
The Close()
method closses the connection the underlying IDal
has to the datasource, clears the Cache, the OpenReferenceDataLibraries
as well as the OpenIterations
.
Once the Session
has been closed a SessionEvent
is sent through the CDP Message Bus notifying listeners that the Session
has been closed. This can used by GUI implementations to perform any clean-up that may be required once a Session
has been closed.
try
{
await session.Close();
}
catch(Exception ex)
{
// handle the exception here and don't forget to do some logging
}