Common method for saving and updating on Entity Framework

This problem has been bugging me for some time now. One of the things that I miss the most from NHibernate when I’m working with EF is the SaveOrUpdate methods. Once you lose that, you realize just how much you loved it in the first place. So, I set out to make my EF repositories to use one of those. My initial approach was rather simple and really close to what you can find here or here, so I basically came out with this:

public T SaveOrUpdate(T item)
{
 if (item == null)
  return default(T);

 var entry = _internalDataContext.Entry(item);

 if (entry.State == EntityState.Detached)
  if (item.Id != null)
   TypeDbSet.Attach(item);
  else 
   TypeDbSet.Add(item);
 
 _internalDataContext.SaveChanges();
 return item;
}

This is a neat idea and it works for most of the cases, with one tiny issue. I was working with an external API and I was caching the objects received on my calls and since these objects had their own keys, I was using those keys on my DB. So, I had a Customer class, but the Id property was set when I was about to insert and since our method uses the convention that if it has an Id, it was already saved, then the repo would just attach it to the change tracker but the object was never saved! Boo! Well, no panic, my repo also has a method called GetOne which receives an Id and returns that object, so I added that into the soup and got this:

public T SaveOrUpdate(T item)
{
 if (item == null)
  return default(T);

 var entry = _internalDataContext.Entry(item);

 if (entry.State == EntityState.Detached)
 {
  if (item.Id != null)
  {
   var exists = GetOne(item.Id) != null;

   if (exists)
    TypeDbSet.Attach(item);
   else
    TypeDbSet.Add(item);
  }
  else 
   TypeDbSet.Add(item);
 }
 
 _internalDataContext.SaveChanges();

 return item;
}

Now, if you think about it, how would you update an object?

  • Check if the object already exists on the DB
  • If it’s there.. update it!
  • If it’s not there.. insert it!

As you can see, Check involves GetOne. Now, if you are thinking that you don’t want an extra DB call, there is always a solution…

public T SaveOrUpdate(T item, bool enforceInsert = false)
{
 if (item == null)
  return default(T);

 var entry = _internalDataContext.Entry(item);

 if (entry.State == EntityState.Detached)
 {
  if (item.Id != null)
  {
   var exists = enforceInsert || GetOne(item.Id) != null;

   if (exists)
    TypeDbSet.Attach(item);
   else
    TypeDbSet.Add(item);
  }
  else 
   TypeDbSet.Add(item);
 }
 
 _internalDataContext.SaveChanges();

 return item;
}

Granted, is not fancy, but gets the job done and doesn’t requires many changes. If you pass the enforceInsert flag, means you are certain that the object you’re saving requires an insert, so it will have an Id, but you know is not there. Just what I was doing!

Do you have any other way of doing this? Do you think this is wrong? Feel free to comment and let me know!

Consuming web services and notifying your app about it on Objective C

Since almost the beginning of my exploits as an iOS developer I’ve been working on several apps consuming web services and one big problem has been notifying different areas of my app that certain event has been updated. My first genius idea was to create my own home brew of notifications using the observer pattern. It wasn’t all that bad, but then a while later I realized that I was reinventing the wheel, so I resorted to the one and only NSNotificationCenter.

Enter NSNotificationCenter

According to Apple on the docs for the notification center, this is the definition:

An NSNotificationCenter object (or simply, notification center) provides a mechanism for broadcasting information within a program. An NSNotificationCenter object is essentially a notification dispatch table.

So, this was my observer! How does it work you say? Let’s get to it! But before, let’s get into context. What I have is a class called ServiceBase which is the base class (duh!) for all classes consuming services. The interface definition for the class looks a bit like this…

 @interface ServiceBase : NSObject<ASIHTTPRequestDelegate>
  - (void) performWebServiceRequest: (NSString*) serviceUrl;
  - (void) triggerNotificationWithName: (NSString*) notificationName andArgument: (NSObject*) notificationArgument;
  - (NSString*) getServiceBaseUrl;
 @end
 

The class has been simplified and the actual class has a few other things that depend more on how I work, but you get the point. However, given the idea of this post, I’m going to concentrate more on the notification side of the class. However, we do need to get some sort of example here going on and to get that done, let’s take a look on the performWebServiceRequest method.

