You are browsing the archive for ROFX.

Avatar of marc

by marc

iOS 7 and OS X Mavericks

June 17, 2013 in Cocoa, iOS, Mac, Oxygene, ROFX, WWDC, Xcode

As you have probably heard by now, last week Apple announced iOS 7 and OS X Mavericks, new major versions of both its flag-ship operating systems. I had the privilege of being on site in San Francisco and attending WWDC in person, but the keynote with the core announcements is available for public viewing by anyone, and the remaining ~100 sessions of the conference are also available for free to all registered developers (major kudos to Apple for that, and more importantly, for making these videos available so fast, in most cases on the same day as the actual presentations!).

iOS 7 is a major new release and – most observers agree – a game changer. It’s a whole new UI paradigm for the OS, and will be a very exciting release for both users and developers; there are a whole bunch of new technologies that will let you create even better iOS apps, and will make the whole iOS experience even better for the user — in the core OS or with your apps.

Due to the massive UI overhaul, most iOS apps will need a serious rethinking for iOS 7 to stay relevant – which means extra work for developers, but also extra opportunities. From what i can tell (and am allowed to tell), switching an application over to the core iOS 7 “look” will be simple, but really making an app feel at home on iOS7 will require a lot of thought — no way around it.

I have already started moving two of our (internal) apps to iOS 7 while on site in San Francisco, simply because after (foolhardily) upgrading my main phone to the new OS, i could no longer stand looking at the old UI ;). One app is “done” and was relatively straight-forward – mainly a matter of rebuilding with the iOS 7 SDK, and making a few adjustments here and there to better embrace the new style; the other will be more work.

OS X Mavericks (if you don’t like the name, you are not alone. Virtually everybody i talked to or heard talk about it found it “weird”) is a smaller upgrade, by comparison, but also a significant release with a ton of exciting technologies for developers – two that were highlighted in the keynote include the new Maps API and cool new energy-saving APIs and technologies. (And if you’re not excited by being able to make your apps more power-efficient, then you have no business developing Mac apps! ;).)

Of course the big question you’re all asking is how Oxygene for Cocoa is working with the new iOS 7 and OS X Mavericks. The good (and slightly unexciting, because expected) news is: it works just fine. We’ve long had an article on the Wiki that discusses the (simple) steps for hooking up Oxygene with new beta SDKs, and Oxygene is working fine with iOS 7 and with Mavericks (although i do recommend grabbing the latest beta drop of Oxygene, as we already made some tweaks and improvements there).

All the new APIs (IIRC Apple mentioned a number of 1500 new APIs being available) will work with Oxygene out of the box – no need to wait for anyone to create any wrappers or headers for you, and re-building your Oxygene apps with the iOS 7 SDK will give you the new iOS 7 look right away (but not save you from re-examining how to really embrace iOS 7 best with your app, of course).

There are also a few new non-API features that we’ll be embracing with Oxygene as well, but unfortunately those are (afaict) all under NDA, so i cannot talk about them yet. But suffice to say over the next few months we will of course be doing a lot of testing with Oxygene and the new APIs and SDKs to keep Oxygene up to date with the SDKs and the Xcode 5 tool chain.

Of course we’ll also be testing Data Abstract and RemObjects SDK for Cocoa with the new SDKs, and (where applicable) expanding them with support for new APIs. In my testing so far, they work great (both the apps i mentioned above are DA-based, and run fine on iOS 7, for example).

Support

Talking about new iOS and OS X SDKs is always a tightrope walk, as there’s a lot of information that’s under NDA (but available to all registered Apple developers – so do make sure you check out the beta builds and all the videos from WWDC). But Oxygene, as well as RO/DA for Cocoa, are already working great with the new operating systems, and we’ll be working hard to expand those parts that do need explicit support and work to fully embrace the new OSs.

If you have any specific questions regarding support for or issues with the new SDKs, there’s two places to get help: for one, we’ll be monitoring and participating in Apple’s beta forums, so you can post questions about Oxygene there (maybe add “(Oxygene)” to the subject so we can find them easier). And you can also always directly email support.

We cannot discuss the iOS 7 or OS X Mavericks Beta SDKs on Connect; you could be violating your NDA by posting details there, and we’d be doing the same by answering. So be careful.

Summary

I’m very excited about both iOS 7 and Mavericks (and i assume i’ll eventually get over the name, too), and so should you. I’m looking forward to seeing what you’ll build on the new OSs with Oxygene and Data Abstract.

RemObjects SDK Beginners Guide

May 22, 2013 in .NET, ROFX

Intro

RemObjects SDK is an awesome framework. Not only because its development feeds me and my 10 cats ;) but also because it allows to efficiently create applications on literally a dozen different platforms (to name them: Win32 (a.k.a. Delphi apps), desktop .NET framework, Windows Phone, Silverlight, Mono, Android, Android via MonoAndroid, iOS, iOS via MonoTouch, native MacOS X apps, Java and JavaScript). Unfortunately, it takes a bit of time to get started with developing, you can’t just jump right in. I myself (and most of the software developers I know) usually want to try their new, just downloaded toy without reading a ton of documentation pages.

So this article will try to be a kind of “crash course”. It won’t go very deep (there are Wiki articles on just about anything, if you want to delve in deeper, and our support team will help you with any questions), it will just try to give you some ‘feeling’ for the tech, a foothold to conquer the new framework.

This article covers the .NET version of the RemObjects SDK, however, the main approach will remain the same for all platforms (.NET, Xcode, Delphi, Java, JavaScript), so you won’t waste your time with this article, even if you don’t use .NET in your development work.

My colleagues will provide similar articles devoted to the other supported platforms later this month.

Note: This article covers the ‘Client Calls The Server’ scenario and doesn’t touch the ‘Server Pings The Client’ one. At this moment it is enough to know that the latter scenario is possible as well and its implementation won’t affect the former one.

The Core

The very heart of the RemObjects SDK is based on ChannelsMessagesEnvelopes and Services. Two more components used under the hood are Interfaces and Invokers. Don’t be afraid of these words, things are actually simpler than they look.

Let’s take a look at the ‘Client calls the server method’ scenario:

var methodCallResult = sampleService.DoSomething();

Looks simple, doesn’t it?

Here’s what happens from the RemObjects SDK’s point of view:

The client code calls the Foo method of some object serverService. Here, sampleService is an instance of the auto-generated proxy class, so calling the sampleService.DoSomething() method actually means the following:

