Best Practices for Images in a Model with Castle ActiveRecord/MonoRail - castle-activerecord

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.

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.

Related

Single User Application File/Data Storage Recommendations

I currently have a C# winform application in which you enter data that is ultimately relational. The amount of data being stored isn't huge. The original version used SQL CE to store the information. However, I found it to be quite slow. Also, I wanted to be able to save application files using my own extension.
I had changed my approach to basically keep my data loaded in-memory using class objects. To save, I simply serialize everything using ProtoBuf and deserialize when opening a file. This approach is lightning fast and changes are never persisted until a user clicks save. However, I find it a little cumbersome to query my hierarchical data. I query data using Linq-To-Objects. I'll have ClassA having a GUID key. I can reference ClassA in ClassB via the GUID. However, I can't really do an easy SQL join-type query to get ClassB properties along with ClassA properties. I get around it by creating a navigation property on ClassB to ClassA that simple returns ClassA via a LINQ query on the GUID. However, this results in a lot of collection scanning.
What options are out there that give me fast, single-user, relational file storage? I would still like to work in-memory where changes aren't persisted until a user uses File|Save. I would also like to be able to continue querying the data using LINQ. I'm looking at SQLite as an option. Are there better options or approaches out there for me?
UPDATE
I was unaware of the AsReference option in the ProtoMember attribute [ProtoMember(5, AsReference = true)]. If I abandon foreign keys in my classes and simply reference the related objects, then it looks like I'm able to serialize and deserialize using ProtoBuf while keeping my object references. Thus, I can easily use Linq-To-Objects to query my objects. I need to stop thinking from the database side of things.
If you have all your objects in some sort of hierarchical structure, you can also store the exact same objects in other structures at an overhead of 4 bytes/object (32bit machines).
Assuming you have a base object like:
public class HierarchyElement
{
public List<HierarchyElement> Children { get; set; }
public HierarchyElement Parent { get; set; }
}
So you have the root element in a local variable, which via the Children property, and the Children property of those first children, etc etc store an unknown number of objects in a hierarchy.
However, while you are building that object, or after deserialising it, you can add a reference to each HierarchyElement to a List (or other flat structure of your choice).
You can then use this flat list to do your Linq queries against.

OOAD - Properties representing relationships between two types

