Consuming a document service

Let's head to Visual Studio and start consuming the document service that we created. You can open the Visual Studio project for this chapter, included in the code files for the book, to see the service in action.

If you are a more experienced Visual Studio user, you can create a project yourself by performing the following steps:

  1. In Visual Studio, create a project for a console application by navigating to File | New | Project….
  2. In the Installed Templates section, navigate to Visual C# | Windows.
  3. Choose a project of type Console Application, insert a name and location for the project, and click on OK.

To add the service reference, perform the following steps:

  1. In Solution Explorer, right-click on the name of your project and click on Add Service Reference….
  2. Enter the WSDL location in the Address field and click on Go. Of course, you'll need to replace DYNAX01:8101 with the server and port of your installation. You should see a form that looks similar to the following screenshot:
    Consuming a document service
  3. Enter TitleServiceRef in the Namespace field and click on OK.

In the following sections, we will go through all of the operations that are available in the service by using a console application. The console application prompts the user to select the action that needs to be executed. We will look only at the methods that consume the service. For the complete sample application, download and install the sample project for this chapter, which is included in the code files of the book. Be sure to read Appendix, Installing the Demo Application, for information on how to install and run the code.

Create

The first service operation lets us insert records into Microsoft Dynamics AX. The flow for using the Create operation is as follows:

  1. Create a new record entity and fill in the field information.
  2. Create a new document instance and put in the table entity array that contains the entities that you want to insert.
  3. Invoke the Create operation that returns the entity keys of the inserted records.

The following code reads an XML file that contains some sample titles to be inserted:

static void createTitles()
{
    List<MovieTitle> sampleTitles;
    int i = 0;

    // Read the XML file containing the sample data into a list
    using (var reader = new StreamReader(@"C:TempTitleDemoData.xml"))
    {
        XmlSerializer deserializer = new XmlSerializer(typeof(List<MovieTitle>));
        sampleTitles = (List<MovieTitle>) deserializer.Deserialize(reader);
    }

    // For all of the titles, create a title in the Ax database
    foreach (MovieTitle title in sampleTitles)
    {
        i++;

        // Create a title entity
        AxdEntity_CVRTitle titleEntity = new AxdEntity_CVRTitle();

        // Fill in all the fields
        titleEntity.Name = title.Name;
        titleEntity.Description = title.Description;
        titleEntity.LengthInMinutes = Convert.ToInt32(title.Length);
        
        // For int and real values, you must flag them as fill in
        // This is to tell Dynamics that they are not null, but the 
        // default value
        titleEntity.LengthInMinutesSpecified = true;

        // Create a title document instance
        AxdCVRTitle titleDocument = new AxdCVRTitle();

        // Initialize the list of title entities in the document
        // CVRTitle is a list of title entities
        titleDocument.CVRTitle = new AxdEntity_CVRTitle[1] { titleEntity };

        // Create an instance of the document service client
        using (CVRTitleDocumentServiceClient client = new CVRTitleDocumentServiceClient())
        {
            // Insert the title in Ax
            EntityKey[] entityKeys = client.create(null, titleDocument);

            // Report progress to the user
            Console.WriteLine(String.Format("Title {0} created", titleEntity.Name));
        }
    }
}

After executing the previous code, we can see the titles within Microsoft Dynamics AX:

Create

Find

The Find operation uses a QueryCriteria object that contains the criteria to be filtered and returns a document that contains the record entities. The flow for using the Find operation is as follows:

  1. Create a QueryCriteria object that contains the criteria's elements.
  2. Invoke the Find operation to retrieve a document instance that contains the resulting records.

Creating query criteria

For some operations, including the Find operation, you are required to pass a QueryCriteria object. Based on this QueryCriteria object, records are queried in Microsoft Dynamics AX. To facilitate the creation of QueryCriteria instances, a method was created, which is shown as follows:

static QueryCriteria createSingleCriteria(string dataSource
                                        , string fieldName
                                        , Operator op
                                        , string value1
                                        , string value2)
{
    // Prepare a queryCriteria instance
    QueryCriteria criteria = new QueryCriteria();

    // Create a criteria element that represents a query range
    CriteriaElement criteriaElement = new CriteriaElement();

    criteriaElement.DataSourceName = dataSource;
    criteriaElement.FieldName = fieldName;
    criteriaElement.Operator = op;
    criteriaElement.Value1 = value1;
    criteriaElement.Value2 = value2;

    // Put the criteria element in the QueryCriteria instance
    criteria.CriteriaElement = new CriteriaElement[1] 
                                    { 
                                        criteriaElement 
                                    };

    return criteria;
}

