With SimpleDB, you need to create a domain to store any data. Domain creation is a unique event in the life of an application, happening at install or some other infrequent event (addition of a new product line, client, etc. depending on how you partition data). 99+% of the time, the code will need to use the domain to Create, Retrieve, Update, or Delete data. These are more commonly known as CRUD operations. AWS stores the data as name-value pairs called attributes. The attributes have an additional value indicating if the value is replaceable/updatable or if the value can only be set of creation. Each item in the database has a name and a set of 1 or more attributes. In this post, I walk through how MembershipUser records are created and updated. This post uses Amazon’s SimpleDB C# library. The example has the following statements at the top of the file:
#light
namespace PhotoWeb_AWS
open System
open System.Web.Security
open Amazon.SimpleDB
open System.Configuration
Every SimpleDB record exists as a set of key value pairs. In our application, most of the attributes on a user can be updated. A user has the following attributes:
- password
- passwordQuestion: The special question to ask when the user forgets their password.
- passwordAnswer: The answer to the special question.
- isApproved: Can this user access the site.
- isLockedOut: Is the user’s account locked due to too many invalid password attempts in a short period of time.
- creationDate
- lastLoginDate
- lastActivityDate
- lastPasswordChangedDate
- lastLockoutDate
To handle the basics of creating these attributes, I have a pair of functions. One handles the very common scenario of creating a replaceable attribute. The other is the slightly more general purpose.
let CreateAttribute key value replaceable =
let retval = new Model.ReplaceableAttribute()
retval.Name <- key
retval.Value <- value
retval.Replace <- replaceable
retval
let CreateAttribute key value =
CreateAttribute key value true
In order to save a user (or any SimpleDB record), you need to have the following:
- A valid connection to the database.
- A PutAttributesRequest with the Domain set to an existing domain. The ItemName on the PutAttributesRequest must be unique within the domain.
- A set of attributes.
The SaveUser method below handles both Create and Update operations. If the ItemName doesn’t exist, it is created. If the ItemName does exist, it is updated.
let SaveUser(user :AwsMembershipUser) =
PhotoWebInit.InitializeAWS
let simpleDb = PhotoWebInit.SimpleDBClient
let putAttr = new Model.PutAttributesRequest()
putAttr.DomainName <- PhotoWebInit.domainName
putAttr.ItemName<- user.Email
let creationDate = System.DateTime.UtcNow
let userAttr = [|
CreateAttribute "password" (user.Password);
CreateAttribute "email" user.Email;
CreateAttribute "passwordQuestion" user.PasswordQuestion;
CreateAttribute "passwordAnswer" user.PasswordAnswer;
CreateAttribute "isApproved" (user.IsApproved.ToString());
CreateAttribute "isLockedOut" (user.IsApproved.ToString());
CreateAttribute "creationDate" (user.CreationDate.ToString());
CreateAttribute "lastLoginDate" (user.LastLoginDate.ToString());
CreateAttribute "lastActivityDate" (user.LastActivityDate.ToString());
CreateAttribute "lastPasswordChangedDate" (user.LastPasswordChangedDate.ToString());
CreateAttribute "lastLockoutDate" (user.LastLockoutDate.ToString());
|]
putAttr.Attribute <- new System.Collections.Generic.List<Model.ReplaceableAttribute>(userAttr)
let response = simpleDb.PutAttributes(putAttr)
()
Each of the values in the attribute must be non-null, populated strings. An empty or null string will cause SimpleDB to reject the PutAttributes request. Instead of storing a null, you need to write code that behaves properly when the key doesn’t exist.