- 论坛徽章:
- 0
|
I hate relational databases! In a high traffic scenario they become painful to scale. Data segmentation, replication, asynchronous updates….you can only go so far. Schema changes alone require site outages and careful planning. That is why I was excited when Amazon announced their
SimpleDB
service.
Features:
- High Availability
- Scales with you
- No need to worry about schema
- Has a free tier for low traffic uses
I am working on two social networking sites (
tool-assisted
,
beerpassport
) that I plan to use SDB for. The basic idea is to have several cheap web servers talking to a pool of memcached instances that act as a caching mechanism for my object graph which is stored in SDB. The first step towards implementing this solution is to come up with a way to persist objects into the SDB.
Object to be persisted
First lets look at the object I want to save to the database. I want as little actual db code in this object as possible.
[code:c#]using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ToolAssistedCom.Models;
using Amazon.SimpleDB.ORM;
namespace ToolAssistedCom.Models
{
public class Platform
{
public string Description { get; set; }
public List Manufacturers { get; set; }
public string Name { get; set; }
public List OnlineServices { get; set; }
public string Predecessor { get; set; }
public string Successor { get; set; }
[SDB(IsKey = true)] public string UID { get; set; }
///
/// Default constructor
///
public Platform()
{
Description = "";
UID = "";
Name = "";
Manufacturers = new Liststring>();
Predecessor = "";
Successor = "";
OnlineServices = new Liststring>();
}
}
}[/code]
Base Class
Now I am going to define my base class. I want this class to be generic enough to load any object from the database. I have defined two methods called LoadOne and LoadMany which will be used to do this. I have not implemented a save mechanism yet.
[code:c#]using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Amazon.SimpleDB;
using Amazon.SimpleDB.Model;
using System.Reflection;
using Attribute = Amazon.SimpleDB.Model.Attribute;
namespace Amazon.SimpleDB.ORM
{
public abstract class SimpleDBObject
{
protected string _domainName = "";
protected string _columns = "*";
protected string _sort = "";
protected string _accessKeyId = "YOURKEY";
protected string _secretAccessKey = "SECRETKEY";
protected AmazonSimpleDB _service = null;
protected SelectRequest _request = null;
protected object _prototype = null;
protected void SetupClient()
{
_service = new AmazonSimpleDBClient(_accessKeyId, _secretAccessKey);
}
protected void CreateNewSelectRequest()
{
_service = new AmazonSimpleDBClient(_accessKeyId, _secretAccessKey);
_request = new SelectRequest();
}
protected void SetValueFromResponse(ref object myobj, string name, string value)
{
// Include the type of the object
System.Type type = myobj.GetType();
// Walk the properties on this object
System.Reflection.PropertyInfo[] pi = type.GetProperties();
if (pi.Length > 0)
{
foreach (PropertyInfo p in pi)
{
if (p.CanRead && p.CanWrite && p.Name.ToLower() == name.ToLower())
{
if (p.PropertyType == typeof(List))
{
((Liststring>)p.GetValue(myobj, null)).Add(value);
}
else if (p.PropertyType == typeof(string))
{
p.SetValue(myobj, value, null);
}
else if (p.PropertyType == typeof(int))
{
p.SetValue(myobj, int.Parse(value), null);
}
}
}
}
}//send SetValueFromResponse
protected void LoadOneFromDB(string id)
{
SetupClient();
CreateNewSelectRequest();
_request.SelectExpression = "select " + _columns + " from " + _domainName + " where UID = '" + id + "'";
if (!string.IsNullOrEmpty(_sort))
{
_request.SelectExpression += " order by " + _sort;
}
SelectResponse response = _service.Select(_request);
if (response.IsSetSelectResult())
{
SelectResult result = response.SelectResult;
List itemList = result.Item;
foreach (Item item in itemList)
{
if (item.IsSetName())
{
}
List attributeList = item.Attribute;
foreach (Attribute attribute in attributeList)
{
if (attribute.IsSetName() && attribute.IsSetValue())
{
SetValueFromResponse(ref _prototype, attribute.Name, attribute.Value);
}
}//end foreach attribute
}//end for each item
}//if issetseltresult
else
{
throw new Exception("WTF M8");
}
}
protected List LoadManyFromDB()
{
Listobject> myList = new Listobject>();
SetupClient();
CreateNewSelectRequest();
_request.SelectExpression = "select " + _columns + " from " + _domainName;
if (!string.IsNullOrEmpty(_sort))
{
_request.SelectExpression += " order by " + _sort;
}
SelectResponse response = _service.Select(_request);
if (response.IsSetSelectResult())
{
SelectResult result = response.SelectResult;
List itemList = result.Item;
foreach (Item item in itemList)
{
if (item.IsSetName())
{
}
object myobj = System.Activator.CreateInstance(_prototype.GetType());
List attributeList = item.Attribute;
foreach (Attribute attribute in attributeList)
{
if (attribute.IsSetName() && attribute.IsSetValue())
{
SetValueFromResponse(ref myobj, attribute.Name, attribute.Value);
}
}//end foreach attribute
myList.Add(myobj);
}//end for each item
}//if issetseltresult
else
{
throw new Exception("WTF M8");
}
return myList;
}
}
}[/code]
Glue Code
Finally here is the code that glues it together.
[code:c#]
class="MsoNormal"> using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Amazon.SimpleDB.ORM;
using System.Reflection;
namespace ToolAssistedCom.Models
{
public class SDBPlatform : SimpleDBObject, IPlatformRepository
{
public SDBPlatform()
{
_domainName = "Platform";
_prototype = new Platform();
}
public Platform GetByUID(string id){
LoadOneFromDB(id);
return ((Platform)_prototype);
}
public void Add(Platform entity)
{
throw new NotImplementedException();
}
public void Remove(Platform entity)
{
throw new NotImplementedException();
}
public List GetPlatforms()
{
List temp = new List();
foreach (Platform item in LoadManyFromDB())
{
temp.Add(item);
}
return temp;
}
public void Save(Platform entity)
{
throw new NotImplementedException();
}
}
}
class="MsoNormal"> [/code]
I will release more details as I finish writing the code. Once the code is in a pretty good state I will throw it up on codeplex incase anyone else wants to use it (or improve it).
[/url]
本文来自ChinaUnix博客,如果查看原文请点:[url]http://blog.chinaunix.net/u/78/showart_1891282.html |
|