1. Sending out a request
The Interface class serializes the request to the server using the configured Message. The Message is then wrapped by the attached Envelopes, if any are set up (f.e. data is encrypted somehow). Then the resulting data package is sent over the wire by the Client Channel.

2. Processing the request on the server side
The Server Channel retrieves the data package and pushes it to the Message component. Message unwraps it using the attached Envelopes, if needed. The resulting data package is provided to the Invoker, which reads the requested service, method names and method parameters from it.

Then the Service method is invoked, which does the actual job.

After the service method has finished, its result (or any exceptions occurred) are serialized, wrapped, and sent back over the wire using the Server Channel (yes, the processing pipeline is similar to step 1).

3. Retrieving the response
The Client Channel retrieves the data package, unwraps it and provides the serialized data package to the Interface‘s method that initiated the remote service call. This method then deserializes the provided data package and provides the method result back to the user code.

RemObjects SDK Overview

The magic is that the entire process is transparent for the user code on both ends of the wire and doesn’t require much attention from the developer. While the service method call pipeline might seem complicated (or even over-complicated), its performance overhead is negligible (especially for the binary serialization-based Message), making the actual network speed the main issue to care about, not the inner RemObjects SDK processes.

Sample Server

Let’s create a sample server and client app in a step-by-step guide and see how the ChannelsMessagesEnvelopesInterfacesInvokers and Services entities are implemented in a real RemObjects SDK-based application.

Prerequisites

For this tutorial you’ll need Visual Studio and either the RemObjects SDK for .NET or the Data Abstract for .NET frameworks installed. Also, a minimal knowledge of C# is required, but the same concepts would apply to Visual Basic for .NET, Oxygene or any other .NET language.

Server Application

As mentioned above, the server application should contain the Server ChannelMessageEnvelope (if needed) and Invoker, as well as the Service itself.

1. Create a new Class Library project named BusinessLogic and add a single class to it:

using System;

namespace BusinessLogic
{
    public class StringProcessor
    {
        public Int32 Process (String value)
        {
            if (String.IsNullOrEmpty(value))
                return -1;

            return (value + @"Secret Salt").GetHashCode();
        }
    }
}

This project imitates an already existing implemetation of a real-world business logic method that should be exposed to remote client applications. While it is not necessary to put the business logic into a separate project, it was done here to emphasize that the business logic layer is fully separated from the to-be-implemented communication layer.

2. Add a new Windows Forms project to the solution and name it SampleServer. Of course, a real-world server application should be running as a Windows Service (and RemObjects SDK provides the needed application template), but for this “crash course” it will be easier to use the simple Windows Forms project.

3. Add the following references to the SampleServer project, as they provide the needed classes:

  • RemObjects.InternetPack.dll
  • RemObjects.SDK.dll
  • RemObjects.SDK.Server.dll
  • RemObjects.SDK.ZLib.dll

Also add a reference to the previously created BusinessLogic project, as we will expose its methods in the server.

4. Now we need to define the Server Surface Area, i.e. the service name, its methods, their parameters and return values, etc. This step is needed to allow the RemObjects SDK to generate strongly-typed Interface and Invoker classes.

Add a new ‘RemObjects SDK Service Definition’ item to the project.

Adding New Item

A new file named NewLibrary1.RODL will be added to the project and the Service Builder app will be started automatically. The RODL is an XML file containing the service definition written in the ‘RemObjects Definition Language’ (or RODL), and the Service Builder provides the GUI to edit .RODL files without diving into the definition language syntax. Please note that the RemObjects SDK exposes the object model that allows to load, parse and generate .RODL files (and even to generate code based on these files), but this topic is outside the scope of this article.

Service Builder

As you can see, the file is almost empty. Select the single topic in the tree on the left side of the app’s window. The edit boxes that will appear will allow you to change the library name, set its namespace or even write its definition. Set the Library name to BusinessLogicLibrary.

Library contains all the entities in the given RODL file. Consider it as a root of a service definition tree.

The next step is to define the Service. Press the ‘Service’ button (or right-click the Library name in the tree and issue the ‘Service’ context menu command) and rename the just added Service to BusinessLogicService

Now we can define this service’s methods. Press the ‘Add Operation’ button (the one with the green “+” glyph). A new method named ‘NewMethod’ will be added. Double-click its definition and change the method’s name to Process.

The last step is to define this method’s parameters and set its return type. Press the ‘Add Parameter’ button and change the parameter’s name to ‘value’. Change the parameter’s type to Utf8String (the ‘Data Type’ editor allows to select a type name from a combo box, so there is no need to enter it manually).

Set the Result type to Integer (the type name can be selected from the combo box as well).

If everything was done right, the Service Builder window should now look like this:

Service Definition

Close the Service Builder.

Set the ‘Build Action’ of the just added RODL file to ‘Embedded Resource’, so it will be embedded into the compiled application. You will find out why this is needed below.

5. As you can see, once you closed the Service Builder, three new code file were added to your project: BusinessLogicLibrary_Intf.csBusinessLogicLibrary_Invk.cs and BusinessLogicService_Impl.cs.
BusinessLogicLibrary_Intf.cs contains the Interface classes, BusinessLogicLibrary_Invk.cs contains the set of Invoker classes and BusinessLogicService_Impl.cs is a blank Service implementation class.
There is no need (and it is NOT recommended) to edit the code in the first two files.

In case you change the RODL file (for example add one more method to the service definition), the *_Intf and *_Invk files will be regenerated automatically to reflect the RODL changes. At the same time the _Impl file will stay untouched to prevent any code loss. Since the service implementation class contained in the _Impl file implements the service interface contained in the _Intf file, the service project won’t be able to build until the Service implementation class will match the Service definition.

For example: If you add a method to a service definition, the interface representing this service in the _Intf file will contain the new method definition as well. And because the Service implementation class has to implement this interface, the developer will have to add the corresponding method implementation to the service definition class.

6. Open the Service Implementation file (i.e. BusinessLogicService_Impl.cs) and find the Process method implementation. It is empty, so change it to

public virtual int Process(string value)
{
    return (new BusinessLogic.StringProcessor()).Process(value);
}

At this time, we have defined and implemented a Service (and it probably took more time for you to read the text above than to actually execute the steps in Visual Studio). Now we need to make the service available remotely.

7. Below, we will manually implement the network connectivity layer using the RemObjects SDK components. This is done to demonstrate the ins and outs of the framework as the RemObjects SDK provides the application templates and (starting from the May 2013 release) the pre-implemented NetworkServer class that allows to implement the connectivity layer in literally 3 lines of code.

