Reputation: 65
This is probably a stupid question, I tried looking for similar post but I couldn't find any so if there's some.
I'm starting to use SQL, it's quite easy but how can I save an entire object in it?
I try to explain better. If I want to save an instance of a "car" object should I just save its primitive values or is there a way to save the entire object?
Also, which SQL software you guys suggest to use? I only tried with Mac embedded sqlite
Upvotes: 2
Views: 223
Reputation: 437592
A couple of thoughts:
If you're going to do SQLite programming in Objective-C, you should consider FMDB. That makes SQLite programming much easier.
Generally, though, Core Data is the preferred object persistence technology.
But assuming you wanted to save an object in a SQLite table, you can store the object in your database as a blob by creating an archive and saving that in your database:
Create an archive (see Archives and Serializations Programming Guide):
Car *car = [[Car alloc] init];
car.make = @"Honda";
car.model = @"Accord";
car.year = 1998;
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:car];
But for that to work, you have to implement the initWithCoder
and the encodeWithCoder
methods for your Car
class as described in the Encoding and Decoding Objects section:
- (NSArray *)propertyNames
{
return @[@"make", @"model", @"year"];
}
- (id) initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
for (NSString *key in [self propertyNames]) {
[self setValue:[aDecoder decodeObjectForKey:key] forKey:key];
}
}
return self;
}
- (void)encodeWithCoder:(NSCoder *)aCoder
{
for (NSString *key in [self propertyNames]) {
[aCoder encodeObject:[self valueForKey:key] forKey:key];
}
}
You can save this as a blob in your database. Use sqlite3_bind_blob
or, easier, use FMDB:
NSString *documentsPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)[0];
NSString *path = [documentsPath stringByAppendingPathComponent:@"cars.sqlite"];
FMDatabase *database = [FMDatabase databaseWithPath:path];
[database open];
[database executeUpdate:@"create table if not exists cars (data blob)"];
[database executeUpdate:@"insert into cars (data) values (?)", data];
You can read this from the database at a later point (using sqlite3_column_blob
and sqlite3_column_bytes
, or, again, using FMDB makes your life easier):
FMResultSet *rs = [database executeQuery:@"select data from cars"];
while ([rs next])
{
NSData *carData = [rs dataForColumnIndex:0];
Car *carFromDatabase = [NSKeyedUnarchiver unarchiveObjectWithData:carData];
NSLog(@"%@, %@, %d", carFromDatabase.make, carFromDatabase.model, carFromDatabase.year);
}
Having shown you how you could do store the object as a blob, I'd discourage you from doing that. (lol). I'd encourage you to create a SQLite data model that mirrors the object model, and store the individual properties in separate columns of the table.
Or better, use Core Data.
Upvotes: 3
Reputation: 2819
Have you had a look at core data link
It makes working with sqlite very easy and is supported on Mac and iOS.
Upvotes: 1
Reputation: 25006
You can use the VARBINARY(MAX) field type in SQL Server, if you like. You can store any type of object in there, up to 2 GB in size.
To access it, you can use ADO.NET - something like this:
object yourMysteryObject = (whatever you like it to be);
MemoryStream memStream = new MemoryStream();
StreamWriter sw = new StreamWriter(memStm);
sw.Write(yourMysteryObject);
SqlCommand sqlCmd = new SqlCommand("INSERT INTO TableName(VarBinaryColumn) VALUES (@VarBinary)", sqlConnection);
sqlCmd.Parameters.Add("@VarBinary", SqlDbType.VarBinary, Int32.MaxValue);
sqlCmd.Parameters["@VarBinary"].Value = memStream.GetBuffer();
sqlCmd.ExecuteNonQuery();
Upvotes: 0