views:

292

answers:

1

Our "user" model needs a small profile picture on it, and I'm not entirely sure how to handle it. Of course we could just save it to a folder on disk and store the path/filename to the database, but I think I'd rather have it stored in the DB itself.

My first thought was to have a property on the model like this:

[Property] 
public byte[] ProfilePicture
{
  get;
  set;
}

But it sure feels like I'm going to have to go a LONG way to get it working this way -- getting a byte array from the database, then converting it to an image with some sort of handler.

Has anyone seen a good tutorial on how to handle this sort of thing? It seems like it would be a common enough requirement that I'd find something MonoRail specific, but so far my searches have come up empty.

+1  A: 

About storing images on database or files, see this question.

If you decided to store it on DB, the most important thing is that you don't retrieve the byte[] every time you query for a User, that could be potentially a lot of data and a perf problem. To do that you could either store the image in another table or map the byte[] to another entity with the same table (assuming the user can have only one picture):

[ActiveRecord("users")]
public class UserWithoutPicture {
  [PrimaryKey]
  public virtual int Id {get;set;}
...
  [BelongsTo]
  public virtual UserProfilePicture ProfilePicture {get;set;}
}

[ActiveRecord("users")]
public class UserProfilePicture {
  [PrimaryKey]
  public virtual int Id {get;set;}

  [Property]
  public virtual byte[] Image {get;set;}
}

This would have some funky behaviors though. For example, for any given user, the ProfilePicture would never be null. You wouldn't really insert or delete UserProfilePicture since it's actually the user, instead you would always update. And you would incur an additional join, and you have to be aware of SELECT N+1. That's just off the top of my head, completely untested.

Conclusion: storing images in another table is much more flexible.

If you want the convenience of dealing with an Image instead of raw byte[], implement IUserType. But remember that Image is an IDisposable, and it'll be very hard to dispose it at the right time.

Implementing a Monorail controller that returns an image is quite straightforward... just use [ARFetch] to get the UserProfilePicture by id and write to the Response stream with the appropriate content-type.

Mauricio Scheffer