Open the main form in designer mode (remember that our server app is intentionally primitive, so no properly layered architecture or ‘Run As Windows Service’ support here):
* Add the IpHttpServerChannel and BinMessage components to the main form (note that a licenses.licx file was automatically added to the server app project. Please do not delete this file).
* Open the properties of the IpHttpServerChannel component and open the custom editor for the Dispatchers property.
* Press the ‘Add’ button and select the previously added BinMessage instance as a value for the Message property.

Channel Properties

* Press OK to close the dialog and save the property’s value.

That’s it. The server message processing pipeline (i.e. the Server Channel and Server Message) is set up.

8. Open the code-behind file of the main form and add this code line to the very end of the main form class constructor:

this.ipHttpServerChannel1.Open();

This code line will ‘open’ the server channel so it will start to accept the incoming connections.

Now you can start the server app. Open a web browser and go to the page http://localhost:8099/rodl. The server app will show the contents of the embedded RODL file at this address. Note that you can always set the the ’Embedded Resource’ property to None for the RODL file and the server will not advertise its methods.

Client Application

Even the most advanced server application is useless if there is no client application for it. So… let’s create one!

If you remember, a client application needs the following components implemented: ChannelMessage, (possibly) Envelope and Interface. This may look scary again, but it will be much easier than it sounds.

1. Create a new Console Application (for simplicity reasons).

2. Add references to the assemblies

  • RemObjects.InternetPack.dll
  • RemObjects.SDK.dll
  • RemObjects.SDK.ZLib.dll

These assemblies provide the client connectivity classes (as you can see, there is no need to reference the RemObjects.SDK.Server.dll assembly).

3. Now issue the ‘Add’ -> ‘Existing Item’ command (available via the context menu for the client application project entry in the Solution Explorer).

4. Select the BusinessLogicLibrary_Intf.cs file (it can be found in the server’s project folder) and add it as a link.

Adding the _Intf file as a link has a little but important advantage over simply adding an existing file to the client app project: when the server RODL is changed, the _Intf file is automatically regenerated. If this file is added as a link, there will be no need to update the _Intf file copy contained in the client app project.

This step adds the Interface part of the client app.

4. Add the following code to the Program.cs:

using System;

namespace SampleConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.Write("Enter string: ");
            String value = Console.ReadLine();
            Console.WriteLine();
            Console.WriteLine("Processing...");

            // Communicating with the server
            SampleServer.IBusinessLogicService service = new SampleServer.BusinessLogicService_Proxy(@"http://localhost:8099/bin");

            Int32 hash = service.Process(value);

            Console.WriteLine();
            Console.WriteLine("String entered: {0}", value);
            Console.WriteLine("String hash: {0}", hash);
            Console.WriteLine("Press ENTER to continue...");
            Console.ReadLine();
        }
    }
}

The Console.WriteLine and Console.ReadLine calls here are pretty usual for any console application. Let’s take a closer look at these code lines:

// Communicating with the server
SampleServer.IBusinessLogicService service = new SampleServer.BusinessLogicService_Proxy(@"http://localhost:8099/bin");
Int32 hash = service.Process(value);

Here, a proxy for a server app service is created and then a service method is called (the Channel and Message components are automatically created behind the scenes to make this possible).

The IBusinessLogicService interface lists all methods exposed by the remote service, while the CoBusinessLogicService.Create static method creates a proxy class that implements this interface. This makes it possible to perform calls to a remote server transparently for the client app’s code.

5. There are probably some explanations needed regarding where the “http://localhost:8099/bin” URL came from. Let’s take a closer look on each part of the URL:

  • http – Protocol used by the server channel. In this sample, we use a simple HTTP channel. The RemObjects SDK supports several other communication protocols as well (f.e. TCP-based ones).
  • localhost – Name or IP address of the server’s host.
  • 8099 – Port the Server Channel is listening to. 8099 is the default port for the IpHttpServerChannel used in our server application.
  • bin – So-called dispatcher name. This is the name of the Message on the server side that processes the incoming data package. bin is the default name for the BinMessage.

6. Build and start both the server and client applications. Enter any string into the client application window and see the result returned by the server app:

Client Application

Conclusion

At this point you should have a basic understanding of how the RemObjecs SDK-based communications can be implemented. As an exercise, try to add one more method to the Service and call it.

This article doesn’t cover many (or even most) of the RemObjecs SDK features. Server Events, Envelopes, client authentication processing and SSL support were not covered for simplicity reasons. Search our Wiki for the questions you are interested in. If for some reason you can’t find the info you need, don’t hesitate to call on our support via RemObjects Connect or email to support@remobjects.com.

Data Abstract for Java Samples on Google Play

April 2, 2013 in Android, Java, ROFX

I’m happy to announce the availability of the DA SQL Sample – our first, but definitely not last, sample application that is available on Google Play. It is written in Java and powered by our Data Abstract for Java framework.

DA SQL Sample on Google Play

Now it is even easier for you to give the possibilities of Data Abstract for Java a try. Just install it on your device and try to fetch some data using SQL from our externally available PCTrade Sample Server. The sample is preconfigured to talk to http://remobjects.com:8099/bin, but you can change it on the Settings screen and direct the application to any locally accessible DA Sample Server. Make sure to also try the other available settings.
da-sql-android-initial-view-skinned
Other details about the usage and the concepts covered can be found at the sample’s wiki page.

More samples will be available in the near future. Meanwhile, please note that you can always download and install Data Abstract for Java and compile and run any sample manually. These samples can give you a good starting point in developing your own application with the Data Abstract for Java framework, be it for Android or any other Java-powered target platform.
da-sql-android-tablet-skinned

P.S. We have published two more Android samples lately.

Filters Sample shows how to use Dynamic Where and Dynamic Select features for obtaining data from the Data Abstract servers.
wiki page, Play link

Simple Sample shows basic Data Abstract functionality, including loading, changing and updating of data from and back to the Data Abstract servers.
wiki page, Play link

simple-sample-clients-list-framedframed_group-selected-framed-2

Install, try them ant tell us what you think!

Avatar of marc

by marc

“The Truth is in the Cloud” — Why iCloud Data is Failing You, and How Data Abstract can Help.

March 27, 2013 in iOS, Mac, ROFX

The past few weeks, everybody has been complaining about iCloud. Or more precisely, they have been complaining about a small subfeature that is crucial to app developers: Core Data syncing via iCloud. Developers are concerned that data syncing via iCloud is difficult and unreliable, and that when things go wrong (and the invariably will), they have little to no recourse to investigate or debug the issues.

