Skip to content

Cassandra Object Mapper

djMax edited this page Sep 14, 2010 · 6 revisions

Introduction

The Cassandra Object Mapper is a framework that allows easy mapping of CLR objects to and from Cassandra rows/records. Cassandra terminology can take a lot of getting used to, and this article may not always get it right (it’s a wiki – fix it). The general idea is that we’d like to create a plain old .Net class, adorn it with some attributes, and then be able to load and save it from Cassandra, including lazy loading “related” Cassandra objects. Our not-so-hypothetical example will be a simple Customer object. We’ve named the object CCustomer, because we also use a relational store for things which require transactional consistency, and that uses BLToolkit to generate entities from the database, so it gets to keep the “Customer” class name. Sorry Cassandra, maybe someday you can has Customer.

Example

So, our declaration looks like this:


	[CassandraEntity("MyKeyspace", "Customer")]
	public class CCustomer : CassandraEntity<int>
	{
		/// <summary>
		/// Needs to be here for simpler generic constraints, perhaps there's a better declaration.
		/// </summary>
		public CCustomer() { }

		/// <summary>
		/// Construct a record for a given relational customer id
		/// </summary>
		public CCustomer(int id) : base(id) { }

		/// <summary>
		/// Expose the row key with a nicer property name
		/// </summary>
		public int CustomerId { get { return RowKey; } }

		/// <summary>
		/// Reference another Cassandra entity
		/// </summary>
		[CassandraRow] public CassandraRowReference<CImageContent> Photo;
	}

	[CassandraEntity("MyKeyspace", "MimeContent")]
	public class CImageContent : CassandraEntity<byte[]>
	{
		public CImageContent() { }

		public CImageContent(Bitmap b) : base(Hash(b)) { Image = b; }

		static byte[] Hash(Bitmap b)
		{
			using (MemoryStream mstr = new MemoryStream())
			{
				b.Save(mstr, b.RawFormat);
				byte[] bits = mstr.ToArray();

				var hasher = System.Security.Cryptography.SHA1.Create();
				return hasher.ComputeHash(bits);
			}
		}

		[CassandraColumn("Dims", typeof(CustomConverters.SizeConverter))]
		public Size Size;

		[CassandraColumn("Mime")]
		public string MimeType;

		[CassandraColumn("Data")]
		public Bitmap Image;
	}

Usage

Now, we can save, read, and partially save these entities:


	Bitmap b = (Bitmap) Image.FromFile(args[1]);

	CImageContent img = new CImageContent(b);
	img.MimeType = MimeType(args[1]);
	img.Size = new Size(b.Width, b.Height);

	CCustomer cust = new CCustomer(1);
	cust.Photo = img;

	using (var client = CassandraInterface.GetClient())
	{
		client.Save(ConsistencyLevel.ONE, img, cust);

		var exCust = client.SelectByRowKey<CCustomer>(1);
		// Load up the associated entity
		exCust.Photo.EnsureValue(client);

		// You can also save parts of an object
		client.SavePartial(ConsistencyLevel.ONE, () => { img.MimeType, img.Data });
	}
Clone this wiki locally