Mario
Mario

Reputation: 65

SQL and oop in objective-c

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

Answers (3)

Rob
Rob

Reputation: 437592

A couple of thoughts:

  1. 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.

  2. 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);
      }
      
  3. 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

sbarow
sbarow

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

Nathan
Nathan

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

Related Questions