Frankly, i’m not surprised about these issues, because from where i stand, Core Data in iCloud uses a fundamentally wrong approach that can only fail. Let’s see how that is so.

Do you remember when Steve Jobs took the stage at WWDC a couple of years back and introduced iCloud? It was going to be better than all of Apple’s previous cloud services, and to explain the reason why, Steve used one catch phrase: “The truth is in the cloud”. Developers rejoiced and gave a standing-o — and rightfully, because Steve was correct.

For a cloud service to work reliably, the “truth” — that is, the authoritative representation of what your data is — needs to be in one central place. The cloud.

And Steve was not lying to us. That claim he made is true for most of iCloud, and if we’re honest, iCloud is working pretty well for most of the services it provides. Cloud-based documents work great. Cloud-based settings (the Key-Value-Store) work great. All the non-developer features of iCloud (Calendar/Contacts, Backups, heck, even things like iTunes Match) work pretty well. The only thing that is causing developers (and by extension, users) headaches is “Core Data in iCloud”. Why is that?

It’s because Core Data in iCloud violates the core promise Steve made about why iCloud is better. Core Data’s truth is not in the cloud. Instead, Core Data merely uses iCloud as a dumb conduit to sync data back and forth between the different devices a user runs your app on — and leaves the onus for sorting out the sync to the individual devices.

And as we all know, “syncing is hard”. And worse, syncing is impossible, if the app doing the syncing has no control over the data flow (for example when the user disables iCloud for a while), and the developer has no way to debug what is going on.

If 15+ years of working with networked data and disconnected clients has taught me anything, it is that this is an unsalvagable situation. In order to have data in your apps and reliably reproduce and “sync” it between multiple devices, you need to take control of that data, and have a single truth source — ideally in the cloud.

It just so happens that here at RemObjects Software, we have spent the past 10 years thinking about these problems, and have developed a technology and libraries around it that solve them.

This blog post is less about selling you on Data Abstract (although i of course hope that you will have a look at it), and more about showing how taking control and hosting your own data will solve your problem in ways that Core Data in iCloud can not — and give your app additional capabilities, to boot. So i will look at this from the perspective of using Data Abstract, our product, but many of the ideas covered will be applicable just as well, should you decide to “roll your own” or use a different infrastructure.

What is Data Abstract?

Data Abstract is a combination of a client library that you link into your iOS or Mac application (it is also available for other platforms), and server-side infrastructure in form of our free Relativity Server.

One of the “downsides” of giving up Core Data/iCloud is that you will need to look at hosting your own data. That seems like a daunting task, but is really not as difficult, or as costly as it might seem. And in fact, you will come to see it as an upside in the long run.

To get started, in most cases a tiny and cheap Amazon EC2 server instance will do the job — we’re talking monthly costs of around $20 or so. This will be enough to handle the initial load of most apps — and of course, if your app sells really well, the extra costs for upgrading the specs, or “scaling out” to more than one server will be peanuts to you, anyways ;).

Setting up the server is really simple. Most Linux servers you can rent or host, including EC2, already come with a database such as mySQL or PostgreSQL (we use the latter a lot, ourselves). All you need to do is install our Relativity Server, and you’re set. You can of course also use Azure, or other more traditional hosting solutions (and we are working on providing a ready-to-use EC2 image that will let you get set up with this even quicker, soon).

You can then design your database as you see fit, and Relativity Server lets you expose the data to your client applications — you decide what tables get exposed and who can access what, and you can write custom logic to control and influence data access and updates via JavaScript. The Relativity Server Explorer makes this easy and visual.

On the client side, Data Abstract is an easy-to-use static library that you can link into your application, and it will handle all the data access for you. The library is built on modern Cocoa principles, for example it uses GCD blocks to handle network access in the background, making it easy to keep your app responsive. Also, it is designed from the ground up for offline data, meaning you do not need to spend a lot of effort worrying about what happens when your user loses network connection — they can work with data while on a plane, and sync back up later when they get back online.

We have a lot of development topics around DA and Relativity server covered in our documentation Wiki, a good starting point is this page: Developing Database Applications for Mac and iOS.

In addition to providing all that Core Data/iCloud promises (but reliably), hosting your own data also provides additional benefits that cannot be achieved (by design) with iCloud data, even if it were working perfectly otherwise:

  • In addition to each user having their own private data, your app can share data between users, where applicable — be it between individual users, or publicly with all users.
  • You can build apps for other platforms, including Android, Windows, or Mac apps not sold in the Mac App Store, that share the same data. (Data Abstract has dedicated libraries for creating native apps for both Android and Windows, as well.)
  • You can build a web front-end for users to view their data, either via server technologies such as ASP.NET, or client technologies such as a pure JavaScript based browser client. (Again, Data Abstract provides libraries for both, and our library for JavaScript is even completely free.)
  • Most importantly, though, you as the app developer are in full control of the data. If one of your users calls you and says that something is wrong with their data, you’ll know exactly where to look.

Summary

I hope you found this article interesting, and that is has given you a fresh take on the intricacies of adding data “syncing” to your app — on iOS and elsewhere.

The key point i hope you will take a way from this is that Core Data in iCloud, being essentially a client-to-client sync mechanism, just like MobileMe and others before it, is fundamentally flawed, so that the myriad of problems many developers are seeing are hardly surprising. And that the solution to that is taking control of your own data, and hosting it with a single “truth in the cloud”.

I’d be lying if i said i didn’t hope you would consider using Data Abstract as your solution for this problem. We’re a small team of developers dedicated to this problem, and i believe we have a great and unique solution to it that provides a lot of benefit and can save you a lot of time and resources. Data Abstract sells as developer license, with no deployment costs or royalties.

Let us know what you think!

Whatever solution you choose, we wish you best of luck with your data-driven apps, and are looking forward to what you’ll produce!

Yours,
marc hoffman

Chief Architect,
RemObjects Software

Where Does Business Logic Belong?

February 25, 2013 in ROFX

The question of where business logic belongs is as old as database application development. Early on, with primitive client server development, the business logic existed in the client and the database existed only to persist the data.

Client Server

The advantage of this approach is that it makes the client responsive for input validation, and simplifies the degree of coupling between the client and server. The disadvantage is that if a different client connects to the database, the business logic is no longer enforced. This compromises the integrity of the database. There are other disadvantages to client server development – to learn more, read the white paper on “Why Multi-Tier”.

With the introduction of Multi-Tier database application development, the business logic moved to a Middle-Tier.

MultiTier

