Repository Save vs Update

One thing that has bugged me to no end (yes, I'm easily irked) is the concept of Save vs. Update. People seem to always follow the CRUD (Create, Read, Update, Delete) mentality even when dealing with objects. Take a class following the Repository pattern:

public class Repository

{

    public static void Update(DomainObject obj)

    {

        // Find the information to update

        // Update the values

    }

 

    public static void Save(DomainObject obj)

    {

        // Add a new item to the repository

        // Update the values

    }

}

So fairly straight forward. If I have a DomainObject that I have to make changes to then I call Repository.Update(). If I want to add a new item to the repository then I call Repository.Save() but that means that somewhere outside my Repository I'm determining if I need to update or save? Isn't it the same. A variation on the Repository could be calling the Save method Add instead but the end result is the same. I don't believe that any object outside of the Repository should have to determine whether or not it's a new item or updating an existing one. Maybe what I really want to do is this:

public class Repository

{

    public static void Update(DomainObject obj)

    {

        // Determine if this is new or not

        // If new, add a new item otherwise

        // find the existing item and update the values

    }

 

    private static void Add(DomainObject obj)

    {

        // Add a new item to the repository

    }

}

 

So now I'm only exposing the Update method to any callers to the Repository and let the Repository make the decision whether or not this is a new item or not. The Add is hidden and maybe I have a private method to do a find based on an identity in the DomainObject. In some cases (like if my Repository is a facade to a DBMS) then I really just need a new id back from the add then I could do a Save using that information which would transmogrify my Repository into something like this:

 

public class Repository

{

    public static void Update(DomainObject obj)

    {

        // Determine if this is new or not

        if(!FindById(DomainObject.Id))

        {

            DomainObject.Id = Add();

        }

 

        // Now update the item using a Mapper

        Mapper.Save(DomainObject);       

    }

 

    private static long Add()

    {

        // Add a new item to the repository

        // could be in-memory or a write to a DBMS

        return SomeMethodToAddRecordInDBMS();

    }

 

    private static bool FindById(long id)

    {

        // Do some kind of find of an item with the same identity

        return SomeMethodToFindRecordInDBMS(id);

    }

}

 

Does this make sense or does this just fly in the face of a Repository as well as falling into a Transaction script? Would like to see some concrete examples of using a Repository as I've only seen a couple and what we've been doing may or may not be on track.

5 Comments

  • I think you're on the right path. Generally speaking, domain objects usually have some sort of unique key (be it an auto-generated int or a GUID). You can use this to determine whether to insert or update the object. FWIW, most O/R mappers figure this stuff out on their own anyways, so the 'Mapper.Save(DomainObject);' you reference would be able to figure it out without your doing any work. If that's not the case, just check the primary key field(s) and call your update or insert methods as required.



    (btw, your blog is quite informative. I've been looking around for Sharepoint info recently, and subscribed to your feed a while ago. Good stuff. And you're in Calgary too!)

  • That looks like a good Repository to me. It is responsible for linking an object to a persistence medium. It also has to tell the medium what to do (get object, save object). You are, however, putting the decision of add or update in the application layer that calls the Repository, so your application layer would have to know if this object already exists or not and call the appropriate method.



    Another way to do it would be to have some sort of marker where the presistence layer could make the decision of add or update (either way, it is "persist").



    I think the decision would depend on the situation.

  • Personally, I have never seen a need for a add / update, just a Save.



    If you think about serialization, you are usually just saving your current object state. Like writing to a file, would you need to determine if you need to write to a new file or not? Well that is logistics of the repository implementation, not something the caller should be concerned with, they just should request to save the current state of the object.



    Call it what you want, I prefer Save over update (even though behind the scenes you may have two methods, update and add) .. just my personal preference

  • Nothing additional to add, just another vote for a single Save() method over an Add and Update. IMO, the API should be as simple as possible so shouldn't make developers think about if its a new or old object. They should just pass it along telling the repository to save, and the repository should do all the work of figuring out if its should save, update, and whatever else.

  • I think the use of Create and Update make sense because the business layer may and usually does treat new and existing object different. Take the creation of a new user. The business layer may need to collect additional information for a new user, but not an existing user. I know this is an old post but I came across it while trying to find info on NTiers a CodeSmith template.

Comments have been disabled for this content.