Interacting with SQL Server Data Services using SOAP

In one of my prior posts I promised some SOAP examples to better illustrate how you can use SOAP to interact with SSDS.  Therefore, to honor that I've decided to write some up some examples of using SOAP with SSDS.

Setting Scope

In the SOAP client we really don't have the luxury of being able to easily determine the scope of a particular operation from the different segments of a URI.  Therefore, to make establishing the scope of a given operation easy we introduced the notion of a scope object to the SOAP interface. 

This object captures all of the possible scopes that are valid for the service.  I've listed below both the Scope object definition as well as a description of what each of the settings mean in the context of the service.

Service Scope - This the scope when a scope object instance is passed to the service without any of the properties set.  This would typically be the case when the intent is to create a new authority object in the service.

Authority Scope - When just the authority id is specified on the scope object.  This is generally the case when the caller is attempting to create a container, retrieve the set (or a restricted set) of containers from a given authority or finally when attempting to simply retrieve a particular authority instance.

Container Scope - As you might imagine this scope is established when both the authority and container id properties are set on the scope object.  This scope is typically used when querying within a container for a set of entities (or all entities), creating new entities, or deleting a specific container.

Entity Scope - Used to narrow the focus of the operation to be performed down to the entity level.  This is typically used when the caller is attempting to update, retrieve or delete a specific entity within the service.

The generated C# code for the Scope object.

     public partial struct Scope : System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {
        
        [System.NonSerializedAttribute()]
        private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
        
        private string AuthorityIdField;
        
        [System.Runtime.Serialization.OptionalFieldAttribute()]
        private string ContainerIdField;
        
        [System.Runtime.Serialization.OptionalFieldAttribute()]
        private string EntityIdField;
        
        public System.Runtime.Serialization.ExtensionDataObject ExtensionData {
            get {
                return this.extensionDataField;
            }
            set {
                this.extensionDataField = value;
            }
        }
        
        [System.Runtime.Serialization.DataMemberAttribute(IsRequired=true)]
        public string AuthorityId {
            get {
                return this.AuthorityIdField;
            }
            set {
                if ((object.ReferenceEquals(this.AuthorityIdField, value) != true)) {
                    this.AuthorityIdField = value;
                    this.RaisePropertyChanged("AuthorityId");
                }
            }
        }
        
        [System.Runtime.Serialization.DataMemberAttribute()]
        public string ContainerId {
            get {
                return this.ContainerIdField;
            }
            set {
                if ((object.ReferenceEquals(this.ContainerIdField, value) != true)) {
                    this.ContainerIdField = value;
                    this.RaisePropertyChanged("ContainerId");
                }
            }
        }
        
        [System.Runtime.Serialization.DataMemberAttribute()]
        public string EntityId {
            get {
                return this.EntityIdField;
            }
            set {
                if ((object.ReferenceEquals(this.EntityIdField, value) != true)) {
                    this.EntityIdField = value;
                    this.RaisePropertyChanged("EntityId");
                }
            }
        }
        
        public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
        
        void RaisePropertyChanged(string propertyName) {
            System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
            if ((propertyChanged != null)) {
                propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
            }
        }
    }

So, now that we have some context about what scope is and what it's used to indicate within the service let's show some examples of using the service.

Creating Authorities

In this example I'd like to illustrate how to create an authority in the system.  As you may recall from some of other posts on our data model the Authority is the top level domain, so to speak, for a set of containers. 

All the containers created within a specific authority will be contained in a single data center.  During the authority creation process a domain name will be created automatically on your behalf.  This last point tends to be more important in the REST examples (from a programmatic point of view) but it will also have a greater significance in our later service releases.

 