This has the immediate advantage of keeping the database secure no mater which client connects, while also simplifying client development. The disadvantage is that the client has to make a round trip to the server to validate user input – a major hit in the user experience department.

What I’ve seen some developers do is duplicate the input validation business logic from the middle-tier into the client. This speeds up input validation, but increases the complexity of client development, and requires that any business logic updates be made in two places – duplication of code is rarely the right answer.

Thankfully Data Abstract has a solution for this thanks to the new Business Rule Scripting support. Not only does it allow you to easily define your server side business logic in JavaScript, but also, select scripts are shared from the server to the client for fast and convenient validation and the best possible user experience.

Data Abstract Business Rules Scripting

This has the advantage of running the validation logic twice – once on the client for fast response, and then again on the middle-tier to protect the database. This is the best of both worlds – you keep your database secure and your client application responsive with no duplication of effort or code to keep synchronized. Data Abstract takes care of all that for you.

Additionally, Data Abstract’s schema technology keeps the client completely decoupled from the database. This keeps the database easier to maintain, and allows your application to easily migrate to a new database when your project requires it.

Both schemas and business rules scripting are supported in all editions of Data Abstract: .NET, Java, Delphi, Xcode and JavaScript. Learn more about Business Rules Scripting on RemObjects TV.

Working with Briefcases

February 12, 2013 in ROFX

bagageOne very useful feature of Data Abstract is Briefcase support. The Data Abstract briefcase provides local persistent storage. Simply store the data in a local briefcase file on the client file system, and the data can be reloaded without needing to request it again from the server.

Some common use cases:

  • Use briefcase for saving client data including uncommitted changes between restarts of your application.
  • Store some quite constant dictionary tables into briefcase and load them during application start and thus avoid having to reload the same data from the server.
  • Request only the changed records for some huge table from the server side and then merge the delta with the client table loaded from the local briefcase.
  • Use briefcases if you don’t have a persistent connection to your server and the user needs to be able to work in offline mode. Use Data Abstract’s robust conflict resolution to post the changes later.

In addition, a set of custom, application-specific string properties can be stored alongside the data. This can be useful, for example, for storing the version number of the data format to ensure newer versions of your application can reload the data correctly, if data formats change over time. (It is not recommended though to use this space for general application settings that are not directly related to the data.)

The main advantage of using a briefcase instead of some embedded database (f.e. SQLite.NET) to cache user data or to implement offline mode is that a briefcase stores not only user data but also its state (i.e. deleted, updated or inserted data rows). This greatly simplifies further synchronization with a Data Abstract-based server.

You can learn more about working with offline briefcases:

And more in the official RemObjects Documentation Wiki.

Avatar of marc

by marc

Using RemObjects SDK and Data Abstract with Oxygene Nougat.

December 25, 2012 in Cocoa, iOS, Mac, Nougat, Prism, ROFX, Visual Studio, Xcode

Nougat is, of course, designed to work with any existing Objective-C libraries out there, because it directly consumes and generates code for the Objective-C runtime. As such, it should come as no surprise that Nougat is ready to use RemObjects SDK and Data Abstract for Xcode, out of the box.

That said, with the new Alpha builds of RemObjects SDK and Data Abstract that we shipped on friday (build .1069), we have made a few improvements that make it even easier to get started with RO/DA in Nougat. These are three-fold:

Read-to-Use .fx files

Unlike .NET and Java, Cocoa libraries do not include easy to parse metadata for compilers to consume. Instead, it depends on .h files to define the available APIs — which is fine when consuming the libraries from a C compiler. Because .h files are slow and complicated to parse, Nougat introduces an intermediary format in the form of .fx files. You can think of an .fx file as “pre-compiled headers” file for a given framework or library; a set of metadata that represents all the information expressed in the framework’s .h files, but encoded in a way that it is easy and quick for the Oxygene compiler (and IDE toolchain) to process, when compiling, driving Code Completion etc.

While Nougat comes with the necessary tools to generate .fx files for any of your favorite third party libraries (and of course ships with .fx files for the supported base SDKs), that is an extra step we want to alleviate, so the new build of RODA/Xcode includes .fx file for those libraries out of the box. After installation, you will find the files next to the corresponding binaries in ./Bin.

All you need to do to use the SDK or Data Abstract from Nougat is to go to “Add Reference”, select the .fx file for your platform (i.e. OS X or iOS) to add a reference. That’s it.

libDA.fx Reference

From the .fx, Nougat will automatically know about all the types in the RO/DA library, and will take care of getting the static library and any dependencies linked in.

Static Libraries for OS X

In the past, RODA/Xcode included precompiled binaries in the form of a framework for OS X and static libraries for iOS. Frameworks are easier to deal with in Xcode, because they combine a binary with its accompanying header files, which is why we chose to ship OS X binaries as a framework. iOS does not support the framework format for third party libraries, so the choice there was easy: static libraries are the only option.

For Nougat, the benefits of a framework (on OS X) are diminished, because metadata is provided in the .fx file anyways, so a static library is just as easy to deal with, and has fewer files involved. For that reason, we have added a static library version of RODA/OS X to the product (in addition to the Framework). Xcode developers can choose to use either version, depending on their preferences (the static library has the benefit of being linkable straight into the executable, which is nice if you’re creating command line tools that use RO/DA); Nougat developers will mostly want to use the new static library alongside its .fx file.

CodeGen for Nougat

For pure Data Abstract use, you’re pretty much all set with the above, but if you’re building custom RemObjects SDK services that you want to talk to, there’s one more step missing: Interface code.

Talking to RO services depends on having strongly typed interfaces generated for your local proxy classes and any complex types you are passing back and forth between the client and the server — and until last week, RO/Xcode generated this code in Objective-C only.

That was not a complete showstopper for Nougat. Remember, Nougat can use any Objective-C library, so you could compile those files using Xcode and the use them from Nougat (in fact, that’s what i’ve been doing with for small RODA project i have been working on over the past few weeks). But that’s not ideal, of course.

The new alpha now includes native Nougat CodeGen for your services, so you can generate an Interface .pas file and add it straight to your Nougat project — as it should be.

The new CodeGen is exposed in three places:

  1. Of course the codegen2.exe command line utility has been updated, so if you generate code from the command line, you can use the /lang:nougat option to have interface files written for Nougat.

  2. Service Builder has also been expanded to support Nougat alongside all the other languages (that menu is getting mighty big!):

Service Builder

  1. Finally, we also added Nougat CodeGen to our rodl2objc.app on the Mac (which is now really becoming overdue for a rename ;). While we were at it, we also revamped the UI for this tool a bit to make it (simple as it is) nicer to use, and look at:

