在db4o中同时防止同一对象返回

时间:2010-08-12 09:21:36

标签: db4o

我在asp.net Web应用程序中使用db4o,正如您所知,db4o返回的是未订购的对象列表。

在我的网站上,我运行一个查询并获取结果中的最后一个对象并对其进行处理(一些处理然后更新其中一个字段)。

我的问题是,如果我在处理该对象时,如果另一个用户再次到达并再次运行该查询,则同一对象将返回给他,并且两个用户都获得相同的对象。

我不想让这种情况发生。我该如何防止它发生?

2 个答案:

答案 0 :(得分:1)

不确定DB4O是否提供了这样的开箱即用,但可以自己实现某种悲观锁定,从而不会返回相同的对象或以只读模式返回。您需要维护正在编辑的对象列表,并在每次返回对象时检查此列表。但是有一些问题,例如用户离开和对象陷入'编辑模式'等等。你通常需要某种服务,涉及一个超时机制来处理它。它会变得复杂。

或乐观地做到,例如让两个用户编辑它但只保存第一个用户的更改,并在尝试保存时向第二个用户发出警告。通常用时间戳完成。

修改

为了提供一个具体的例子,这个C#代码提供了一种“锁定”对象的基本方法,因此它不会每次都被带回来。在现实生活中,它会更复杂。

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" }
            };
        }
    }
}

答案 1 :(得分:0)

您可以使用db4o中内置的带外消息传递支持来实现基本锁定系统。上面的Grant列表可以在db4o服务器上实现。客户端向服务器发送消息“我想编辑对象x”,服务器尝试将对象放入其列表中。如果成功,它将回复“是,继续”消息,否则它可以回复“否,稍后再试”。当客户端完成编辑时,它会向服务器发送一条消息,说“我已完成对象x'。