The code...

             // Begin by creating an instance of our SOAP proxy class.
            using (SitkaSoapServiceClient client = new SitkaSoapServiceClient("SitkaSoapEndpoint"))
            {
                // Next, set the credentials that will be used to associate the request with a known
                // user in the system.  This user will also then become the, "owner" of this authority.
                client.ClientCredentials.UserName.UserName = "my_user";
                client.ClientCredentials.UserName.Password = "my_password";

                // Create a new scope object at the service level.
                Scope serviceScope = new Scope();

                // Next, create an Authority object and set the Id of that authority.
                Authority myNewAuthority = new Authority();
                myNewAuthority.Id = "ssdsrocks";

                try
                {
                    // Proceed to create the authority object.
                    Scope authorityScope = client.Create(serviceScope, myNewAuthority);

                    // Finally using the returned Scope object which is initialized to my 
                    // new authority object retrieve the authority.
                    Authority theAuthority = (Authority) client.Get(authorityScope);

                    Console.WriteLine("Here's my ID {0}", theAuthority.Id);

                }catch(FaultException<Error> ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }

The Results

image

 

Creating Containers

In the last example I gave an example of creating new authorities in SQL Server Data Services.  Now, let's go ahead and create some containers.  Recall that containers are the mechanism in our service that we use for partitioning data.  All of the data for a particular container will be located on a single machine within the cluster (with multiple replicas existing on other machines in the cluster). 

Now, with no further delay creating containers.

The code...

             // Begin by creating an instance of our SOAP proxy class.
            using (SitkaSoapServiceClient client = new SitkaSoapServiceClient("SitkaSoapEndpoint"))
            {
                // Next, set the credentials that will be used to associate the request with a known
                // user in the system. 
                client.ClientCredentials.UserName.UserName = "my_user_id";
                client.ClientCredentials.UserName.Password = "my_password";

                // Create a new scope object at our new authority level.
                Scope authorityScope = new Scope();
                authorityScope.AuthorityId = "ssdsrocks";

                // Next, create the new Container object and set the Id 
                string containerId = "MyMusic";
                Container newContainer = new Container();
                newContainer.Id = containerId;

                try
                {
                    // Proceed to create the container object.
                    Scope containerScope = client.Create(authorityScope, newContainer);

                    // Now, rather than simply retrieve the new container let's query the authority
                    // for it.
                    string query =
                        String.Format(@"from e in entities where e.Id ==""{0}"" select e", containerId);

                    List<Entity> containers = client.Query(authorityScope, query);

                    // Finally, let's print out the results of all the containers we've found.
                    foreach(Container c in containers)
                    {
                        Console.WriteLine("Container id:{0}", c.Id);
                    }
 

                }catch(FaultException<Error> ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }

and the Results...

image 

Creating Entities

Entities represent the really interesting stuff in the service.  These are the objects where the real data will be stored and later queried for.  In this example I will create some new entities (with some properties) and then query for a subset of the entities.

The code.

             // Begin by creating an instance of our SOAP proxy class.
            using (SitkaSoapServiceClient client = new SitkaSoapServiceClient("SitkaSoapEndpoint"))
            {
                // Next, set the credentials that will be used to associate the request with a known
                // user in the system. 
                client.ClientCredentials.UserName.UserName = "my_user_id"; 
                client.ClientCredentials.UserName.Password = "my_password";

                // Create a new scope object at our new container level.
                Scope containerScope = new Scope();
                containerScope.AuthorityId = "ssdsrocks";
                containerScope.ContainerId = "MyMusic";

                try
                {
                    // Create some entities with various properties.
                    Entity[] entities = new Entity[3];
                    entities[0] = new Entity();
                    entities[0].Id = "1";
                    entities[0].Kind = "Album";
                    entities[0].Properties = new Dictionary<string, object>();
                    entities[0].Properties["Artist"] = "The Shins";
                    entities[0].Properties["Title"] = "Chutes Too Narrow";

                    entities[1] = new Entity();
                    entities[1].Id = "2";
                    entities[1].Kind = "Album";
                    entities[1].Properties = new Dictionary<string, object>();
                    entities[1].Properties["Artist"] = "Brett Dennen";
                    entities[1].Properties["Title"] = "So Much More";

                    entities[2] = new Entity();
                    entities[2].Id = "3";
                    entities[2].Kind = "Album";
                    entities[2].Properties = new Dictionary<string, object>();
                    entities[2].Properties["Artist"] = "The Shins";
                    entities[2].Properties["Title"] = "Wincing the Night Away";

                    // NOTE: This is a unique property to this entity instance.
                    entities[2].Properties["Released"] = 2007m; // treat as decimal. 

                    // Go ahead and create the entities in the service.
                    foreach(Entity currentEntity in entities)
                    {
                        client.Create(containerScope, currentEntity);
                    }

                    // Okay, so the entities are there now.  Let's first retrieve all the entities.
                    List<Entity> allEntities = client.Query(containerScope, "from e in entities select e");
                    
                    Console.WriteLine("All Entities in container are:");
                    foreach(Entity e in allEntities)
                    {
                        Console.WriteLine("Entity id = {0}", e.Id);
                    }

                    // Now, let's restrict the set of entities returned to the one (and only one) that
                    // had a release date of 2007.
                    String query = String.Format(@"from e in entities where e[""Released""] == 2007 select e");
                    List<Entity> entityResults = client.Query(containerScope, query);

                    Console.WriteLine("All Entities with a Released property set to 2007:");
                    foreach (Entity e in entityResults)
                    {
                        Console.WriteLine("Entity id = {0}", e.Id);
                    }

                }catch(FaultException<Error> ex)
                {
                    Console.WriteLine(ex.Detail.Message);
                }
            }
 The Results...

 image

So, that wraps up the SOAP examples for tonight.  Hope you enjoy them and if you have questions (or other examples that you would like to see) please let me a comment back so that I can try to get it out there for you.

 

--Jeff--