Using Scalable Table

Table with BCL dictionary based item
Table put and delete writers and select reader
Table XML configuration

Using Scalable Queue

Queue with string based message


Using scalable table with BCL dictionary based item

We create instance of SdbTable and pass ensureDomain true so if Amazon SimpleDB domain does not exist it will be created

ITable phoneBook = SdbTable.Create(ServiceId, ServiceSecret, "PhoneBook", null, true);

Let's define phone book item class. By basing on BCL dictionary we use simplified SimpleDB item model. All attributes in this simplified mode have only single value.

public class PhoneItem : Dictionary<string, string>
{
    public PhoneItem() { }

    public string FirstName { get { return this["FirstName"]; } set { this["FirstName"] = value; } }
    public string LastName { get { return this["LastName"]; } set { this["LastName"] = value; } }
    public string Number { get { return this["Number"]; } set { this["Number"] = value; } }
}

Now it is possible to add some items to phone book table. Note that Set accepts item name string and instance of PhoneItem.

phoneBook.Set("nielsb", new PhoneItem() { FirstName = "Niels", LastName = "Bohr", Number = "999-123-4567" });
phoneBook.Set("aageb", new PhoneItem() { FirstName = "Aage", LastName = "Bohr", Number = "999-987-6543" });
phoneBook.Set("alberte", new PhoneItem() { FirstName = "Albert", LastName = "Einstein", Number = "999-333-4444" });

By setting PhoneItem for exitsing item name it is possible to update item. Only key value pairs set in the dictionary will be updated. Non-empty value string will replace attribute value for corresponding key. Empty or null value string will delete attribute for corresponding key.

phoneBook.Set("nielsb", new PhoneItem() { Number = "999-123-0000" });
phoneBook.Set("aageb", new PhoneItem() { FirstName = string.Empty });

It is easy to select all phone book items with specified last name. Note that Get returns IEnumerable<KeyValuePair<string, PhoneItem>>, where Key is the item name

var phoneItems = phoneBook.Get<PhoneItem>(Condition.WithAttributeValue("LastName", "Bohr")).Select(pair => pair.Value);

foreach (PhoneItem phoneItem in phoneItems)
{
    Console.WriteLine(phoneItem.Number);
}

You should get (with undefined order)

999-123-0000
999-987-6543




Using scalable table with put and delete writers and select reader

Table additionally supports put and delete writers to allow more flexible operation on attributes. By passing action lambda to Put method it is possible to add or replace attributes. Similarly by passing action lambda to Delete it will delete attributes by name or by name and value. Next example replaces first and last name attribute and adds two number attribute values

phoneBook.Put("nielsb", w =>
{
    w.ReplaceAttribute("FirstName", "Niels");
    w.ReplaceAttribute("LastName", "Bohr");

    w.AddAttribute("Number", "1234");
    w.AddAttribute("Number", "2345");
});

To delete all values of first name attribute and specified value of number attribute

phoneBook.Delete("nielsb", w =>
{
    w.DeleteAttribute("FirstName");

    w.DeleteAttribute("Number", "1234");
});

Correspondingly, multi-valued attributes can be read with Select method that returns reader. Initially reader is in position before first item. Read method returns true if it advanced to the next item, attribute or attribute value. Position property returns one of the following reader positions: Item, EmptyItem, Attribute or Value. Item position means that reader is at the beginning of the item and ItemName, AttributeName and AttributeValue properties contain valid values. EmptyItem is returned when reader encountered empty item, in other words there were no attributes selected, in this state only ItemName property has valid value. Attribute position means that reader is at the beginning of the next attribute of the same item, therefore ItemName property has the value from previous position, while AttributeName and AttributeValue properties contain next attribute name and value. Value reader position is returned when reader is at the next value of the same item and same attribute. In this position both ItemName and AttributeName properties remain the same as in previous position and AttributeValue property contains next value.