Using Find

Now that we have a way to create the query criteria that is needed for the Find operation, we can go ahead and use the Find operation to get the data from Microsoft Dynamics AX, as demonstrated in the following code snippet:

static void getTitles_Find()
{
    // Variable to hold the title document
    AxdCVRTitle titleDocument = new AxdCVRTitle();

    // Create a criteria element that selects titles that run over 110 
    // minutes
    QueryCriteria criteria = Program.createSingleCriteria("CVRTitle" , "LengthInMinutes", Operator.Greater, "110", null);

    // Create a client for as long as we need to
    using (CVRTitleDocumentServiceClient client = new CVRTitleDocumentServiceClient())
    {
        // Find the titles that match the criteria
        titleDocument = client.find(null, criteria);

        // Loop all the titles
        foreach (AxdEntity_CVRTitle title in titleDocument.CVRTitle)
        {
            // Report the results to the console window
            Console.WriteLine(title.Id + ' ' + title.Name + ' ' + title.LengthInMinutes);
        }
    }
}

A part of the result looks as follows:

T000000006 Schindler's List 114
T000000007 The Dark Knight 119
T000000008 The Lord of the Rings: The Return of the King 112
T000000011 Fight Club 115

Read

The Read operation sounds like the Find operation, but there is a difference. Find uses the query criteria as input and returns the title document immediately with all of the resulting rows. Read returns the same document but does not take the query criteria as a parameter. Instead, Read uses a set of Entitykey objects as input. As a result, the Read operation returns only one record for each entity key in the set, because the entity keys correspond to the primary key of the record.

You could be asking yourself why you would want to use Read instead of Find if the latter gives you the same result in one operation. Well, the answer is twofold.

The first scenario is one where you have already cached the entity keys in your application. In other words, you already know the unique key of the records that you want to retrieve. Then you can just construct an array of entity keys and invoke the Read operation.

The flow for using the Read operation with the custom entity keys is as follows:

  1. Create an array of the Entitykey objects that contain the keys of the records that you want to find.
  2. Invoke the Read operation to return a document that contains the related records.

The following is the code implementation:

static void getTitle_ReadWithEntityKey()
{
    // Let the user enter an Id in the console window
    Console.WriteLine("Enter a title Id to look for :");
    string titleId = Console.ReadLine();
    
    // Create an instance of the keyfield containing the title id to 
    // search for
    KeyField keyField = new KeyField() { Field = "Id", Value = titleId };
    
    // Create an entity key instance and put in the key field data
    EntityKey entityKey = new EntityKey();
    entityKey.KeyData   = new KeyField[1] { keyField };

    // Create an array of entity keys and put in the previously created key
    EntityKey[] entityKeys = new EntityKey[1] { entityKey };

    AxdCVRTitle titleDocument = new AxdCVRTitle();

    // Create a client for as long as we need to
    using (CVRTitleDocumentServiceClient client = new CVRTitleDocumentServiceClient())
    {
        // Use the keys to read all of the titles
        titleDocument = client.read(null, entityKeys);
    }

    // Loop all the titles to report to the console window
    foreach (AxdEntity_CVRTitle title in titleDocument.CVRTitle)
    {
        Program.printSingleTitle(title);
    }
}

If we execute the previous code for title ID T000000007, the following result is printed to the console window:

Title : T000000007
Name : The Dark Knight
Length in minutes : 119
Description : When Batman, […]

FindKeys

The second scenario, in which you can use the Read operation, is used in combination with the FindKeys operation. This can enhance the performance. Let's say that you have a .NET application that queries Microsoft Dynamics AX. It's possible that your query will return a large number of records but you want to use paging so that you don't have to load all of the data at once. So, you can use the FindKeys operation to return only the keys of the records instead of all of the fields. Once you have the keys, you can implement paging in your application and call the Read operation with the subset of keys that are actually needed.

