Feeds:
Posts
Comments

Posts Tagged ‘Async framework’

The Problem:
System Center Orchestrator 2012 exposes a data service that enables to query and execute runbooks.  But working directly with the data service is like executing a WCF service by manually composing the SOAP messages. There are no type-safe parameters, no intellisense and you need to type the exact path of the runbook or even worse, specify GUIDs . Developing and testing a code that is involved with runbooks execution quickly becomes a cumbersome and tedious task.

The Solution:
The solutions is a Visual Studio item template.  When you add it to an existing project, it will ask for the Orchestrator server’s details and generate hierarchy of proxy classes that match-up with the Orchestrator server folders’ hierarchy, and within every class there will be methods that will match-up with the runbooks on said folder that accept the runbook’s parameters. In addition, the runbook’s description will be appended to the method’s remark summary, which makes the Visual Studio intellisense more helpful. Every class that contains runbooks also implements an interface named “I{ClassName}” that include these methods for easier testing. After adding this item to your project you will be able to execute a runbook as seen in the following code:

 OrchestratorReference orchestratorReference = new OrchestratorReference();
 Guid jobId = orchestratorReference.Development.Utils.WriteErrorLog(message, activity, runbook);

The OrchestratorReference object can be initialized with the credentials for accessing the Orchestrator web services.Ex:

 OrchestratorReference orchestratorReference = new OrchestratorReference();
 NetworkCredential cred = new NetworkCredential(userName, password, domain);
 orchestratorReference.OrchestratorServiceCredentials = cred;