rodl2objc

(and as the beta progresses, CodeGen will also be available directly inside the Visual Studio IDE, as well)

So with that you should be all set to build your first great client application for the Mac or iOS, using RemObjects SDK/Data Abstract and Oxygene “Nougat” over the holidays ;)

Let us know how it all works out!

yours,
marc

Remote Script Debugger

December 18, 2012 in .NET, ROFX

Introduction

Today I’d like to write about a new technology that is currently being developed by the RemObjects team – the Remote Script Debugger.

The Remote Script Debugger is a service that exposes several methods and events. It has to be explicitly implemented by a server application (in most cases in the same way the DataService is implemented, i.e. without any custom code). The Script Debugger service was designed in a way that allows to easily add (or remove) it to an already existing DataAbstract for .NET server. You’ll literally have to write just one line of code that instantiates the Remote Script Debugger on the server side.
As you’ve probably noticed, the Remote Script Debugger is not just some client debugger application – it is a base service that exposes debug information about Business Rules Scripts being executed by the server.
In this blogpost, I’ll show you how to add a Remote Script Debugger service to a server application and create a really simple debugger application.

Server

Let’s create a simple Data Abstract for .NET server application using the New Project Wizard:



Use the PCTrade database as data source:



Don’t forget to add support for OData publishing – this will later allow to use a browser as data access application stub without writing any client application code.
Start the server and the open URL http://localhost:8099/odata/orders.
You should see some data in the server response (use the login/password ‘test’ when asked).



At this point, we have a working Data Abstract for .NET server. Now let’s add a debugger service to it.

Debugger Service
To add the Remote Script Debugger service, you need to perform the following steps:

  1. Add a reference to the RemObjects.DataAbstract.Scripting.RemoteDebugger assembly.
  2. Open your service’s .RODL file and change its base RODL from DataAbstract.RODL to RemoteScriptDebugger.RODL.
  3. Add the ‘ScriptDebugger’ service and set its base service to the BaseScriptDebuggerService.


  4. Close the Service Builder. _Intf and _Impl files will be regenerated and a new ScriptDebugger_Impl file will be added.
  5. Open the ScriptDebugger_Impl file in the designer and point its ServiceSchemaName property to the same Schema the DataAbstract service uses.
  6. Open the data service implementation code and make sure that the ‘Debug’ property of the EcmaScriptDebugger component is set to true.
  7. Add a class override for the GetScriptDebugger method to the data service implementation:
    protected override RemObjects.DataAbstract.IScriptDebugger GetScriptDebugger()
    {
      return new RemObjects.DataAbstract.Scripting.RemoteDebugger.RemoteScriptDebugger(this.SessionID);
    }

    This change allows the Data Service to instantiate the script debugger and wire up its events.

  8. Since the RemoteScriptDebugger uses events to send debugger data back to the client, you need to add EventSinkManager and MemoryMessageQueueManager components to your application. For Wizard-generated applications, the best place for network communication components is the Engine component. Don’t forget to set up the Message property of the newly added EventSinkManager component.


And that’s all that is needed to expose the Remote Script Debugger service. In a real-world appication you should add some security checks to control who can access the remote script debugger service.

Debugger Client

Now let’s create a very simple debugger application. You can add code highlighting or a better variable inspector window later, but to keep the debugger client application simple, I’ll skip these steps for now.

Create a new WinForms application. Add references to the Internet Pack for .NET, RemObjects for .NET and Data Abstract for .NET client assemblies, namely RemObjects.InternetPack, RemObjects.SDK, RemObjects.SDK.ZLib and RemObjects.DataAbstract.

You’ll also need to generate an _Intf file based on the RemoteScriptDebugger.RODL. Just open the file in the Service Builder and generate the Interface code using the CodeGen menu.

Now add 4 buttons, 2 Text Boxes and a ListView to the main form:



Several private fields have to be introduced:

private IClientChannel fChannel;
private IMessage fMessage;
private EventReceiver fEventReceiver;
private IBaseScriptDebuggerService fScriptDebugger;
private Guid fSessionId;

The main form of our application has to implement the IScriptDebuggerEvents interface to be able to retrieve data about debug events from the server.

Now let’s implement methods that send debugger commands (like Step Into or Continue Execution) to the server, and event handlers that are invoked when debugger events are sent by the server.

private void AttachButton_Click(object sender, EventArgs e)
{
  this.fChannel = new IpHttpClientChannel() { TargetUrl = @"http://localhost:8099/bin" };
  this.fMessage = new BinMessage();
  this.fEventReceiver = new EventReceiver() { Channel = this.fChannel, Message = this.fMessage };
 
  // Initialize ScriptDebugger service proxy
  this.fScriptDebugger = new BaseScriptDebuggerService_Proxy(this.fMessage, this.fChannel, "ScriptDebugger");
 
  // Attach Debugger
  this.fScriptDebugger.Attach(Guid.Empty, new String[] { "Enable Step By Step Debug" });
 
  // Assign ScriptDebuggerEvents listener
  this.fEventReceiver.RegisterEventHandler(this, typeof(IScriptDebuggerEvents));
}
 
private void DetachButton_Click(object sender, EventArgs e)
{
  this.fScriptDebugger.Detach(Guid.Empty);
}

Note how we attach to the debugger by calling the Attach method. Its first parameter defines which session data access calls should be debugged. An empty Guid means that it’ll listen (i.e. debug Business Rules Scripts) to all sessions.

It is possible to retrieve the session list from the server via the RemoteServiceDebugger service methods to be able to select specific session and debug scripts running in that context only.

The code behind the Step and Continue/Run buttons is quite straightforward:

private void StepButton_Click(object sender, EventArgs e)
{
  this.fScriptDebugger.StepInto(this.fSessionId);
}
 
private void RunButton_Click(object sender, EventArgs e)
{
  this.fScriptDebugger.Continue(this.fSessionId);
}

Look at the this.fSessionId parameter. This method requires an exact identifier of the session being debugged, and does not allow Guid.Empty as a wildcard. This restriction is due to the fact that Step, Continue or Break Execution commands can only be sent to specific data access sessions.

If the Guid.Empty wildcard was used, the Session identifier is sent by the server when any Business Rules Script method execution starts.

Now we need to implement event handlers for the FrameEnter, FrameExit, TracePoint, UnhandledException and Log events.