- (void) performWebServiceRequest: (NSString*) serviceUrl
{
    if (!self.queue) {
        self.queue = [[NSOperationQueue alloc] init];
    }
    
    NSURL *url = [NSURL URLWithString: serviceUrl];
    ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
    [request addRequestHeader:@"accept" value:@"text/json"];
 
 [requestion setCompletionBlock: ^{
  //this will keep the self object reference alive until the request is done
  [self requestFinished: request];
 }];
 
    [self.queue addOperation: request];
}
 

Now, we have this simplified method that creates a request, sets the requestFinished method as the completion block and queues up the request. Now, I said I would focus on the notifications, but one thing to consider here:

 [requestion setCompletionBlock: ^{
  //this will keep the self object reference alive until the request is done
  [self requestFinished: request];
 }];
 

Keep in mind, that this sentence will preserve the reference to self until the request is finished, so it’s not autoreleased by ARC, however, the way I use services on my app, each service works as a singleton (or quite close to that) and keeping the reference is not a problem because you are not creating one new instance of each service class every time you make a request. This also solves an issue with ASIHttpRequest loosing the reference to the delegate before the service is complete, however, that’s a story for another day. Now, moving on the the end of the request…

- (void)requestFinished:(ASIHTTPRequest *)request
{
    JSONDecoder* decoder = [[JSONDecoder alloc] init];
    NSData * data = [request responseData];
    NSArray* dictionary = [decoder objectWithData: data];

    for (NSDictionary* element in dictionary) {
  [self triggerNotificationWithName: @"ItemLoaded" andArgument: element];
    }
}
 

When the request is finished, it will only convert the data received, notice that this is a simple scenario, and make a notification that an Item has been loaded using the [triggerNotificationWithName: andArgument] method. Now, into the actual notification method…

- (void) triggerNotificationWithName: (NSString*) notificationName andArgument: (NSObject*) notificationArgument
{
    NSNotificationCenter * notificationCenter = [NSNotificationCenter defaultCenter];
   
 if ( notificationArgument == nil )
 {
  [notificationCenter postNotificationName: notificationName  object: nil];
 }
 else
 {
  NSMutableDictionary * arguments = [[NSMutableDictionary alloc] init];
  [arguments setValue: notificationArgument forKey: @"Value"];
  [notificationCenter postNotificationName: notificationName  object:self userInfo: arguments];
 }
}
 

Now, we only need to subscribe to a notification and retrieve the value which is very simple, take this example inside a UIViewController:

- (void) viewDidLoad
{
 NSNotificationCenter * notificationCenter = [NSNotificationCenter defaultCenter];
 [notificationCenter addObserver: self selector: @selector(authenticationFinished:) name:@"AuthenticationCompleted" object: nil];
}

- (void) itemLoadedNotificationReceived: (NSNotification*) notification
{
 NSDictionary* itemLoaded = [notification.userInfo valueForKey: @"Value"];
    // Do something with the item you just loaded
}
 

In the itemLoadedNotificationReceived method the app will receive a notification when each item is loaded. This may not be the best example, because when you’re loading several items, they normally go into a cache to be loaded from a UITableView afterwards, but this idea should get you going.

Do you use a different approach? Do you normally use it like this? Well, if you have anything at all to say, feel free to leave it in the comments!

The status of Lucene2Objects

After some time without being able to work into it, I’ve managed to put some time into Lucene2Objects again. First thing I did on my last session was to work on separating the attributes from the actual Lucene2Objects project for a very simple reason that was brought to my attention by a fellow user of the library. Currently if you want to annotate your entities on your domain project, you will have to import the Lucene2Objects library into the domain project, thus adding a dependency on the library and on Lucene .NET and on Lucene Contrib project which is used for importing several analyzers and any other dependencies these might bring along. Now, for a domain project, which is supposed to have as less dependencies as possible, this is very heavy duty, hence the need for a separation (of concerns if you will).

The basic idea that I followed on this new update was to separate the project into 2 different libraries, one very light containing the attributes with no dependencies at all and the actual library. Obviously this will make me create another package, which I will do it very soon, but will hopefully allow people to integrate easily with Lucene2Objects .

My next step is working over adding collection support for Lucene2Objects . I have a few ideas on this and I hope a new version should be done soon, but there is nothing worth pushing now. Hopefully, I will manage to put more time into this from now on, so feel free to let me know if there’s something you’d like to see on Lucene2Objects !