There are two variants of Select method that return reader. First is static on SdbTable and directly passes select expression to SimpleDB - it is not implemented in local file system table. Second is on ITable interface and takes list of attribute names to be selected and filtering condition. When attribute list is empty or null then all attributes are returned (effectively 'select *'). When condition is null then no filtering is performed (effectively no 'where' clause). Variety of conditions can be created using Condition class factory, including attribute existence and value tests, value ranges, and logical groups. All conditions are supported by both SimpleDB and local file system table implementations and unit tests ensure that they have the same behavior. For example to print all items and all attributes of phone book

using (IReader reader = phoneBook.Select((string[])null, (Condition)null)))
{
    while (reader.Read())
    {
        Console.WriteLine("{0} {1} {2}", reader.ItemName, reader.AttributeName, reader.AttributeValue);
    }
}

To print phone book item names and numbers

using (IReader reader = phoneBook.Select(new string[] { "Number" }, (Condition)null))
{
    while (reader.Read())
    {
        Console.WriteLine("{0} {1}", reader.ItemName, reader.AttributeValue);
    }
}

Logical group conditions for AND and OR take one or more inner conditions. Logicals groups are created with Condition.And and Condition.Or factory methods. Attribute conditions are correspondingly created with Condition.WithAttributeValue, Condition.WithAttributeIsNotNull, Condition.WithAttributeIsNull etc. factory methods

using (IReader reader = phoneBook.Select(new string[] { "Number" }, 
    Condition.And(Condition.WithAttributeValue("FirstName", "Albert"), Condition.WithAttributeIsNotNull("LastName"))))
{
    while (reader.Read())
    {
        Console.WriteLine("{0} {1}", reader.ItemName, reader.AttributeValue);
    }
}


Using scalable table XML configuration

To enable runtime configuration create configuration XML file, e.g. PhoneBook.xml

<Coniguration>
  <Table>
    <AssemblyName>Stratosphere</AssemblyName>
    <TypeName>Stratosphere.Table.Sdb.SdbTable</TypeName>
    <ServiceId>...</ServiceId>
    <ServiceSecret>...</ServiceSecret>
    <DomainName>PhoneBook</DomainName>
    <EnsureDomain>true</EnsureDomain>
  </Table>
</Coniguration>

Now you can change code to create phone book table from configuration

ITable phoneBook = TableConfiguration.Configure(XElement.Load("PhoneBook.xml"));

It's easy to test application locally by changing configuration to use file system (SQLite backed) implementation. Note that you need to add reference to Stratosphere.FileSystem

<Coniguration>
  <Table>
    <AssemblyName>Stratosphere.FileSystem</AssemblyName>
    <TypeName>Stratosphere.Table.FileSystem.FileSystemTable</TypeName>
    <DatabaseFileName>c:\PhoneBook.db3</DatabaseFileName>
  </Table>
</Coniguration>


Using scalable queue with string based message

First we create instance of queue object. Note that Create method will ensure that Amazon SQS queue exists

IQueue queue = SqsQueue.Create(ServiceSecret, ServiceId, "UserFeedback");

Now we can send some feedback messages

queue.Send("I have troubles logging in");
queue.Send("Great application!");
queue.Send("How boring...");

We may receive messages in batches with maximum count specified (e.g. 5). Note that you need to Delete message via receipt, otherwise it will appear again after invisibility timeout

foreach (IReceipt receipt in queue.Receive(5))
{
    Console.WriteLine(receipt.Message);
    receipt.Delete();
}

In our example this may return. Note that order or messages in undefined, some messages may be arrive more than once and not all messages may arrive in one receive

How boring...
I have troubles logging in
Great application!


You may also try to receive single message

IReceipt receipt = queue.Receive();

if (receipt != null)
{
    Console.WriteLine(receipt.Message);
    receipt.Delete();
}

Last edited May 26, 2010 at 5:16 AM by petrohi, version 14

Comments

No comments yet.