I have started to model some city-transport data (bus lines and bus stops) for a community project. The data arrived to me as JSON files, and I'd like to create some classes from it, considering the already available data at first.
There is a BusLine object, whose JSONs don't contain information about which BusStop are related to it.
And there is a large collection of BusStop, of which one property is BusLines, a collection of (references to) bus lines which pass about that stop.
So far I have modelled this (C# style, but intended just for visualization at first):
public class BusLine
{
public String code;
public String name;
public List<DirectPosition> route;
}
public class BusStop
{
public String code;
public DirectPosition location;
public List<BusLine> busLines;
}
My doubt, from now, is this: most probably, I'll want to know the BusStops associated with a given BusLine. I imagine some possible ways of doing it, but am not sure at all how this rather trivial situation should be addressed. My naive thoughts:
Create a getStops() method that would look somewhere to check which stops existed along that route, and create such list on-the-fly;
Create an explicit List<BusStop> stops property in BusLine class (that sounds very wrong);
Eliminate containment altogether and create a third, "Relation" kind of class that would manage (somehow) the relations between those classes. That would mean the knowledge about those relations, extracted from the JSON files, wouldn't be stored "inside" the entities, but somewhere else.
I am pretty sure this is a common pattern (I'd bet there's at least one design pattern for that), but my current level of knowledge gives me no clue...
Thanks for any help!

Silverlight serialize object with cycles in object graph

I'm having an issue serializing objects when sending them to my WCF services. My classes look like this.
public class Foo
{
public Bar Bar { get; set; }
}
public class Bar
{
public Foo Bar { get; set; }
}
This causes a cycle in my object graph. I've fixed this on the server end by using the PreserveReferencesOperationBehavior. However, I still get an error when I try to serialize the objects in Silverlight.
While I can mark my objects with [DataContract(IsReference = true)], I'd prefer not to use this method because I have a large number of classes, many of which have over 100 properties and I don't want to have to add the [DataMember] attribute to each property.
Is there any other way to tell Silverlight to preserve references?
If it matters at all, I am using EntityFramework 4 with Code First.
The infered DataContract behaviour of the serializer is present to assist in the simple DTO scenarios. If you want to do it "properly" you should be using the DataContract and DataMember attributes.
When you find you have anything other than the most simple of scenarios you just need to do things properly. The correct and only way to handle circular references is with IsReference.
Lesson here is that helpful magic pixie dust only goes so far after that you just need to put in the graft. Sorry its not the answer you were looking for.

DB4O with Silverlight RIA Services

I've considered using the db4o OODBMS with a recent Silverlight / RIA Services project, but there's one point that I could use some advice on - how to make associations work. RIA Services requires that you mark all of your associated entities with an AssociationAttribute. The AssociationAttribute's constructer requires that you specify your entity's key to the associated entity, and the key of the associated entity itself.
As an example, imagine that I have a Racer class with CarID and Car properties, and a Car class with an ID property. My Racer class would look something like this:
class Racer
{
public int ID { get; set; }
public int? CarID { get; set; }
[Association("Racer_Car", "CarID", "ID")]
public Car Car { get; set; }
}
The problem that I see with using db4o (or any OODBMS) is that foreign keys and primary keys do not, and need not, exist - and the result is that I wouldn't need the Racer.CarID and Car.ID properties. To make this work with RIA Services, I would need to create my own unique keys, which I don't mind, I just don't know the best way to go about doing so.
So my question for you is "how would you create these keys/IDs"?
Since there isn't any concept of an auto incrementing generated field (none that I'm aware of any way), I would have to choose between trying to manually, safely increment the keys, or use something like a Guid. Since the former would be more difficult to manage with multiple users and/or multithreading, I'd imagine that using a Guid would be the simplest solution.
So let's consider using a Guid. The easiest solution would be to create my ID properties, just as I had within the example above, but use a Guid instead of int. I would need to set the ID to a new Guid after creating new entities - then, whenever I set the the Racer.Car property, I would also need to set the Racer.CarID.
Doing that by hand would be prone to error, so I'd want a lot of that handled in the property getters and setters, but I'm not sure of the best way to implement that.
That's what I've thought of so far. I think I'll look into how the Linq-to-SQL generated code handles some of these concerns - maybe I'll find a clue there.
Any suggestions would be greatly appreciated.
Thanks,
-Charles
Db4o does use IDs and UUIDs internally and it is possible to use those. Also worth reading is this.

Is it bad practices to allow null fields to a DB Table in order to simplify Model Binding from Ajax?

Please read here and here to get a quick overview of my problem and to see exactly what I mean when I say Model Binding from Ajax.
Would it be a bad idea to make the foreign key fields nullable in order to allow for Model Binding from javascript?
For example, we want to bind to a Person object during an ajax call to... (The Person class is created from the Entity Framework)
public ActionResult Create(Person personToCreate)
{
//Create person here
}
If the Person had a Pet object that was a foreign key in the db, you can't pass the Pet object along with the other data from the ajax call. So unless the Pet is nullable in the DB, binding to Person wouldn't work.
So what I want to know is... in order to do Model Binding, should/can I null the db fields I can't pass from javascript? Or do I have to make a Custom Model Binder and bind to a "Flatter" version of the object in order to follow best practices? example of flatter version of the object:
public class SimplePerson() {
private string firstName;
private string lastName;
private string petName;
}
The reason I ask this is because a lot of my Entity Framework created classes contain foreign keys, which means I'll need to create a flat duplicate of nearly all of those classes, and it seems to go against the whole DRY principal.
I read over what you linked and posted, I can't really think of a good solution off the top of my head, but the whole concept of changing your underlying database for the sake of AJAX makes me uncomfortable. I know that's not a great answer, I'm struggling with several EF design issues right now myself, and there have been several times when I've been tempted to modify the database for the sake of the model, but doing that has always come back to bite me in the past.

Resources