Confused with DA/XCode, use the generated code or DARemoteDataAdapter?

So, i finally start to create the client on iOS, to several services in a DA.NET server.

I generate the code and get the proxy. However, in the samples I see is used DARemoteDataAdapter.

At first, I think DARemoteDataAdapter was simple a dynamic invocator, but now when try to get data, I see only DARemoteDataAdapter have beginGetDataTable, and the generated proxy have beginGetData.

So, If I use DARemoteDataAdapter I have a more convenient methods to get data, auto-login, but only the proxy have the custom methods of my server… Plus, I need to send Deltas manually, and the DARemoteDataAdapter requiere send the DATables…

What to use? Need both?

I don’t see how use beginGetData?

Hi

Right, if you added some custom methods to your DataAbstract service, then in order to call them, you will need to create a proxy object and call these methods from there.

DARemoteDataAdapter simplifies working with the base DataAbstractService and with login services.

I don’t see how use beginGetData?

We are supporting two approaches:

  1. Using delegates:

We need to create asynchronous DAAsyncRequest for the particular method. In case when we need to control exact moment of starting such asynchronous request we can specify NO as the start parameter, this will prevent request from being started automatically. Usually we may want to delay execution method until we configure request properly. We may need to specify the delegate instance or/and provide some context for the request. As the delegate we can use any instance of the class which implements DAAsyncRequestDelegate protocol. This protocol exposes set of the methods that could be called at successful completing asynchronous request of at it failure. All of the methods of that protocol are optional so you are free to implement only those you are really need here.

Later, after we configured our request, we can run it using start method which will run our request in the separate thread.

- (IBAction)loadData:(id)sender {
    
	NSArray *fields = [NSArray arrayWithObjects:
                       @"WorkerID", 
                       @"WorkerLastName", 
                       @"WorkerFirstName", 
                       @"WorkerPosition", nil];
    
	// compose asynchronous request but not start it until we configure it properly
	DAAsyncRequest* request = [remoteDataAdapter beginGetDataTable:@"Workers" 
                                                                select:fields
                                                                 where:nil
                                                                 start:NO];

    // setting self as the delegate means that the current class should be able to process 
    // the result of the async call
    [request setDelegate:self];

    // we can also specify any data to pass it to the result processing methods as the request context.
    [request setContext:@"beginGetDataTable request"];

    // run the request
    [request start];
}

When the async method will ends its execution with success, then it will try to find asyncRequest:didReceiveTable: delegate method and invoke it with appropriate parameters. All we need here is to consume received data. Something like following:

- (void)asyncRequest:(DAAsyncRequest *)request 
     didReceiveTable:(DADataTable *)table {

        // here we can obtain request context, we specified before, and use it for own purposes
        id context = [request context];
        NSLog(@"Context is: %@", id);

        // consumes the data
       [self setWorkersTable:table];
       [tableView reloadData];
}

When the async method will ends with failure, then it will try to find and invoke asyncRequest:didFailWithException: delegate method. Here we should add our logic for proper handing various exceptions.

- (void)  asyncRequest:(ROAsyncRequest *)request 
  didFailWithException:(NSException *)exception {

    // handle the exception in right way
    [self showException:exception];
}
  1. Using blocks:
    The similar as above, but it doesn’t require setting delegate since all the code can be specified here in place as the blocks.
- (IBAction)loadData:(id)sender {
    
    NSArray *fields = [NSArray arrayWithObjects:
                       @"WorkerID", 
                       @"WorkerLastName", 
                       @"WorkerFirstName", 
                       @"WorkerPosition", nil];
    
    // compose and run the asynchronous request
    [remoteDataAdapter beginGetDataTable:@"Workers" 
                                  select:fields
                                   where:nil
                               withBlock:^(DADataTable *table) {
                                  // this code will be executed at the main thread  when request ends
                                  [self setWorkersTable:table];
                                  [tableView reloadData];
                               }];
}

if we need to handle possible exceptions then it will be something like following:

- (IBAction)loadData:(id)sender {
    
    NSArray *fields = [NSArray arrayWithObjects:
                       @"WorkerID", 
                       @"WorkerLastName", 
                       @"WorkerFirstName", 
                       @"WorkerPosition", nil];
    
    // compose asynchronous request but not start it until we configure it properly
    DAAsyncRequest* request = [remoteDataAdapter beginGetDataTable:@"Workers" 
                                                                select:fields
                                                                 where:nil
                                                                 start:NO];
    [request setFailureBlock:^(NSException *exception){
        
        // handle the exception in right way
        NSLog(@"%@", exception);                
    }];

    // run the request
    [request startWithBlock:^{

        // this code will be executed at the main thread  when request ends
        [self setWorkersTable:table];
        [tableView reloadData];
    }];
}

Hope this helps

Ok, but that mean is necessary to setup both objects for each service? Because the proxy don’t have the methods in the example you show…

Setup both will be problematic in anya sense? (ie: Will cause 2 session, channels open?)

Hi,

Ok, but that mean is necessary to setup both objects for each service?

If I correctly understand and you mean DARemoteDataAdapter and Service Proxy object under these both objects then yes, you will
need them both,

Because the proxy don’t have the methods in the example you show…

If your custom service is the descendant from the base DataAbstractService then it should already have the GetData & other functionality, and you can use DARemoteDataAdapter on it. Or I probably not completely understand you?

Setup both will be problematic in anya sense? (ie: Will cause 2 session, channels open?)

Since sessions are the global objects you can use the single session to access to even different service. All depends on your login implementation. Also for login you can use the same channel as for getting data.

Thanks

Ok, GetData exist in the generated proxy, but no methods like beginGetDataTable. That are only in DARemoteDataAdapter.

I will workaround creating both (or copy the implementation of GetDataTable from the sourcecode, I remember the code is inlcluded :wink: )

Hi,

I can recommend you to use both DARemoteDataAdapter and generated proxy. Btw for your proxy service you can use copies of your channel and message objects from the DARemoteDataAdapter. Something like following:

ROClientChannel *channel = [[[[remoteDataAdapter dataService] channel] copy] autorelease];
ROMessage *message = [[[[remoteDataAdapter dataService] message] copy] autorelease];

// if you want to use another session for executing proxies methods then you will need to uncomment following line
//[message setClientID:[ROGuid guid]];

asyncCustomService = [[CustomService_AsyncProxy proxyWithMessage:message channel:channel] retain];
customService = [[CustomService_Proxy proxyWithMessage:message channel:channel] retain];

Also please notice that each generated file contains sources for proxies of both kind, usual and async.
Async proxy exposes the same methods like in usual but they can be running asynchronously.

Thanks