The flow for using the Read operation with FindKeys is as follows:

  1. Create a QueryCriteria instance that contains the criteria for finding the records.
  2. Invoke the FindKeys operation to retrieve the keys that match the query.
  3. Using the keys, invoke the Read operation to return a document that contains the related records.

The following is the code implementation:

static void getAllTitles_ReadWithFindKeys()
{
    // Variable to hold the title document
    AxdCVRTitle titleDocument = new AxdCVRTitle();

    // Create a criteria element that selects titles that run over 110 
    // minutes
    QueryCriteria criteria = Program.createSingleCriteria("CVRTitle" , "LengthInMinutes", Operator.Greater, "110", null);

    // Create a client for as long as we need to
    using (CVRTitleDocumentServiceClient client = new CVRTitleDocumentServiceClient())
    {
        // Call the findKeys operation to fetch all of the keys that 
        // match the query criteria
        EntityKey[] entityKeys = client.findKeys(null, criteria);

        // Check if we had matching titles
        if (entityKeys.Length > 0)
        {
            // Use the keys to read all of the title records
            titleDocument = client.read(null, entityKeys);
        }
    }

    if (titleDocument != null)
    {
        // Loop all the titles to report to the user
        foreach (AxdEntity_CVRTitle title in titleDocument.CVRTitle)
        {
            Console.WriteLine(title.Id + ' ' + title.Name + ' ' + title.LengthInMinutes);
        }
    }
}

As we are using the same query criteria, we should see the same result as the Find operation. A part of the result looks as follows:

T000000006 Schindler's List 114
T000000007 The Dark Knight 119
T000000008 The Lord of the Rings: The Return of the King 112
T000000011 Fight Club 115

Update

To update records in the Microsoft Dynamics AX database, the Update operation can be used. First, you need to use the Read operation to get the records that you want to update. For this, you need to specify the entity keys. Once you have the document that contains the records that you want to update, you can edit the fields and then call the Update operation. The basic flow for updating the records is as follows:

  1. Create an array of Entitykey objects.
  2. Invoke the Read operation to retrieve the data from Microsoft Dynamics AX.
  3. Update the fields that you want to change.
  4. Change the action property on the changed records to be updated.
  5. Invoke the Update operation.

The following is the code implementation:

static void updateTitle()
{
    Console.WriteLine("Enter a title Id to look for :");
    string titleId = Console.ReadLine();

    // Create an instance of the keyfield containing a record id to 
    // search for
    KeyField keyField = new KeyField() { Field = "Id", Value = titleId };

    // Create an entity key instance and put in the key field data
    EntityKey entityKey = new EntityKey();
    entityKey.KeyData = new KeyField[1] { keyField };

    // Call the findKeys operation to fetch all of the keys that match 
    // the query criteria
    EntityKey[] entityKeys = new EntityKey[1] { entityKey };

    // Create a client for as long as we need to
    using (CVRTitleDocumentServiceClient client = new CVRTitleDocumentServiceClient())
    {
        // Use the keys to read all of the titles
        AxdCVRTitle titleDocument = client.read(null, entityKeys);

        // Get the CVRTitle record entity
        AxdEntity_CVRTitle title = titleDocument.CVRTitle.First();

        title.Description = "Updated Description";
        title.action = AxdEnum_AxdEntityAction.update;
        title.actionSpecified = true;

        // Invoke the update operation
        client.update(null, entityKeys, titleDocument);
    }
}

Delete

As you might have guessed already, the Delete operation will delete records from Microsoft Dynamics AX. The flow for using the Delete operation is as follows:

  1. Create an array of EntityKey objects.
  2. Invoke the Delete operation to delete the data from Microsoft Dynamics AX.

The following code will prompt the user to enter a title ID and then delete that title from Microsoft Dynamics AX:

static void deleteTitle()
{
    // Let the user enter an Id in the console window
    Console.WriteLine("Enter a title Id to delete :");
    string titleId = Console.ReadLine();

    // Create an instance of the keyfield containing the title id to 
    // search for
    KeyField keyField = new KeyField() { Field = "Id", Value = titleId };

    // Create an entity key instance and put in the key field data
    EntityKey entityKey = new EntityKey();
    entityKey.KeyData = new KeyField[1] { keyField };

    // Create an array of entity keys and put in the previously 
    // created key
    EntityKey[] entityKeys = new EntityKey[1] { entityKey };

    using (CVRTitleDocumentServiceClient client = new CVRTitleDocumentServiceClient())
    {
        client.delete(null, entityKeys);
    }
}