Each event is explained below, together with its handler implementation code.

  • Log event: The most obvious event of all. It is fired when the log script method is called.
    public void Log(ScriptDebuggerEventSender sender, String message)
    {
      this.Invoke(new Action(
      delegate
        {
          this.LogTextBox.AppendText(String.Format("{0} {1}: Log: {2}\r\n\r\n", DateTime.Now, sender.ScriptName, message));
        }));
    }
  • FrameEnter event: Fired when a script function is entered. It allows to retrieve the script source code, the name of function being executed and the session ID of the client that triggered the event.
    public void FrameEnter(ScriptDebuggerEventSender sender, String functionName, String scriptSource, Boolean executionPaused)
    {
      this.fSessionId = sender.SessionID;
     
      this.Invoke(new Action(
        delegate
          {
            this.ScriptSourceTextBox.Text = scriptSource;
          }));
    }
  • FrameExit event: Fired when the debugger leaves the script method. In our sample application this event is not used, but in more advanced debbuger implementations, it would be a good place to remove current code line highlighting etc.
    public void FrameExit(ScriptDebuggerEventSender sender, String functionName)
    {
    }
  • TracePoint event: The most important event of the RemoteScriptDebugger. It is fired before some script code line is executed and provides information about the position of the code being executed and the script variable values.
    public void TracePoint(ScriptDebuggerEventSender sender, ScriptDebuggerState debuggerState, Boolean executionPaused)
    {
      this.Invoke(new Action(
      delegate
        {
          this.LogTextBox.AppendText(String.Format("{0} {1}: Executing line {2}\r\n\r\n", DateTime.Now, sender.ScriptName, debuggerState.StartLine ));
     
          this.VariablesList.Items.Clear();
          this.ShowVariablesInfo(debuggerState);
        }));
    }
  • UnhandledException event: Fired when script execution fails for some reason and Provides details about the exception that occurred.
    public void UnhandledException(ScriptDebuggerEventSender sender, ScriptDebuggerState debuggerState, ScriptExceptionType type, String message, String stackTrace)
    {
      this.Invoke(new Action(
      delegate
        {
          this.LogTextBox.AppendText(String.Format("{0} {1}: Failed at line {2}\r\n\r\n", DateTime.Now, sender.ScriptName, debuggerState.StartLine));
          this.LogTextBox.AppendText(String.Format("{0} {1}: {2} {3}\r\n\r\n", DateTime.Now, sender.ScriptName, type, message));
     
          this.ShowVariablesInfo(debuggerState);
        }));
    }

The ShowVariablesInfo method mentioned in the code above lists the script variable names and values. Variable values are serialized using the JSON serialization format. This allows to send variable values in a platform independent format.

The sample debugger application being created in this post uses this ShowVariablesInfo method implementation:

private void ShowVariablesInfo(ScriptDebuggerState debuggerState)
{
  for (Int32 i = 0; i < debuggerState.CallStack.Length; i++)
  {
    var frame = debuggerState.CallStack[i];
 
    ListViewItem item = new ListViewItem("[METHOD]");
    item.SubItems.Add(String.Empty);
    item.SubItems.Add(frame.FunctionName);
    this.VariablesList.Items.Add(item);
 
    foreach (var variable in frame.Variables)
    {
      item = new ListViewItem(variable.Name);
      item.SubItems.Add(variable.Type);
      item.SubItems.Add(variable.Value);
 
      this.VariablesList.Items.Add(item);
    }
  }
}

Now we need to add a simple Busness Rules Script to our server application. I’ll add a simple script code like:

function beforeGetData(names, requestInfos)
{
  log('Entering beforeGetData');
  log(JSON.stringify(session));
  log('Exiting beforeGetData');
}



Testing the debugger

Start the server again and open the URL http://localhost:8099/odata/orders.

Now start the debugger App and press the ‘Attach’ button.

Go back to the browser and reopen the http://localhost:8099/odata/orders.

You’ll see the script source and status messages in our debugger application (press the Step button to run the script in step-by-step mode).



That’s it. We have created a simple Business Script Rules remote debugger.

I intentionally skipped advanced parts, like code highlighting and the proper display of variable values (i.e. deserializing for JSON form), as these are far beyond the scope of this post.

Summary

This blogpost shows how you can easily add a Remote Script Debugger service to a Data Abstract for .NET based server application and how a simple debugger App can be created. Debugger application sources can be downloaded here.

The Script Debugger service is already integrated into Relativity server. Alex Karpenko is working on the integration of the Script Debugger into Schema Modeler and it looks really cool (expect a blogpost about Script Debugger soon).

New features in Schema Modeler 7

December 12, 2012 in ROFX, Windows

As you might know, we are switching to the new Schema Modeler tool in our Data Abstract products. We wanted to make it better, handier and up-to-date with the latest conceptions introduced in Data Abstract. In the last release we fixed some bugs and added a set of new features. Today I want to highlight some of these features. So let’s get started.

UI improvements to simplify navigation

During the beta, we’ve had some complaints that navigation in the new Schema Modeler is more complex than in the old one. In order to see and select a schema table field, we need to expand the Table node, then expand the Fields node, and after that we will see the particular fields. We tried to simplify this by adding a new Content section to the bottom of the schema table view.

Inside this section you can see the table content, including fields, parameters and statements. You can quickly navigate to any particular item – just double-click it. You can navigate to fields, parameters and statements collection nodes by clicking the corresponding hyperlinks (you can find them above the container).
And finally, you can easily create and remove table elements easily from the table view. There are two buttons at the top right corner of each element view.

See video

Tip: You can select several fields and remove them in one go, rather than deleting them one by one.

There are similar improvements planned for the schema command view in the next release.

Improved fields collection view

Now it shows size, scale, precision, and many other field properties. It also highlights read-only fields with gray, so you can easily notice them.

Improved recreating or updating schema table fields

We added the ability to choose a statement for recreating or updating schema table fields.
The previous version used a selected statement, which was not obvious and handy.

If the schema table has only one statement, it will be used for recreating fields automatically. But for cases where your table has several statements, you will see a dialog where you can choose the statement you want to use.

See it in action

Connection Types

Some time ago in the Data Abstract v5, we introduced the new concept of the ConnectionType, which replaces specifying the exact connection with the more general Connection Type. It allows us to implement a more flexible way of working with several connections in the application.

The new Schema Modeler simplifies setting the connection type for the statement by offering a list of available types in the combo-box. You don’t need to remember what connection types your connection manager contains. Just select the appropriate one from the list.

See this in action

Loading connection content by demand

We have implemented a lazy loading pattern for Connections Manager documents in the new Schema Modeler, which is more efficient and decreases memory consumption.

See this in action

