tags:

views:

30

answers:

1

hi,

i am using db4o in a asp.net web application, as you know when db4o returns a list of objects they are not ordered.

in my website, i run a query and get the last object in the results and work on it (some processing and then update one of its fields).

my question is, if when i am working on that object , if another user arrive and run that query again , the same object returns to him, and both of users get same object.

i don't want to allow this to happen. how can i prevent it from happening ?

+1  A: 

Not sure if DB4O provides anything like this out of the box, but could implement some kind of pessimistic lock yourself, whereby the same object either won't be returned or will be returned in a read-only mode. You'd need to maintain a list of objects being edited, and check this list each time you return your objects. But then there are problems such as users leaving and object getting stuck in 'edit mode' etc. You generally need some kind of service involving a timeout mechanism to deal with that. It can get complicated.

Or do it optimistically, e.g. let both users edit it but only save changes from the first user, and give the second user a warning when they try to save it. Usually done with a timestamp.

Edit

To provide a concrete example, this C# code provides a basic way to 'lock' an object so it isn't brought back every time. In real life it will be more complex though.

using System;
using System.Collections.Generic;
using System.Linq;

namespace ListTest
{
    class Program
    {
        static void Main(string[] args)
        {
            DataAccess dataAccess = new DataAccess();

            // get objects from database
            List<MyThing> things = dataAccess.GetThings();
            MyThing thingToWorkOn = things[things.Count-1];
            printThingList(things);

            // lock the object to work on
            dataAccess.LockThing(thingToWorkOn);

            // someone else gets the list - doesn't include thing being edited
            List<MyThing> moreThings = dataAccess.GetThings();
            printThingList(moreThings);

            // edit the object
            thingToWorkOn.Name = "Harrold";
            thingToWorkOn.Name = "Harry";

            // save the object and unlock it
            dataAccess.Save(thingToWorkOn);
            dataAccess.UnlockThing(thingToWorkOn);

            // now when someone else gets the list, includes all objects
            List<MyThing> evenMoreThings = dataAccess.GetThings();
            printThingList(evenMoreThings);
        }

        static void printThingList(List<MyThing> things)
        {
            Console.WriteLine("* Things *");
            things.ForEach(x => Console.WriteLine(x.Name));
            Console.WriteLine();
        }
    }

    // The objects you're working with.  Could just use 'object' or some interface.
    class MyThing : IEquatable<MyThing>
    {
        public string Name { get; set; }

        public bool Equals(MyThing other)
        {
            return other.Name == this.Name;
        }
    }

    // Class to get objects from database.
    class DataAccess
    {
        // simple list to store 'locked' objects
        private static List<MyThing> lockedThings = new List<MyThing>();

        // Get all objects except the locked ones
        public List<MyThing> GetThings()
        {
            List<MyThing> thingsFromDatabase = LoadThingsFromDatabase();

            var nonLockedThings = (from thing in thingsFromDatabase
                                   where !lockedThings.Contains(thing)
                                   select thing
                                    ).ToList<MyThing>();

            return nonLockedThings;
        }

        // lock an object so it can't be seen by anyone else
        public void LockThing(MyThing thingToLock)
        {
            lockedThings.Add(thingToLock);
        }

        // unlock an object
        public void UnlockThing(MyThing thingToLock)
        {
            lockedThings.Remove(thingToLock);
        }

        public void Save(MyThing thing)
        {
            // save to database
        }

        // dummy method to give us some objects
        private List<MyThing> LoadThingsFromDatabase()
        {
            return new List<MyThing>() {
                new MyThing(){ Name="Tom" },
                new MyThing(){ Name="Dick" },
                new MyThing(){ Name="Harry" }
            };
        }
    }
}
Grant Crofton
what is pessimistic lock ?
It's not a DB4O thing, it's something you have to to yourself. This explains a little about it: http://www.agiledata.org/essays/concurrencyControl.html#PessimisticLocking. That article is about databases, but the same principle applies regardless.
Grant Crofton
Basically when the first user starts working on an object, you put it in a list, perhaps (in C#) 'List<object> LockedObjects'. When someone else want's to use an object, you check if it's in that list - if it is, they aren't allowed to use it, or they can only read it and not update it. When the first guy is done editing, the object is removed from that list.
Grant Crofton
Thanks Grant, do we have anything on the databases to do this List<Object> work ? is there any feature in DBMS's to do this ? like lock or something like that
The thing I'm talking about, you have to do yourself. What language are you using?
Grant Crofton
i use C# 3.5 with Asp.net
Check out the code example in the edited answer, that might give you some idea
Grant Crofton
Thanks i got it, Thank You