GetKeys

The GetKeys operation will return the keys for records that match the document filter that is configured on the integration port. Document filters are only available on enhanced integration ports.

Document filter

For the sake of this demonstration, we assume that a document filter is added on the port used by the CVRTitleDocumentService service, as shown in the following screenshot:

Document filter

Using GetKeys

The flow for using the GetKeys operation is as follows:

  1. Create a DocumentPaging object that contains the number of keys to be returned (optional).
  2. Invoke the getKeys operation that returns the entity keys that match the document filter.
  3. Use the Read operation to retrieve the data of the related records when needed.

The following code uses GetKeysoperation to fetch the records from Microsoft Dynamics AX that match the document filter that we just discussed:

static void getKeys()
{
    AxdCVRTitle titleDocument = new AxdCVRTitle();

    // Create a client for as long as we need to
    using (CVRTitleDocumentServiceClient client = new CVRTitleDocumentServiceClient())
    {
        // Call the findKeys operation to fetch all of the keys that 
        // match the document filter
        EntityKeyPage keyPage = client.getKeys(null, null);

        // Fetch the entity key list from the page
        EntityKey[] entityKeys = keyPage.EntityKeyList;

        // Check if we had matching titles
        if (entityKeys.Length >= 0)
        {
            // Use the keys to read all of the titles
            titleDocument = client.read(null, entityKeys);
        }
    }

    // Loop all the titles to report to the console
    foreach (AxdEntity_CVRTitle title in titleDocument.CVRTitle)
    {
        Console.WriteLine(title.Id + ' ' + title.Name + ' ' + title.LengthInMinutes);
    }
}

Based on the document filter that selects titles starting with The, a part of the resulting titles looks as follows:

T000000001 The Godfather 102
T000000002 The Godfather: Part II 102
T000000004 The Good, the Bad and the Ugly 97
T000000007 The Dark Knight 119
T000000008 The Lord of the Rings: The Return of the King 112
T000000009 The Dark Knight Rises 103

GetChangedKeys

The GetChangedKeys operation also fetches the keys of records from Microsoft Dynamics AX that match the document filter. In addition to this, it also restricts the returned keys to records that have changed since a given date and time.

Tip

Change tracking

To be able to use getChangedKeys, SQL Server Change Tracking has to be configured. Once change tracking has been configured, the integration ports will need to be reactivated.

Information about change tracking can be found at the following links:

The flow for using the GetChangedKeys operation is the same as the one for using the getKeys operation. The difference is that you can retrieve only the records that have changed since a given date instead of all the records that the document filter applies to. The following code shows us the use of the same document filter. It also illustrates the use of change tracking to further narrow down the list to only the records that were changed. This assumes that we have updated the records with change tracking enabled:

static void getChangedKeys()
{
    AxdCVRTitle titleDocument = new AxdCVRTitle();

    // Create a client for as long as we need to
    using (CVRTitleDocumentServiceClient client = new CVRTitleDocumentServiceClient())
    {
        // Call the getChangedKeys operation to fetch all of the keys 
        // that were changed
        // The change date used here was 2013/12/01 15:30
        EntityKeyPage keyPage = client.getChangedKeys(null, null, new DateTime(2013, 12, 01, 15, 30, 00));
        // Fetch the entity key list from the page
        EntityKey[] entityKeys = keyPage.EntityKeyList;

        // Check if we had matching titles
        if (keyPage.PageStatus == EntityKeyPageStatus.Success && entityKeys.Length > 0)
        {
            // Use the keys to read all of the titles
            titleDocument = client.read(null, entityKeys);
        }
    }

    // Loop all the titles to report to the console
    foreach (AxdEntity_CVRTitle title in titleDocument.CVRTitle)
    {
        Console.WriteLine(title.Id + ' ' + title.Name + ' ' + title.LengthInMinutes + ' ' + title.Description);
    }
}

As we updated one record for this sample, the following is the result:

T000000007 The Dark Knight 119 Updated Description for the dark knight
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.141.200.3