Added ability to open *.daConnections files

Now we can open connection files by double-clicking in the Windows Explorer, or in the Visual Studio Solution Explorer, and edit them separately from the schema.

Working with *.daRemoteSchema files

daRemoteSchema files are just a reference to a remote Data Abstract server. Schema Modeler can open these files: it connects to the server and downloads the schema from there. If the server requires a login or is encrypted with an AES envelope, Schema Modeler shows a login dialog where you can provide the login and password.

Since we cannot update a schema on the server in runtime, daRemoteSchema project opens in Read-only mode and can be used for informational purposes only.

See this in action

Working with *.RelativityClient files

A RelativityClient file is the another type of shortcut file that can reference a particular schema in a particular Relativity domain. The important point here is the necessity to work with connections using Relativity abilities only. Actions like obtaining metadata, a list of database objects or driver information should be performed by the Relativity application. Saving changes in the schema and connection manager will lead to uploading data directly to the Relativity server, no local or temporary files will be created.

See this in action

Working with Internal connections

Internal connections is a quite new concept in the Relativity world, representing a general connection that can be managed by Relativity only. Its main aim is to abstract the details of connections even for Relativity administrators. With an internal connection, it doesn’t matter what driver is used for working with data. It can be SQLite, or a more exotic driver, Relativity will know how to deal with it.

Improved automatic mappings regeneration

Now it understands SQL field aliases and generates proper mappings for it.

See this in action

Improved generation delta commands for schema tables

Now it creates commands and sets them for the table.

See this in action

So far that’s all for the current release.

If you have any remarks or ideas, please let us know.
Thanks!

Avatar of marc

by marc

Improvements to the DA LINQ workflow in Data Abstract 7

October 9, 2012 in .NET, RemObjects, ROFX

One of the many improvements in the all-new Data Abstract 7 is that we completely revamped the user experience for creating and updating the strongly typed code files for DA LINQ in DA/.NET.

If you create a DA project from one of the templates and use our wizard, your project will already start out with a TableDefinitions source file that reflects all the tables you selected in the wizard. But sooner or later, your schema will change and evolve, and then code will need to be updated. Also, you might have an existing non-DA project that you want to add DA client functionality to, and in this case you will want to create a fresh TableDefinitions file.

Let’s have a look at this.

In the simplest case, which already worked fairly similar in previous versions, your solution contains a custom DA server and with it one or more actual .daSchema files. In this case, you can simply right-click the .daschema and choose “Create DA LINQ Table Definitions” from the context menu:



This will launch our new wizard for this process, in this case with only a single page:



This screen allows you to specify three things:

  1. The file to generate or update. If there’s already one (or more) existing table definition source files in your solution, you can select a file (from any of the projects) here; you can also specify a new file to be created.

  2. The namespace to be used for the generated or updated file.

  3. The list of tables to generate classes for.

Another new and improved thing here is that if you are updating an existing file, the wizard will automatically persist the existing namespace, as well as any tables you previously decided to not generate code for by unchecking them (new tables that have been added to the schema since you last generated the code will be checked by default).

When you click Finish, the code file with your DA LINQ classes will be created or updated and opened in the IDE.

Remote Schema Files

So far so good. But what happens for client-only projects, where you don’t have the server or a .daSchema file in your solution?

We have introduced a new file type for this, called .daRemoteSchema. The project wizard (or the DA LINQ wizard) will automatically add these files to your client project as needed, and you can think of them as a kind of “link” to the schema on the DA server that is running elsewhere (or locally).

Just as with a .daSchema, you can right-click these .daRemoteSchema files and find the “Create DA LINQ Table Definitions” option in the context menu:



When invoked, it opens the same wizard you have seen above, but with an additional first step:



The wizard gathers the location and options for the remote server from your .daRemoteSchema file, lets you adjust them if necessary, and optionally provide the login for the server, if needed (you can opt to store the login in a .daRemoteSchema.user file for future reference, so you don’t need to re-enter it every time you update the table definitions — the idea being that while the .daRemoteSchema file is part of your project, you would exclude the .daRemoteSchema.user file from version control to keep your login safe).

When you click “Next”, the wizard goes out to the network and fetches the schema from your server (which should be running and accessible), and then continues on to the same page you’ve already seen above.

Relativity Client Files

In a similar fashion, we are also introducing a new .relativityClient file type to provide a reference to a Relativity Server that your application might be talking to.

Once again, the file will be automatically added by the new project wizard when you create your application, and you can simply right-click it to invoke the now-familiar “Create DA LINQ Table Definitions” option:



As above, selecting this option shows the DA LINQ wizard, this time with a page tailored for the Relativity Server connection:



You can verify or update you server address (the wizard and .relativityClient files also support ZeroConf-discovered servers), and select a domain and schema to work with. All these settings will be persisted in the .relativityClient file for future reference.

When you click next, you once again get the same wizard page shown above.

Adding New Client Connectivity

In addition to invoking the DA LINQ wizard from the three file types seen here, you can also trigger it from a global menu item (“RemObjects SDK|Create DA LINQ Table Definitions”) or a button in the Solution Explorer toolbar.

When invoked in this fashion, it will give you three choices:

  1. Proceed with an existing .daSchema, .daRemoteSchema or .relatvityClient file, if one exists in your solution (this will take the exact same path as if invoked straight from the file as seen above).

  2. Freshly connect to an existing remote DA server.

  3. Connect to an existing Relativity Server domain.

The last two options will ask for the connection parameters for the server you want to connect to (on a screen similar to the ones seen above), and then automatically add a new .daRemoteSchema or .relativityClient file to your project, alongside the generated code file.



Other Benefits of .daRemoteSchema and .relativityClient Files

In addition to giving you quick access to the DA LINQ wizard, these new file types also have another benefit: by double-clicking the file (in Solution Explorer or in Windows Explorer), you can launch straight into the new Schema Modeler 7 (which i’ll talk more about in future bog posts).

For .daRemoteSchemas, DASM7 will download the schema from the server and present it to you read-only, giving you a quick and easy way to browse and explore the schema your application is working against.

Much more importantly, for .relativityClient files, DASM7 will connect to the Relativity Server and — much like you might already know from our Schema Modeler for Mac — remotely design and edit the schema(s) stored in your Relativity Server domain (this will also be the topic of another upcoming blog post).

Summary

So this is a first peak at some of the workflow improvements that Data Abstract 7 for .NET is bringing to working with DA LINQ. We hope you like them and stay tuned for more!

Data Abstract 7 is available now. Read more at remobjects.com/da.