In case the runbook path’s prefix depends on development environments you can use the “AddReplaceFolderPrefix” method to dynamically replace the path prefix. Ex:

 OrchestratorReference orchestratorReference = new OrchestratorReference();
 orchestratorReference.AddReplaceFolderPrefix(@"\Development\", @"\Production\");

All the runbooks’ functions return the job Id that was created on the Orchestrator server. The execution of the runbooks is asynchronized, to wait for the runbook completion and optionally collect the runbook’s return values, you can use the created job Id with the following methods:
Sync:

 Guid jobId = orchestratorReference.Development.VMManager.VM.GetNextVMName("Test##");
 Dictionary<string, string> result = orchestratorReference.GetJobResult(jobId);
 string nextVMName = result["nextVMName"];

Async:

 public async Task GetNextVMName(string template)
 {
   OrchestratorReference orchestratorReference = new OrchestratorReference();
   Guid jobId =
         orchestratorReference.Development.VMManager.VM.GetNextVMName(template);
   Dictionary<string, string> result =
                     await orchestratorReference.GetJobResultAsync(jobId);
   return result["nextVMName"];
 }

The T4 template, responsible for generating the code, removes any classes/methods duplication and will name classes/methods with Pascal-case and methods parameters with camel-case. It also removes from the class/methods’ name any un-letter prefix characters, so if the folder name includes an index number prefix, this index will be truncate and will be visible only from the class/methods remark’s summary.

Deployment:

  1. Extract the zip file available for download at the bottom of this post.
  2. Execute the “DeployItemTemplate.cmd” file.

Using:

  1. Open Visual Studio 2010.
  2. Click on add -> new item… in a project from which you need to execute a runbook
  3. Choose the “Orchestrator Reference” template from the template list, type in a file name and click OK.
    Orchestrator Reference - add item template
  4. Type the Orchestrator server’s name, port number where the Orchestrator service is listening (default 81) and if SSL is required.
  5. Click on the “Load” button. The wizard will load the folders structure from the Orchestrator service and will enable to specify which folders to include in the new generated class.
    Orchestrator Reference
  6. Click the “Add” button.
  7. Optional – Expand the template file to check the generated cs file.
  8. Happy developing!

Source & Binary

Read Full Post »

In the last two parts of this session I have shown how to develop Silverlight application that shows information from a database in occasion connected environment. In this last part I will show you how to manage updates (including inserting and deleting records) and synchronizing them back into the database.

The first step is to make sure we are working with the relevant DomainContext object and to apply all the updates to the offline/online DomainContext, depending on the application’s status. To accomplish this I have created a factory method that checks the application’s status and returns the relevant DomainContext. This method should be used whenever we need a DomainContext object in Silverlight projects.

public static NorthwindDomainContext GenerateNewNorthwindDomainContext()
{
    NorthwindDomainContext northwindDomainContext;
    if (OfflineHelper.IsApplicationOnline)
    {
        northwindDomainContext = new NorthwindDomainContext();
    }
    else
    {
        northwindDomainContext = 
          (NorthwindDomainContext)DomainContextExtension.
                    GetOfflineDomainContext(typeof(NorthwindDomainContext));
    }

    return northwindDomainContext;
}

The second step is submitting the changes. To accomplish that, we will need to check the application status; if it is online we should use the out of the box SubmitChanges method and if it is offline, we just call the OCSaveAsOfflineDomainContext that we implemented in the previous parts. Since the Entity object is tracing all the changes, we do not need to do anything except serialize the updated DomainContext to the offline storage. To simplify the operation I created this extension method:


public static Task OCSubmitChangesAsync(this DomainContext source)
{
    if (OfflineHelper.IsApplicationOnline)
    {
        return source.SubmitChangesAsync();
    }
    else
    {
        return TaskEx.Run(() =>
        {
            source.OCSaveAsOfflineDomainContext();
        });
    }
}

The third and last step is synchronizing with the database when the application becomes online.  All we need is to call the SubmitChanges on the offline DomainContext. Although the MSDN sample that enables serializing RIA DomainContext objects fit the job, it still required fixing some bugs to make it work properly (I attached the final code at the button of the post). Again, I warp it up with an extension method:

public static Task OCSyncWithOnlineServiceAsync(this DomainContext source)
{
    Task result = null;
    if (OfflineHelper.IsApplicationOnline)
    {
        DomainContext offlineDomainContext = 
             GetOfflineDomainContext(source.GetType());
        try
        {
            result = offlineDomainContext.SubmitChangesAsync();
        }
        catch (Exception ex)
        {
            HandleSyncErrors(ex);
        }
    }

    return result;
}

An example of using the above methods for doing offline updating, would look something like this:

NorthwindDomainContext domainContext = 
          DomainContextFactory.GenerateNewNorthwindDomainContext();

await this.domainContext.LoadAsync(this.domainContext.GetCustomersQuery());
this.domainContext.OCSaveAsOfflineDomainContext();

OfflineHelper.IsApplicationOnline = false;

domainContext = DomainContextFactory.GenerateNewNorthwindDomainContext();
// Do some update on domainContext objects...

OfflineHelper.IsApplicationOnline = true;
await this.domainContext.OCSyncWithOnlineServiceAsync();

In addition, I have also attached a simple application that demonstrates the use of this framework. Notice that you can take the application offline, make changes, close and open the application and the changes will still be there. The application is also able to run out of the browser so you will be able to run this application even after the web server and the SQL server are unavailable.

Summary: To convert your application to support offline scenarios you will need to follow these steps:

  1. Download and install the Microsoft Visual Studio Asynchronous Framework.
  2. Add reference to the SilverlightOccasionallyConnected DLL.(attached to this post)
  3.  Create a factory method as demonstrated, to create DomainContext and use only this method throughout the Silverlight projects.
  4. Use the OCLoadAsync and OCSubmitChangesAsync to query and submit your changes respectively.
  5. Make sure that the filter and order-by logic are located in the Silverlight projects and not on the Server-side project.
  6. Add to your application this functionalities :
    1. An offline/online indication
    2. An option to generate offline copy of the database using the OCSaveAsOfflineDomainContext function. Load all the data that your application will need access to in offline mode before calling this method.
    3. An option to synchronize using the OCSyncWithOnlineServiceAsync function.

Source Code for this article

Read Full Post »

In the previous part I showed how to easily write a unified code that automatically checks the application connectivity status and executes a query against the database, or an offline storage, whether the application is online/offline respectively. In this part I will describe in more detail the implementation of the DomainContext extension methods that enables this.
The DomainContextExtension class includes the method OCLoadAsync that receives as a parameter an RIA services query that can be customized on the fly and returns a Task of type IEnumerable of the requested entity type.

The method contains 3 main steps:

  1. If the application is online, the method just loads the data from the RIA service.
  2. Else, will create an IQueryable of the requested entity from the offline DomainContext.
  3. Transfers the query from the current DomainContext to the offline DomainContext.

I will explain in details each step:

  1. The class SilverlightOccasionallyConnected.OfflineHelper has a static Boolean property IsApplicationOnline. The property is initiated with the built-in NetworkInterface.GetIsNetworkAvailable() value. The idea is to set the status at the application loading and to enable control of this property to the application. If the application is online, the method use the Async framework to load the query from the server as I described in detail in this article.
  2. If the application is offline we need to execute the query on the offlineDomainContext that is stored on the application Isolated Storage. I used the example from the MSDN- Code Gallery to load the DomainContext from the Isolated Storage. Next we need to create IQueryable for the requested Entity. If the entity framework’s model used in the domain service does not have any inherit relation we can just write:
    OfflineDomainContext.EntityContainer.
                           GetEntitySet(requestEntityType)
    

    If however we have inherit relation we need to do an extra step and find the base type of the Entity (the parent entity that is inherit directly from the System.ServiceModel.DomainServices.Client.Entity object) and then use the following syntax:

    OfflineDomainContext.EntityContainer.
                           GetEntitySet(baseEntityType).OfType<T>()
    

    Where T is the requestEntityType. We also need to convert the IEnumerable to IQueryable so the next step of changing the query source will be available.

  3. This step is the trickiest. We need to transfer the query from the current DomainContext to the offline DomainContext. The queries on the DomainContext are of type EntityQuery<T>. This type has a Query property of type IQueryable that contains the specific requested query (for example “where-clauses” that narrow the result).
    The IQueryable contains an Expression property that exposes the expression tree that builds the requested query. By debugging I realized that the expression tree contains nesting of MethodCallExpression where the first argument can be the next MethodCallExpression or the ConstantExpression that represents the original IQueryable object (the object we’d like to replace) and the second argument is a UnaryExpression that represents the lambda expression. In light of the above tree structure, I wrote recursive method that goes through the expression tree and creates new expressions with a different source for the query (the offline DomainContext IQueryable that we created in step 2).
private static Expression ChangeQueryableExpressionSource<T>(
                                             Expression expression,
                                             IQueryable<T> newSource)
{
    MethodCallExpression methodCallExpression =
                                        (MethodCallExpression)expression;
    Expression expressionLeftArgument =
                                        methodCallExpression.Arguments[0];
    Expression expressionRightArgument =
                                        methodCallExpression.Arguments[1];

    if (expressionLeftArgument is ConstantExpression)
    {
        return Expression.Call(
                               methodCallExpression.Method,
                               Expression.Constant(newSource),
                               expressionRightArgument);
    }
    else
    {
       return Expression.Call(
                              methodCallExpression.Method,
                              ChangeQueryableExpressionSource(
                                      expressionLeftArgument, newSource),
                              expressionRightArgument);
    }
}

To the above method I just added some basic functionality that loads and saves DomainContext to a fixed-name file on the Isolated Storage.

In the next part I will add submit update functionality that will enable making updates in occasionally connected application.

Feel free to use this code in your applications and let me know what you think about it.

Source Code for this article

Read Full Post »

I got a request to build an internet application that will also be available offline; The user “checks out” part of the database to the client, works offline and checks it in when going back online.

To implement this request I decided to use Silverlight built-in out-of-browser application, RIA services for accessing the remote database and the MSDN sample that enables serializing RIA DomainContext objects to an isolated storage, so I can save database tables locally(part of the “Authentication quick-start” example).

The challenge with the above is that every query against the database requires checking if the application is online or offline and writing a duplicate Data access code for each scenario. The solution I used was to write a helper code that will enable writing one data access code regardless of the application status (online/offline).

For example you can write in your view model the following code:

private AdventureWorksLTDomainContext domainContext =
                              new AdventureWorksLTDomainContext();
this.Customers = await this.domainContext.OCLoadAsync(
                           this.domainContext.GetCustomersQuery());

Things to notice:

  1. The method OCLoadAsync will check the application connectivity status. If it is online it will execute the RIA service against the remote server and if it is offline it will load the information from the isolated storage.
  2. I am using the Async framework (still in CTP) to load the query. For more detail on using Async framework with RIA service please refer to this article.
  3. The query can be customized on the fly, for example the following line is also valid:
    this.Customers = await this.domainContext.OCLoadAsync(
      from customer in this.domainContext.GetCustomersQuery()
      where customer.FirstName.StartsWith(this.Prefix)
      orderby customer.FirstName, customer.LastName
      select customer );
    
  4. Given the way RIA is implemented, only the final complete query is executed against the Database.
  5. The implementation of the offline support will not include any code rules in the domain service methods. The assumption is that your domain service methods will basically return all entities for a specific type. You can add code rules to the domain service, for example security trimming;  The offline version will not include these code rules, however the local storage will only contain the records that the user had access to last time they were online..

Before you will be able to access offline storage you will need to create one. This is also an easy task with the OCSaveAsOfflineContext method. Just execute the following code when the application is online:

await this.domainContext.LoadAsync(
                    this.domainContext.GetCustomersQuery());
this.domainContext.OCSaveAsOfflineDomainContext();

Things to notice:

  1. The method LoadAsync returns the result of the query but also populates the DomainContext with the result, so by saving the domaincontext to the Isolate Storage we can access the information later when the application is offline.
  2. You will need to load all the queries you like to save with the same domainContext and then use the OCSaveAsOfflineDomainContext method to save local version of your database in the Isolated Storage.

To use this solution follow these steps:

  1. Create normal Silverlight project with Entity framework model and RIA services (if you’re not familiar with RIA you can check this link).
  2. Install the Async Framework and add reference to the AsyncCtpLibrary_Silverlight DLL.
  3. Add reference to the SilverlightOccasionallyConnected Dll  download available at the bottom of this article.
  4. Add using-statement to ‘SilverlightOccasionallyConnected” to have access to the extension methods for the DomainContext class.
  5. Start writing your class.

In Part II,  I Will explain in more detail the implementation of the DomainContext extension methods.

Source Code for this article

Read Full Post »

Since Silverlight enforces an a-synchronic  development (you can’t call any services in sync mode), the new release of the async framework (still in CTP) brings new opportunities and simplification to Silverlight developers. As RIA services are a common way to connect Silverlight to a backend database it make sense to use the async framework to call the RIA services.
When I searched for samples of how to use the async framework with RIA I found Kyle McClelln’s blog that provides a nice solution but with couple of issues:

  1. If you read the code carefully you will notice that the registration for the onComplete event is executed after the function load is executed, so theoretically if the method is completed before the registration, we will miss the event and the code will never execute. of course   calling the RIA Service  takes time to complete but this is not good practice.
  2. Relatively cumbersome Bracketing required in any call to RIA function.
  3. Incompatible with the naming convention of the Task-based Asynchronous pattern.

So, inspired by Kyle’s blog I wrote my version of the solution to solve the above issues

 using System.Collections.Generic;
 using System.ServiceModel.DomainServices.Client;
 using System.Threading.Tasks;

 public static class DomainContextExtension
 {
     public static Task&amp;lt;IEnumerable&amp;lt;T&amp;gt;&amp;gt; LoadAsync&amp;lt;T&amp;gt;(this DomainContext source, EntityQuery&amp;lt;T&amp;gt; query) where T : Entity
     {
        return source.LoadAsync(query, LoadBehavior.KeepCurrent);
     }

     public static Task&amp;lt;IEnumerable&amp;lt;T&amp;gt;&amp;gt; LoadAsync&amp;lt;T&amp;gt;(this DomainContext source, EntityQuery&amp;lt;T&amp;gt; query, LoadBehavior loadBehavior) where T : Entity
     {
         TaskCompletionSource&amp;lt;IEnumerable&amp;lt;T&amp;gt;&amp;gt; taskCompletionSource = new TaskCompletionSource&amp;lt;IEnumerable&amp;lt;T&amp;gt;&amp;gt;();

         source.Load(
             query,
             loadBehavior,
             loadOperation =&amp;gt;
             {
                 if (loadOperation.HasError &amp;amp;&amp;amp; !loadOperation.IsErrorHandled)
                 {
                     taskCompletionSource.TrySetException(loadOperation.Error);
                     loadOperation.MarkErrorAsHandled();
                 }
                 else if (loadOperation.IsCanceled)
                 {
                    taskCompletionSource.TrySetCanceled();
                 }
                 else
                 {
                     taskCompletionSource.TrySetResult(loadOperation.Entities);
                 }
             },
             null);

         return taskCompletionSource.Task;
     }
 }
  1. Using the lambda expression in the Load function ensures that the function will complete without executing the callback.
  2. The function returns a Task of IEnumerable of the requested entity and copys all the information from the LoadOperation object into the Task object (cancel and errors if exist) so there is no need to deal with the LoadOperation object on the calling side,thus  achieving a clean calling syntax (see the example bellow).
  3. The function’s name is compatible with the naming convention of Async suffix.

Example of client model function:

public Task&amp;lt;IEnumerable&amp;lt;Customer&amp;gt;&amp;gt; GetAllCustomer()
{
    DemoDomainContext dc = new DemoDomainContext();
    return  dc.LoadAsync(dc.GetAllCustomerQuery());
}

And client to this function can be:

IEnumerable&amp;lt;Customer&amp;gt; result = await GetAllCustomer();

I find that the above is a avery practical and clean solution to using the new and amazing Async framework combined with RIA.

Update – I updated the code for Visual Studio 2010 SP1 + Silverlight 5 and added the functions:

  • LoadEntityAsync – Supports methods that returns a single Entity and not IEnumerable<Entity>
  • InvokeAsync – Support for RIA Invoke methods, so you can write code like:
string methodResult = await dc.InvokeAsync(() =&amp;gt; dc.InvokeMethodName(parameter1));

Update – Update version for Visual Studio 2012 + Silverlight 5.
Source Code for this article
Source Code for this article – VS2012

Read Full Post »