Console
The Simple Data Operations and Simple Data Operations Async console samples demonstrate the most basic & common interactions you will make to an instance of Relativity Server. It shows how to:
- connect to the server
- retrieve a table from the server
- add a row to the retrieved table and apply that change to the server
- update/change the contents of a row and apply that change to the server
- delete a row from the table and apply that change to the server
The difference between the two samples is simply that one uses a synchronous method of communication where the program waits until the method completes, on the other hand the asynchronous method returns immediately and handles the communication in a background thread.
Getting Started
The Console sample is typically located in /Developer/RemObjects Software/Samples/Data Abstract/Console/SimpleDataOperations
, though you may have installed the Data Abstract for Cocoa and it's samples in another location.
To build it, you will of course need Xcode, and like all the samples provided with Data Abstract for Cocoa you will need to be running the Relativity Server with the DASamples
Domain and the Simple
Schema available.
Lastly this sample makes use of a convenience method (DALogTable
) provided by a class extension to NSArray that we ship with Data Abstract for Cocoa. It is actually a #define method that uses one of three new log methods added to NSArray
to print the contents of a DADataTable in a pretty fashion to the console using NSLog. To use this in your own code you must add the following to your import statements #import <DataAbstract/NSArray+DADataTableLog.h>
. Please note that this class extension is intended for test purposes only.
Running the Sample
When run the sample sets up a connection to an instance of Relativity Server and logs in (Step 1). It then retrieves the "Deps" table and prints the table to the console (Step 2). It then inserts a new row with a department name ("DepName") of "Security" and phone number ("DepPhone") before applying those changes to the original on the server (Step 3). The phone number is then updated to a new value (Step 4) before the new row is deleted from the table (Step 5).
Examining the Code
All of the code can be found in the main.m source file. All of the #define values are at the top of the .m file.
The Deps
schema table used here has three fields:
DepId
is the primary key and use anAutoInc
data type.DepName
is a string of up to 50 characters and is required for each new rowDepPhone
is also a string of up to 50 characters, the field is optional.
Setting up a Connection (Step 1)
There are three stages to setting up a connection to an instance of Relativity Server.
In the first stage we initialize the underlying services we wish to establish a connection with on the server. We create two RORemoteServices objects (which are part of the Remoting SDK), the first is the data service which will be used to retrieve and update data and schema information. The login service defines the service that should be called if authentication is required. The loginService
object is simply a copy of the dataService
object, with the serviceName
property changed to LOGIN_SERVICE_NAME
, it could be created like the dataService
object, just passing in LOGIN_SERVICE_NAME
instead.
The second stage is to configure a DARemoteDataAdapter object that we interact with to communicate with the server. It's constructor takes the two services we created previously. At this point we have a working connection but we will be unable to manipulate the schema data until we log in. Attempting to do so will cause an ROException
exception to be thrown with the message "Session could not be found.".
The final stage passes a special login string (LOGIN_STRING
) to the loginWithString method to establish a login session. The loginWithString
method returns a boolean which will be true
if the login attempt was successful or false
if it failed. The login string is comprised of 4 parts:
- Username the username to attempt to login with
- Password the password to use
- Domain the name of the domain that the schema is located in
- Schema the name of the schema we wish to use
For example, the login string from this sample is "User=simple;Password=simple;Domain=DASamples;Schema=Simple"
NOTE If there is a problem attempting to communicate with the server, or if the schema or domain name is incorrect then an ROException
will be thrown and should be handled appropriately.
// Initialize SDK layer
NSURL *url = [NSURL URLWithString:TARGET_URL];
NSLog(@"Target URL is %@.", url);
RORemoteService *dataService = [[RORemoteService alloc] initWithTargetURL:url serviceName:DATA_SERVICE_NAME];
RORemoteService *loginService = (RORemoteService *)[dataService copy];
loginService.serviceName = LOGIN_SERVICE_NAME;
NSLog(@"RO SDK layer is configured.");
// Initialize DA layer
DARemoteDataAdapter *dataAdapter = [[DARemoteDataAdapter alloc] initWithDataService:dataService loginService:loginService];
NSLog(@"RO DataAbstract layer is configured.");
// Login to DA Service
NSLog(@"STEP 1: Login to DataService");
NSLog(@"Login string is %@.", LOGIN_STRING);
@try {
BOOL logged = NO;
logged = [dataAdapter loginWithString:LOGIN_STRING];
if (!logged) {
NSLog(@"Unsuccessful login. Please check your login and password. Exiting...");
return 1;
}
}
@catch (NSException *exception) {
NSLog(@"Exception happened: %@", exception.reason);
NSLog(@"Exiting...");
return 0;
}
NSLog(@"Login has been successfull. Going further...");
Retrieving a Table (Step 2)
To retrieve a copy of a table from the schema we need to use the getDataTable method which takes the name of the table as a string and returns a DADataTable.
Variants of getDataTable exist that allow you to retrieve only a subset of a table using an SQL statement, or Dynamic Select and Dynamic Where objects, or retrieve multiple tables at once. There are also asynchronous variants of all of the methods.
NOTE Passing an invalid table name to the getDataTable
method will result in an ROException
being thrown which should be handled accordingly.
NSLog(@"STEP 2. Select the data (List of departments) ...");
DADataTable *table = [dataAdapter getDataTable:@"Deps"];
DALogTable(table);
Inserting a row (Step 3)
Each table is made up of multiple DADataTableRow objects. Each one representing a row in the schema table and its columns. To add a new row to the table, we use the addNewRow factory method of DADataTable which appends a new row to the table and returns a reference to it. The values for all of the columns will be initially set to null
, except for any columns that use an AutoInc
value in which case they will be assigned a negative value.
To set a value for a field, you use a dictionary accessor passing in the name of the key and assigning a string object as a value. Here we set the DepName
to "Security" and the DepPhone
to "(873)000-00-00". The DepId
field uses AutoInc
and is assigned -1
which you can see in the example output at the bottom of this page.
NOTE Passing an invalid column name to dictionary accessor will result in an ROException
being thrown which should be handled accordingly.
At this stage only the local copy of the DADataTable has the new row, to apply those changes to the server version we need to use the applyChangesForTable. This method extracts a delta of changes from the given table and passes it to the server, then it receives incoming delta and merges those changes into the local table. This means when we check the value DepId
after applying the changes it now has a value of 8 (in the output below) rather than -1.
NSLog(@"STEP 3. Insert a new row (Security department)...");
DADataTableRow *addedRow = [table addNewRow];
addedRow[@"DepName"] = @"Security";
addedRow[@"DepPhone"] = @"(873)000-00-00";
DALogTable(table);
NSLog(@"Apply changes....");
[dataAdapter applyChangesForTable:table];
NSLog(@"Changes has been applied. New department has got an ID %@", addedRow[@"DepId"]);
DALogTable(table);
Updating a row (Step 4)
To update the a field, we do the same as in Step 3; we assign a new value to the dictionary for a particular key and apply the changes to the server. Here we update the DepPhone
field to "(873)456-77-77" which only replaces the local value until applyChangesForTable is called.
NSLog(@"STEP 4. Modify row (Change phone for added department)...");
addedRow[@"DepPhone"] = @"(873)456-77-77";
NSLog(@"Apply changes....");
[dataAdapter applyChangesForTable:table];
NSLog(@"Changes has been applied");
DALogTable(table);
Deleting a row (Step 5)
To remove a row from a table you need to use the removeRow method which takes the DADataTableRow you want to remove. The change is added to the changedRows
list, which is a list of all DADataTableRows that have modifications. Again to delete the row on the server, we need to call applyChangesForTable which will update the server and then the local table accordingly.
There is a variant of removeRow
, removeRowAtIndex, that takes an index for the row you wish to delete; note that this index value is simply the position the row has in the table and has no relation to the DepId
value. So to delete the new row we would use an index value of 3 (Starting counting from 0)
NSLog(@"STEP 5. Delete row (Remove added department)...");
[table removeRow:addedRow];
NSLog(@"Apply changes....");
[dataAdapter applyChangesForTable:table];
NSLog(@"Changes has been applied");
DALogTable(table);
Example Output
This is an example of the output you will see when the sample is run. In Step 2 you can see there are three rows in the Deps
table, in Step 3 there are now 4 rows and that in Step 4 the phone number for the Security
department has changed. Lastly in Step 5 there are once again only three rows.
Target URL is http://localhost:7099/bin.
RO SDK layer is configured.
RO DataAbstract layer is configured.
STEP 1: Login to DataService
Login string is User=simple;Password=simple;Domain=DASamples;Schema=Simple.
Login has been successfull. Going further...
STEP 2. Select the data (List of departments) ...
TABLE: Deps (3 rows from 3)
-----------------------------------------------------------
| DepId | DepName | DepPhone |
-----------------------------------------------------------
| 1 | Sales | (873)456-78-99 |
| 2 | Incomes | (873)456-78-88 |
| 4 | Test | (999)456-78-11 |
-----------------------------------------------------------
STEP 3. Insert a new row (Security department)...
TABLE: Deps (4 rows from 4)
-----------------------------------------------------------
| DepId | DepName | DepPhone |
-----------------------------------------------------------
| 1 | Sales | (873)456-78-99 |
| 2 | Incomes | (873)456-78-88 |
| 4 | Test | (999)456-78-11 |
| -1 | Security | (873)000-00-00 |
-----------------------------------------------------------
Apply changes....
Changes has been applied. New department has got an ID 8
TABLE: Deps (4 rows from 4)
-----------------------------------------------------------
| DepId | DepName | DepPhone |
-----------------------------------------------------------
| 1 | Sales | (873)456-78-99 |
| 2 | Incomes | (873)456-78-88 |
| 4 | Test | (999)456-78-11 |
| 8 | Security | (873)000-00-00 |
-----------------------------------------------------------
STEP 4. Modify row (Change phone for added department)...
Apply changes....
Changes has been applied
TABLE: Deps (4 rows from 4)
-----------------------------------------------------------
| DepId | DepName | DepPhone |
-----------------------------------------------------------
| 1 | Sales | (873)456-78-99 |
| 2 | Incomes | (873)456-78-88 |
| 4 | Test | (999)456-78-11 |
| 8 | Security | (873)456-77-77 |
-----------------------------------------------------------
STEP 5. Delete row (Remove added department)...
Apply changes....
Changes has been applied
TABLE: Deps (3 rows from 3)
----------------------------------------------------------
| DepId | DepName | DepPhone |
-----------------------------------------------------------
| 1 | Sales | (873)456-78-99 |
| 2 | Incomes | (873)456-78-88 |
| 4 | Test | (999)456-78-11 |
-----------------------------------------------------------
Done!
Program ended with exit code: 0